Attest your MCP package's build provenance
What we checked
We looked for build provenance: a signed attestation, published alongside your package, that cryptographically binds the artifact to the source commit and the CI run that built it. The signal passes only when that attestation exists and verifies. The other outcomes (no attestation, an attestation that fails verification, an unpublished version, or an inconclusive check) mean:
Why it matters
A registry account proves who uploaded a package; it doesn’t prove where the bytes came from. Build provenance closes that gap. A signed attestation lets anyone confirm the artifact was built from a specific commit in your public repository, by your CI, and hasn’t been swapped or tampered with since. That defends against a stolen publish token, a compromised maintainer laptop, or a malicious mirror, none of which can forge a valid signature bound to your repo.
How to fix it
Publish from CI and emit a signed attestation as part of the publish step. The mature, turnkey paths today are npm and PyPI, both built on Sigstore and OIDC: no long-lived signing keys to manage.
name: publish
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # required for provenance (OIDC)
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
- run: npm ci
# --provenance generates and publishes a signed attestation
- run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} name: publish
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # required for Trusted Publishing + attestations
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install build && python -m build
# Uses PyPI Trusted Publishers (OIDC); publishes PEP 740 attestations
- uses: pypa/gh-action-pypi-publish@release/v1 For npm, also confirm your package.json repository field points at the same
public repo the workflow runs in; the attestation binds to it, and a mismatch
means the attestation exists but fails verification.
How we re-check
We re-fetch the attestation for your latest published version on our next crawl. Once a valid, repo-bound attestation is present, the signal flips to verified on the following score refresh.
Give this to your AI
Paste this into Claude Code (or any coding agent) from inside your server's repository. It states the failing signal, the outcome we re-check for, and the format the fix has to take.
Context: this repository publishes an MCP server. VerifyMCP's build provenance check failed, which means the published package carries no signed attestation binding it to the source commit and CI run that built it, or the attestation exists but doesn't verify. Goal: the published artifact carries a valid, repo-bound attestation, so the next crawl records verified provenance. Do this: 1. Identify the registry you publish to (npm, PyPI, NuGet, Go modules, crates.io, or an OCI container image). 2. For npm: publish from CI with `id-token: write` permission and run `npm publish --provenance` (add `--access public` only if the package is meant to be public and is not already); confirm the `repository` field in `package.json` points at the same public repo the workflow runs in, since a mismatch stops the attestation verifying. 3. For PyPI: configure Trusted Publishing (OIDC) and publish with `pypa/gh-action-pypi-publish`, which emits PEP 740 attestations. 4. For NuGet, Go, or crates.io: there is no native equivalent of repo-bound build provenance today (NuGet package signing proves the signer, not the build; Go relies on the `go.sum` checksum database; crates.io has no mechanism). Say so plainly rather than approximating one. 5. If you ship an OCI container image, sign and attest it with Sigstore `cosign` (e.g. `cosign attest`). 6. Prepare the release, then stop and let me run the publish myself, since the check reads the published attestation. Rules: - Never run the publish command (`npm publish`, `twine upload`, `dotnet nuget push`, `cargo publish`, a release tag that triggers one) yourself. A published version is permanent and notifies every downstream consumer: prepare the change, show me the diff, and let me publish it. - Never fabricate, hand-craft, or hardcode an "attestation" file; it must come from a real signing step tied to the actual CI run and commit. - If the registry or ecosystem genuinely has no provenance mechanism, say so in your report rather than claiming the signal now passes. - Ask me before changing where or how the package is published (e.g. moving publishing into CI) if that touches secrets or release process you don't control. Report back: the workflow files you changed, the registry involved, and how I can verify the attestation myself (e.g. the provenance link on the npm package page, or the PyPI attestations tab). Reference: https://verifymcp.io/docs/packages/build-provenance