Skip to content

v2 release pipeline, Phase 1: OIDC trusted publishing — ✅ complete (validation release 2026.7.4) #4463

Description

@cliffhall

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.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

  1. 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.
  2. Tag-before-test: the cron tagged and pushed versions before running a single test, stranding versions on any failure (June 3, June 16 — see Runbook: recover stranded June npm releases by re-running release.yml publish jobs (no repo changes — June 3 window closes TODAY) #4465 for the abandoned recovery).
  3. Phantom versions: version bumps lived only on orphaned tag commits — main's package.json files were never touched.
  4. 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.
  5. 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).

Phase 0 — hygiene ✅

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
  • NPM_CONFIG_PROVENANCE: "true" — provenance attestations
  • Test gates before publish in both publish jobs
  • skip-existing: true on the PyPI publish action
  • .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.

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions