mcp-vault CLI
The command line behind the GitHub Action and pre-commit hook:
an MCP config scanner for repositories, and a supply-chain gate for the
Model Context Protocol servers on your own machine. Package
@froggychips/mcp-vault, repository
mcp-skills-vault.
In a repository: check
# The MCP configs this repository commits, one pass, one exit code.
# Offline: no network call, nothing from your home directory.
npx -y @froggychips/mcp-vault check
# Stricter, or for a pipeline:
npx -y @froggychips/mcp-vault check --strict # warnings fail too
npx -y @froggychips/mcp-vault check --sarif > mcp.sarif # each finding on its config line
With no paths it reads .mcp.json (Claude Code),
.vscode/mcp.json (VS Code) and .cursor/mcp.json
(Cursor). In one decision it looks at pins and hashes of known packages,
stored advisories, launches with no exact version, overridden package
sources, lookalike names (typosquatting), plain-text secrets (the value is
never printed), what the servers of one config can do together, and stored
tool-description scans (tool poisoning). Exit 0 clean,
1 something fails, 2 a config, the policy or the
arguments could not be read. This is what the
Action and the
pre-commit hook run.
On your machine: status
# One command. No network calls: every claim comes from evidence
# already on disk, and the report says so rather than implying
# it was checked just now.
npx -y @froggychips/mcp-vault status
# Then, when you want a live answer or more detail:
npx -y @froggychips/mcp-vault verify --installed # re-hash what your hosts launch
npx -y @froggychips/mcp-vault explain <name> # why one entry is allowed or denied
npx -y @froggychips/mcp-vault scan --cwd ./my-project # what to install for this stack
npx -y @froggychips/mcp-vault audit --strict # every drift and scope finding
# Prefer it on PATH? Drop the npx prefix after this.
npm i -g @froggychips/mcp-vault
status reads the host configs on this machine — Claude Code,
Claude Desktop, Cursor, VS Code, Codex — so its answer depends on whose
machine runs it; check reads only the files in the repository.
Servers are matched by artifact identity, not by the name in your config, and
the version is compared separately: evidence about x@1.0.0 is not
a finding about x@2.0.0 in either direction.
Zero runtime dependencies. Node 18 or newer, built-ins only. No telemetry.
Policy for a team or an organisation
.mcp-vault.policy.json sets the bar once, so CI and your shell
enforce the same one: unpinned-launch handling, signature and provenance
requirements, licence allow/deny, acceptable tiers. An organisation keeps one
policy and projects inherit it with "extends": an allow-list means
default deny, a deny rule outranks every allow, and a project can only tighten
the organisation’s rules. An unknown key is an error, not a no-op.
Beyond the configs
- Hash the bytes yourself —
verify --deepdownloads each artifact and hashes it locally; npm registry signatures are checked on every run, provenance attestations are read and compared with the recorded source repository. - The whole dependency tree —
verify --depsresolves it without installing anything and checks every package, including install scripts deep in the tree. - Why was it denied? —
explain <name>prints each piece of evidence with its date, the policy in force, every rule with its outcome, and the rule that decided it.--recordkeeps the decision as an audit line. - What do I install instead? —
upgradefinds the shortest version that clears every advisory against a pin, not the newest release. - Freeze what actually runs — a pinned root does not pin its tree.
lockrecords npm’s lockfile per server,--checkdiffs a fresh resolve,--vendorinstalls it so nothing resolves at launch. - What the tools tell the model —
tool-scanreads atools/listpayload for hidden Unicode, terminal escapes, injected instructions and credential paths. - Secrets on this machine —
secretsruns the same secret scanning over every host config the tool reads, with a suggested fix in each host’s own syntax. - Machine-readable —
--jsoneverywhere, SARIF for code scanning, CycloneDX 1.6 fromsbom. - Also —
budget(context tokens your servers inject),capabilities(what a package can do, and what a new version gained),availability,identity,posture,doctor.mcp-vault --helplists them all.
For known servers: the curated database
The vault ships a database of known MCP servers with pinned versions,
integrity hashes (npm sha512, PyPI sha256, Docker @sha256) and
SPDX licences. Trust is derived from dated evidence, each kind with its own
shelf life — a hash match holds for 90 days, “no advisories” for 7 —
rather than typed by hand. As of 2026-09-30 (the newest evidence in the
database): 112 entries, 107 verified, 1 candidate, 4 unverified. It is
what check compares a known server against; it is not a
list of everything you may run.
What this does not do
- Not a sandbox. An installed MCP server still runs with the permissions of your MCP host.
- Not a runtime monitor. The vault decides before a server runs; it does not watch it afterwards.
- Not proof that a server is benign. A hash proves you got the artifact you expected, not that the artifact is safe.
- Provenance is bound, not cryptographically verified. The attestation’s digest is tied to npm’s signing key; the Fulcio certificate chain and the Rekor inclusion proof are not checked, so the repository identity stays a claim.
- A pattern scan shows presence, never absence. Minified or obfuscated code defeats it, so a capability not found is recorded as nothing at all.
Releases
v0.16.0 — adds mcp-vault check, the GitHub Action and the pre-commit hook: one offline pass over a repository’s MCP configs with one decision and one exit code.