The passmcp ecosystem¶
What exists, what each piece is for, and what is not yet released. Nothing on this page is aspirational unless it says so: a map that lists things which do not exist is worse than no map, because it costs a reader the trip.
The family¶
Every repository around passmcp, generated from internal/ecosystem so that
this table and the manifest cannot disagree. make ecosystem-verify fails the
build when they do.
Released¶
| Repository | Licence | Lockstep | What it owns |
|---|---|---|---|
passmcp |
GPL-3.0-only | yes | The engine, every check, and the three peer surfaces: CLI, TUI and the embedded local web UI. |
passmcp-reporting |
Apache-2.0 | yes | The attestation predicate, its JSON Schema and the offline verifier, as a module with no dependencies; the report schema, the renderers and the rubric as data follow when a consumer needs them. |
passmcp-server |
GPL-3.0-only | yes | An MCP server exposing passmcp's diagnostics as read-only tools, so an agent can evaluate a server, or check an attestation about one, from inside the editor. |
passmcp-action |
Apache-2.0 | yes | The GitHub Action wrapping the published image by digest, and a GitLab CI template. |
passmcp-graph |
GPL-3.0-only | yes | A local graph of which agents use which MCP servers, which tools those servers expose and which identities reach them, built from passmcp's attestations, reports and MCP client configurations, queried offline and gated by policy in CI. |
passmcp-registry |
AGPL-3.0-only AND CC-BY-4.0 | yes | The tooling for a signed public scorecard of the remote servers in the MCP Registry: each checked read-only and without credentials by a pinned passmcp release, every result an offline-verifiable attestation, and anything that would expose a vulnerability withheld for its owner first. No run has been published yet. |
passmcp-lsp |
Apache-2.0 | yes | A language server over MCP artefacts — server.json, tool schemas, client configuration, passmcp policy and attestation files — with check-id hover from the guidance catalogue. |
passmcp-census |
CC-BY-4.0 | yes | The reliability census of the MCP Registry's remote servers: the methodology, the disclosure log and the command that reproduces the figures. No edition has been published yet. |
satellion.com |
GPL-3.0-only | yes | The public site at satellion.com, built with SSG against passmcp's latest release: the home page, the manual and a sample report passmcp generates. |
passmcp-sdk-go |
Apache-2.0 | yes | MCP client and server SDK for Go covering revisions 2025-06-18 through 2026-07-28 (stdio and Streamable HTTP, OAuth 2.1 with PKCE, SEP-2164, SEP-2549, stateless server/discover, read-only defaults) and offline passmcp attestation verification. |
passmcp-sdk-python |
Apache-2.0 | yes | MCP client and server SDK for Python covering revisions 2025-06-18 through 2026-07-28 (stdio and Streamable HTTP, OAuth 2.1 with PKCE, SEP-2164, SEP-2549, stateless server/discover, read-only defaults) and offline passmcp attestation verification. |
passmcp-sdk-java |
Apache-2.0 | yes | MCP client and server SDK for Java covering revisions 2025-06-18 through 2026-07-28 (stdio and Streamable HTTP, OAuth 2.1 with PKCE, SEP-2164, SEP-2549, stateless server/discover, read-only defaults) and offline passmcp attestation verification. |
passmcp-sdk-cpp |
Apache-2.0 | yes | MCP client and server SDK for C++20 covering revisions 2025-06-18 through 2026-07-28 (stdio and Streamable HTTP, OAuth 2.1 with PKCE, SEP-2164, SEP-2549, stateless server/discover, read-only defaults) and offline passmcp attestation verification. |
passmcp-sdk-typescript |
Apache-2.0 | yes | MCP client and server SDK for TypeScript covering revisions 2025-06-18 through 2026-07-28 (stdio and Streamable HTTP, OAuth 2.1 with PKCE, SEP-2164, SEP-2549, stateless server/discover, read-only defaults) and offline passmcp attestation verification. |
passmcp-sdk-rust |
Apache-2.0 | yes | MCP client and server SDK for Rust covering revisions 2025-06-18 through 2026-07-28 (stdio and Streamable HTTP, OAuth 2.1 with PKCE, SEP-2164, SEP-2549, stateless server/discover, read-only defaults) and offline passmcp attestation verification. |
The ssg surfaces¶
Every web surface built here is generated by ssg
from a theme in the SSG theme suite.
That is an invariant, not a habit: make ssg-check fails the build when a
page appears outside a layout, when a configuration stops matching this
table, or when CI would install an ssg older than the theme requires.
| Surface | Theme | Vendored from | Layouts | Output | Embedded |
|---|---|---|---|---|---|
web-shell |
passmcp | e32f60c (min ssg 0.0.56) |
web/_layouts |
internal/web/dist |
yes |
The layouts are vendored so the site builds in CI with nothing but the ssg
binary. 9 file(s) deliberately differ from the theme, each with a recorded
reason — a declared delta is a patch on its way upstream, and an undeclared
one is a fork nobody decided to make. The list is in
internal/ecosystem/sites.go.
Considered and rejected¶
| Repository | Why not |
|---|---|
passmcp-gateway |
Fourteen incumbents, two of them free and open source, one of them AWS. Being in the data path would also convert passmcp from a tool that touches nothing into a production dependency trusted with traffic. |
passmcp-wasm |
CORS blocks a browser build against most servers. A build target, not a repository. |
passmcp-proxy |
The gateway again under another name: in the data path is in the data path whether it only watches or also rewrites (ADR 0007). A rewriting shield would also judge by classifier rather than cite the request that showed the property (ADR 0002). Live inspection is the official MCP Inspector's job. |
passmcp-fuzz |
An adversarial mode in its own repository, which ADR 0008 rules out behind a flag and behind a verb alike: the read-only posture is what lets a security team approve passmcp. Resilience is already a phase of the check, and passmcp fuzzes its own parsers. |
Decisions in that table that were once made the other way, recorded here rather than reversed quietly — a reversed decision with its history intact is worth more than a tidy page:
passmcp-serverwas previously reserved for the public site and hosted diagnostic. It is listed above as an MCP server instead, because a repository with that name containing no MCP server misleads everyone who finds it. The public site moved to its own repository, satellion.github.io, which serves satellion.com, on 26 Sep 2026. The drift that kept it here is closed from that side: its build reads the check count, score, ledger and evidence from the passmcp release it builds against and fails when the page disagrees. The embedded shell stays here,go:embeded, under the same count gate.passmcp-lspwas considered and deliberately deferred, on the grounds that a language server is a large permanent surface with no demand behind it. That reasoning holds for a language server over MCP server source and not for one over MCP artefacts —server.json, tool schemas, client configuration, and passmcp's own policy and attestation files, where hovering a check id can return the guidance catalogue's remediation. It is listed above at that narrower scope.passmcp-registrywas once rejected as an index of MCP servers: contested by the official registry, the container catalogue and four directories, two of which already publish a score, with the advice to "supply the signal they display instead". The repository that now carries the name is that advice taken: not an index but a signed, per-server scorecard of the official registry's remote servers, each result an attestation anyone can verify offline. The objection to an index stands.passmcp-lspandpassmcp-censuswere outside the lockstep. The census was held out because a census edition is not a build of the tool and binding it would force a no-op tool release every quarter; the language server because editor marketplaces keep their own cadence. The owner decided on 29 Sep 2026 that the whole family carries one version, including both: a reader should never have to ask which version of which piece they are looking at. The cost that argument named is accepted, as it already was for the site (see the version rule). Neither had been tagged, so on the same day the owner decided both skip 0.0.1 and first ship at the family's next version, 0.0.2: an untagged changelog section is not a release, and a member joining the lockstep joins at the family's version.passmcp-graphandpassmcp-registryhave no recorded archive criterion. Every other satellite states when it should be archived; for these two the owner has not yet said, and their rows say so rather than carry a guess.
Today: three surfaces, one engine¶
Everything below ships from passmcp itself.
| Surface | Entry point | What it is |
|---|---|---|
| CLI | passmcp check |
The diagnostic as a command. Text, JSON, NDJSON, Markdown or HTML. |
| TUI | passmcp tui |
The same run, driven interactively, for picking a tool and watching a phase. |
| Web | passmcp serve |
The same run in a browser, on the operator's own machine. |
The three are not three implementations. internal/engine owns a run:
RunSpec carries the intent, Run executes it, a Sink receives events.
Each surface builds a spec and presents the events.
That is enforced rather than intended. cmd/parity_test.go fails the build
when a flag configures a run but carries no RunSpec field, because a
capability reachable only through a flag is one the TUI and the web UI can
never have. See ADR 0005 for
how the hosted surface inherits the same guarantee.
Published artefacts¶
Every release produces the same set, from one tag.
| Artefact | Where | Provenance |
|---|---|---|
| Binaries | GitHub Releases | SHA256SUMS, keyless cosign signature, SLSA provenance |
| Container image | ghcr.io/sebastienrousseau/passmcp |
Multi-arch, cosign-signed, digest-addressable |
| SBOM | Attached to each release | CycloneDX, generated by Syft |
| Packages | deb, rpm, AUR, Homebrew cask, Nix | Built from the release archives — see pkg/ |
Verification instructions, including the cosign certificate identity, are in
pkg/VERIFY.md. There is no KEYS.asc: signing is
keyless, so there is no long-lived key to publish, and the thing to check is
the workflow identity in the certificate rather than a key fingerprint.
The version rule¶
Every repository in the ecosystem always carries the same version.
This is a hard rule, not a convention, and it exists because ambiguity about which build of the tool is behind a hosted service is the expensive kind of ambiguity for a security diagnostic.
- One source.
passmcp's tag is the only place a version is authored. Satellites never choose their own. - Propagation is automated up to the tag. A release fires
repository_dispatchat a satellite, which writes the version and pins the image by digest on itsfeat/vX.Y.Zbranch. A person reviews and merges that pull request and pushes the signed tag. - Drift is a red check. Each satellite carries a required
Version Lockstepstatus check comparing its version to the latest publishedpassmcprelease. Disagreement blocks the merge.
The cost is real and accepted: a typo on the site cannot ship as a site-only
patch. It bumps the whole ecosystem, including a passmcp release in which
nothing changed. A no-op release is cheap and automated; not knowing what is
deployed is not.
All three rules are in force. How each repository meets them differs, and
is stated here as it is, not as it will be. passmcp-action and
passmcp-server follow passmcp's release as rule 2 describes: the release
fires repository_dispatch at them, and each one's sync workflow commits the
version and the image digest onto its feat/vX.Y.Z branch, or opens
sync/vX.Y.Z when that branch does not exist. It does not merge or tag; the
owner does, after the pull request's checks are restarted (commits made with
the workflow's own token start no workflows). Each one's Version Lockstep
check refuses a version that is not passmcp's latest. passmcp-reporting runs the other way, because passmcp
imports it: it tags first, so that passmcp's go.mod can name the version,
and its lockstep check allows it to be exactly one release ahead of passmcp's
latest and nothing else. It has no dispatch workflow: nothing in it reacts to
passmcp's release.
The rule binds every repository in the family: every row above says yes in
its Lockstep column, and internal/ecosystem refuses a row that does not.
The dispatch in release.yml reaches the three repositories named above
today. passmcp-graph, passmcp-registry, passmcp-lsp, passmcp-census
and the website carry the version in their own CHANGELOG.md; the dispatch
does not reach them yet, and adding them needs the dispatch token's scope
widened to them, which is a repository setting rather than a change here.
Where to go next¶
- User manual — installing, running, reading a report
- API reference — the Go packages the CLI is built on
- DEVELOPMENT.md — toolchain and every CI gate reproduced locally
- docs/architecture.md — how a run is actually put together