You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Phases 0–1 of the release-pipeline rebuild: recover from the June publish failures, move npm publishing to OIDC trusted publishing (tokenless), and validate it with a production release. ✅ Complete — validation release 2026.7.4 published all four TypeScript packages via OIDC with provenance attestations, ~2 minutes dispatch-to-release.
Phase 2 — semver via changesets (TS) + GitHub-Release-triggered publishing — continues in #4472.
Background
The @modelcontextprotocol/* npm packages are bound to trusted publishers:
Setting
Value
Publisher
GitHub Actions
Repository
modelcontextprotocol/servers
Workflow filename
release.yml
Environment
release
Allowed actions
npm publish
npm only accepts a publish whose OIDC token attests it came from a release.yml run using the release environment — release.yml is the single publish path.
What the June incidents exposed
Dead publish paths: typescript.yml/python.yml had release:-triggered publish jobs that never fired (the cron created releases with GITHUB_TOKEN, which suppresses workflow triggers) and could never succeed under OIDC. The TS one still referenced the dead NPM_TOKEN.
Phantom versions: version bumps lived only on orphaned tag commits — main's package.json files were never touched.
Approval-delay bugs: environment-approval waits crossing midnight UTC produced a tag (2026.6.3) whose packages were stamped 2026.6.4; failed runs sat perpetually "waiting" — 31 zombie runs accumulated.
Expired token: both June attempts failed every npm leg with a disguised auth error (E404 on the publish PUT); the token could not be replaced (tokenless policy adopted instead).
2026-07-04: GitHub environment Release deleted and recreated as lowercase release (npm matches the OIDC environment claim case-sensitively — same bug inspector#1199 fixed). Side effects: all 31 stale waiting runs auto-failed and the dead env-level NPM_TOKEN secret was deleted. Reviewers: @dsp-ant, @pcarleton, @domdomegg, @cliffhall, @olaservo.
Phase 1 — OIDC trusted publishing ✅
Landed in #4466 (three clean @claude review passes):
permissions: id-token: write (+ explicit contents: read) on publish-npm
npm@^11.5.1 in the publish job (trusted publishing needs ≥ 11.5.1; Node 22 bundles 10.x)
NODE_AUTH_TOKEN removed; no NPM_TOKEN secrets remain anywhere
.md counts as a change in release.py matrix detection (READMEs ship in the published artifacts)
typescript.yml/python.yml converted to pure CI (dead publish jobs + release: triggers removed; CI runs on all pushes + PRs, per-ref concurrency cancellation except main)
Daily release cron removed — release.yml is workflow_dispatch-only (renamed "Release") until Phase 2's release: [published] trigger
RELEASING.md documents the process as merged, linked from README
Out-of-band prerequisites:
npm trusted publishers registered for all four packages (2026-07-04)
Validation release ✅
2026.7.4 — SUCCEEDED 2026-07-04 23:06 UTC (run 28722509733, ~2 minutes dispatch-to-release, three environment gates approved via API). All four npm packages published via OIDC with provenance attestations: everything, filesystem, memory, sequential-thinking at 2026.7.4 = latest. First npm releases since 2026.1.26.
Operations
Day-to-day release and retry procedures live in RELEASING.md. In short: dispatch release.yml, approve the environment gates (approve update-packages the same UTC day as the dispatch), and recover failed legs with gh run rerun <run-id> --failed. No tokens, ever — a manual/token publish breaks the provenance chain and will not be re-introduced.
Scope
Phases 0–1 of the release-pipeline rebuild: recover from the June publish failures, move npm publishing to OIDC trusted publishing (tokenless), and validate it with a production release. ✅ Complete — validation release
2026.7.4published all four TypeScript packages via OIDC with provenance attestations, ~2 minutes dispatch-to-release.Phase 2 — semver via changesets (TS) + GitHub-Release-triggered publishing — continues in #4472.
Background
The
@modelcontextprotocol/*npm packages are bound to trusted publishers:modelcontextprotocol/serversrelease.ymlreleasenpm publishnpm only accepts a publish whose OIDC token attests it came from a
release.ymlrun using thereleaseenvironment —release.ymlis the single publish path.What the June incidents exposed
typescript.yml/python.ymlhadrelease:-triggered publish jobs that never fired (the cron created releases withGITHUB_TOKEN, which suppresses workflow triggers) and could never succeed under OIDC. The TS one still referenced the deadNPM_TOKEN.2026.6.3) whose packages were stamped2026.6.4; failed runs sat perpetually "waiting" — 31 zombie runs accumulated.E404on the publish PUT); the token could not be replaced (tokenless policy adopted instead).Phase 0 — hygiene ✅
2026.6.4/2026.6.16deliberately never exist on npm)Releasedeleted and recreated as lowercaserelease(npm matches the OIDC environment claim case-sensitively — same bug inspector#1199 fixed). Side effects: all 31 stale waiting runs auto-failed and the dead env-levelNPM_TOKENsecret was deleted. Reviewers: @dsp-ant, @pcarleton, @domdomegg, @cliffhall, @olaservo.Phase 1 — OIDC trusted publishing ✅
Landed in #4466 (three clean
@claude reviewpasses):permissions: id-token: write(+ explicitcontents: read) onpublish-npmnpm@^11.5.1in the publish job (trusted publishing needs ≥ 11.5.1; Node 22 bundles 10.x)NODE_AUTH_TOKENremoved; noNPM_TOKENsecrets remain anywhereNPM_CONFIG_PROVENANCE: "true"— provenance attestationsskip-existing: trueon the PyPI publish action.mdcounts as a change inrelease.pymatrix detection (READMEs ship in the published artifacts)typescript.yml/python.ymlconverted to pure CI (dead publish jobs +release:triggers removed; CI runs on all pushes + PRs, per-ref concurrency cancellation exceptmain)release.ymlisworkflow_dispatch-only (renamed "Release") until Phase 2'srelease: [published]triggerRELEASING.mddocuments the process as merged, linked from READMEOut-of-band prerequisites:
Validation release ✅
2026.7.4— SUCCEEDED 2026-07-04 23:06 UTC (run 28722509733, ~2 minutes dispatch-to-release, three environment gates approved via API). All four npm packages published via OIDC with provenance attestations:everything,filesystem,memory,sequential-thinkingat2026.7.4=latest. First npm releases since2026.1.26.Operations
Day-to-day release and retry procedures live in
RELEASING.md. In short: dispatchrelease.yml, approve the environment gates (approveupdate-packagesthe same UTC day as the dispatch), and recover failed legs withgh run rerun <run-id> --failed. No tokens, ever — a manual/token publish breaks the provenance chain and will not be re-introduced.