A fail-closed CI gate over your committed mcpm-lock.yaml. It runs mcpm verify —
repo-only, no AI clients required — so it works on a hosted runner where mcpm up
cannot, and it checks three independent dimensions:
- Integrity — each locked npm server against npm's published
dist.integrity. - Provenance (Sigstore) — for every server the lock recorded as cryptographically
verified, the npm SLSA attestation is re-verified offline and the signer identity compared against the locked baseline. Evidence-gated: a lock with no verified baseline is unaffected. - Coverage — every server
mcpm.yamldeclares must appear in the lock, so a truncated lock cannot pass vacuously.
The step fails (non-zero) on integrity drift, an unverifiable record, an
integrity format mismatch, a suspicious missing baseline, a provenance
signer-changed / regression / unverifiable verdict, uncovered declared
servers, or a vacuous run (an empty lock with no mcpm.yaml to confirm that is
intentional). It writes a job step summary from the --json model naming every
blocking server and its reason, grouped by dimension.
Honesty boundary: a failure means npm's published record diverged from (or can't be matched against) your lock — not that mcpm caught malicious bytes. npx/uvx fetch the artifact independently at server launch.
Pin the Action source to a reviewed release SHA (or tag) and select the CLI
version separately. The Action defaults to version: latest; an Action-source
pin alone does not pin the @getmcpm/cli package it executes:
name: mcpm
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: getmcpm/cli/.github/actions/mcpm-verify@v0.53.0
with:
version: 0.53.0 # executed @getmcpm/cli version
working-directory: . # dir containing mcpm.yaml / mcpm-lock.yamlEquivalent one-liner (no action):
- run: npx --yes @getmcpm/cli@0.53.0 verifyPre-commit hook (same verb):
# .pre-commit-config.yaml
- repo: local
hooks:
- id: mcpm-verify
name: mcpm verify
entry: npx --yes @getmcpm/cli@0.53.0 verify
language: system
pass_filenames: falseOnce the gate is in your CI, advertise it with a static badge:
| Input | Default | Description |
|---|---|---|
version |
latest |
Version or dist-tag of @getmcpm/cli to run. |
working-directory |
. |
Directory containing mcpm.yaml / mcpm-lock.yaml. |
0 verified · 1 block or no lock file found. A block is any of: integrity drift /
unverifiable / format mismatch / missing baseline; a provenance signer-changed /
regression / unverifiable verdict; declared servers the lock does not cover; or a
vacuous run over an empty lock. See contracts.