A source-mirroring build hub for Model Context Protocol servers. One repo that vendors the source of every MCP it tracks and builds container images for the ones upstream doesn't publish.
Small community MCP servers can disappear or stop shipping images. This keeps the set self-sufficient:
- Archive —
vendor/<name>/holds each MCP's real source at a pinned release. If an upstream repo vanishes, the code is still here (auditable, patchable). - Build the gaps — MCPs that ship no image (
build: trueinfleet.yaml) are built and pushed toghcr.io/<owner>/<name>. - Rebuild insurance — archive-only entries (
build: false) use upstream's image today; if that image ever disappears, flipbuild: trueand it rebuilds from the vendored source.
One workflow, sync (weekly + manual):
- Resolves each MCP's latest upstream release and re-vendors its source into
vendor/<name>/only when the ref differs (recordsref+commitinfleet.yaml, commits, pushes). - In the same run, builds every
build: trueentry that changed and publishesghcr.io/<owner>/<name>:<ref>+:latest, with SBOM and build-provenance attestation.
Run it with force_build: true to rebuild all build: true images regardless of change
(bootstrap the first image, or refresh base images after a CVE).
Edit fleet.yaml:
- name: something-mcp
upstream: https://github.com/owner/something-mcp
ref: v1.2.3 # vendor-sync auto-bumps this
build: false # true -> build+publish; add `dockerfile:` if upstream ships none
image: ghcr.io/owner/something-mcp:v1.2.3 # informational, for build:false
# pin: v1.2.3 # optional: freeze; vendor-sync won't auto-bumpThen run the sync workflow (or wait for the weekly run).
Some MCPs don't exist upstream at all — we write them here. Put the source under
mcps/<name>/ (with its own Dockerfile) and add a local: true entry:
- name: something-mcp
local: true # source in-repo under mcps/ (vendor-sync skips it)
ref: v0.1.0 # hand-bumped; tag when the source changes
build: true
context: mcps/something-mcp
dockerfile: mcps/something-mcp/DockerfileA push touching mcps/** rebuilds the changed first-party image. Bump ref when
you cut a new version.
mcps/ also holds adopted MCPs: upstreams that went dormant while we still need
fixes. Moving one out of vendor/ is deliberate — a patch left in vendor/ is silently
reverted the next time sync.sh re-vendors that ref. An adopted MCP keeps its upstream
LICENSE and adds a FORK.md recording the origin commit and every local change
(see mcps/jellyfin-mcp/).
fleet.yaml # the manifest (source of truth)
vendor/<name>/ # mirrored upstream source (committed archive)
mcps/<name>/ # first-party MCP source we author (local: true)
dockerfiles/<name>.Dockerfile # for build:true MCPs whose upstream ships no Dockerfile
scripts/sync.sh # vendoring logic (skips unchanged; writes .changed)
.github/workflows/ # sync.yml (vendor + build), renovate.yml
vendor-syncpushes tomainunreviewed. To add a checkpoint, protectmainand switch the workflow to open a PR instead.- This repo's own glue (workflows, scripts, Dockerfiles) is MIT. Everything under
vendor/retains its upstream project's license, as does any adopted MCP undermcps/.