The passmcp ecosystem¶
What exists, what each piece is for, and what is only planned. 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.
Shipping¶
| 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. |
satellion.com |
GPL-3.0-only | no | 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-action |
Apache-2.0 | yes | The GitHub Action wrapping the published image by digest, and a GitLab CI template. |
Planned¶
These do not exist yet. They are recorded so the layout cannot drift silently once they do, and so nobody goes looking for them. Every row states the boundary that forces a separate repository and the criterion for archiving it.
passmcp-lsp¶
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.
- Licence Apache-2.0 · go · Lockstep no
- Why separate Editor embedding. It ships inside editors and extension marketplaces whose licensing and release cadence are not passmcp's; the extensions live in its own editors/ directory rather than a repository each.
- Archive when The guidance hover goes unused. Scoped so that cutting it costs one repository and no capability.
passmcp-census¶
The published reliability census: the dataset, the methodology, the disclosure log and the reproduction command.
- Licence CC-BY-4.0 · data · Lockstep no
- Why separate Licence and cadence. A GPL repository cannot cleanly carry a CC-BY dataset, and a quarterly data release has no business sharing a version with a fortnightly tool release.
- Archive when The census is not repeated on schedule. Delete it rather than leave a stale dataset presented as current.
The ssg surfaces¶
Both web surfaces are 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-registry |
Contested by the official registry, the container catalogue and four directories, two of which already publish a score. Supply the signal they display instead. |
passmcp-wasm |
CORS blocks a browser build against most servers. A build target, not a repository. |
Two names in that table are still open questions, recorded here rather than settled quietly:
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.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. The original objection is kept because a reversed decision with its history intact is worth more than a tidy page.
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 automatic. A release fires
repository_dispatchat each satellite, which writes the version, pins the image by digest, tags itself and deploys. - 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: the first satellites exist. Two facts about
them are worth stating. passmcp-action and passmcp-server follow passmcp's release
exactly as rule 2 describes: the release fires repository_dispatch at
them, each pins the new image by digest, and 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. The dispatch reaches it too, as the signal that the release it tagged
for has shipped.
The rule binds every repository whose Lockstep column says yes. Two rows
are deliberately outside it. passmcp-census publishes a dataset, and a census
edition is not a build of the tool — binding them would force a no-op tool
release every quarter. passmcp-lsp follows editor and marketplace cadences
that are not this project's. Anything that embeds or reports a passmcp version
stays in lockstep, because that is the ambiguity the rule exists to remove.
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