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
{{ message }}
Repository navigation
go-live 5/9: publish 2.0.0 (rc under next first; rollback plan written first) #1818
Confirm whoever cuts the release holds the npm rights to do all three.
Tasks
Publish 2.0.0-rc.1 under --tag next to the real registry and install it on a clean machine via npx @modelcontextprotocol/inspector@next. This is the only way to validate what only exists against live npm: provenance/OIDC minting, the files allowlist as npm actually packs it, the postinstall cascade's early-exit under a real dependency install, and the Docker job. A wasted prerelease number is cheap next to a broken 2.0.0.
npm run pack:verify green (the publish job already runs it as a gate).
Cut the release: tag 2.0.0 or v2.0.0 (the assert tolerates the leading v) targeting the post-merge main commit.
Confirm Docker latest moves to 2.0.0 and a 1-pinned tag is preserved for v1 users.
changed the title [-]go-live 4/9: replace main's tree with v2[/-][+]go-live 5/9: publish 2.0.0 (rc under next first; rollback plan written first)[/+]on Jul 27, 2026
Rollback plan (the blocking prerequisite) — written, verified, ready
Verified 2026-07-28, before any 2.0.0 publish.
npm rights confirmed
npm access list collaborators @modelcontextprotocol/inspector — the person cutting the release (cliffhall) holds read-write, which covers all three rollback operations. Four other maintainers also hold read-write (ashwin-ant, fweinberger, jspahrsummers, ochafik-ant), so recovery is not single-person dependent.
⚠️All registry writes require a 2FA OTP. Under rollback pressure that means having an authenticator to hand. Learned in #1816: a long pasted command gets hard-wrapped by the terminal and the newline is stored verbatim — for npm deprecate, put the message in a script file rather than pasting it.
State to restore to
latest 1.0.1
v1-latest 1.0.1
If 2.0.0 is broken
npm unpublish is effectively unavailable (72h window, disallowed once anything depends on it). Rollback is dist-tag surgery, in this order:
1. Move latest back — do this first, it stops the bleeding.
Every npx @modelcontextprotocol/inspector immediately resolves to 1.0.1 again. Note this re-points latest at a deprecated version, so installs will warn — correct and intended: a deprecation warning beats a broken tool.
2. Deprecate the bad version, so anyone pinned to it is told why:
npm deprecate "@modelcontextprotocol/inspector@2.0.0""2.0.0 was withdrawn: <reason>. Use @modelcontextprotocol/inspector@2.0.1 or later." --otp=<code>
Deprecation is retroactive but mutable — liftable later with an empty message.
3. Ship 2.0.1 with the fix, which reclaims latest automatically (the version is not a prerelease, so #1834's tag derivation gives it latest).
Docker rollback
The container image is a separate artifact on the same release trigger. If the image is bad but npm is fine, re-point the registry tag rather than re-cutting a release; if both are bad, the release-level rollback covers each.
What is NOT a valid rollback
npm unpublish — unavailable in practice; do not plan around it.
Deleting the GitHub release/tag — does nothing to npm. The package stays published. The 1.* tag ruleset (19859230) also blocks deleting or moving v1 tags outright; the 2.x tags are unprotected today, but deleting one still has no registry effect.
A failed publish (workflow errors before or during npm publish) consumes nothing and needs no rollback — fix and re-cut. The dangerous state is a successful publish of a broken artifact, which is what the above addresses.
The narrow bad case is a partial publish, but v2 is not an npm workspace — it is a single npm publish of one package, so the multi-package partial failure that made v1's publish-all risky (#1815) does not exist here.
The v1 tag is v1-latest, not v1 — npm rejects any dist-tag that parses as a SemVer range, and v1 parses as 1.x (found in #1816, fixed in #1829). The expected end state is:
latest 2.0.0 ← was 1.0.1
v1-latest 1.0.1
next 2.0.0-rc.3
npx @modelcontextprotocol/inspector now resolves to v2 worldwide.
Verification
Check
Result
npm latest → 2.0.0
✅
npm v1-latest → 1.0.1 (escape hatch intact)
✅
Cold node:22 container install from latest
✅ 2.0.0; --help and a real --cli tools/list against a live stdio server both work
Docker latest moved
✅ digest identical to 2.0.0
Docker image runs
✅ contains @modelcontextprotocol/inspector@2.0.0
Open Dependabot alerts
✅ 0
Open CodeQL alerts
✅ 0
The 1-pinned Docker tag — closing as satisfied by 1.0.1
This issue asked to confirm "a 1-pinned tag is preserved for v1 users". There is no 1 tag, and there never was — the workflow tags images by exact version only. What exists is ghcr.io/modelcontextprotocol/inspector:1.0.1, multi-arch and intact at its own digest.
That serves the purpose: v1 users have a working, stable pin. A floating 1 would add a maintenance obligation (something must move it on every future v1 release) for little benefit on a line that is deprecated and takes security fixes only. Closing on that basis rather than creating the tag; if a floating 1 is ever wanted, it needs adding to v1/main's workflow, not just pushing once.
What the RC process actually caught
Three release candidates, and they were not ceremony — the v2 publish job had never executed before, so every defect below was waiting for whoever cut the first v2 release:
The RCs also prompted a dependency audit that cleared every prod-scope advisory (#1837) and three high-severity vite dev-server file-read advisories (#1841).
Each RC was validated by installing the published tarball into a cold node:22 container and driving it end to end. latest stayed on 1.0.1 through all three — the proof that the tag derivation worked.
Rollback
Not needed. The plan remains valid if 2.0.0 turns out to be broken: dist-tag surgery, not unpublish.
Both dev-scope, neither shipped. Their alerts are dismissed with per-alert reasoning — tolerable_risk for vitest, not_used for esbuild (its dev-server mode is never invoked here; esbuild is reached only as a bundler via tsup and vite).
Next: #1819 (triage and bulk-close the v1 backlog — note it is 125 PRs, not ~30).
Activity
[-]go-live 4/9: replace main's tree with v2[/-][+]go-live 5/9: publish 2.0.0 (rc under next first; rollback plan written first)[/+]ci: set a least-privilege default GITHUB_TOKEN scope (#1831)
chore(deps): upgrade @hono/node-server to 2.0.12 (#1832)
cliffhall commentedon Jul 28, 2026
Rollback plan (the blocking prerequisite) — written, verified, ready
Verified 2026-07-28, before any 2.0.0 publish.
npm rights confirmed
npm access list collaborators @modelcontextprotocol/inspector— the person cutting the release (cliffhall) holds read-write, which covers all three rollback operations. Four other maintainers also hold read-write (ashwin-ant,fweinberger,jspahrsummers,ochafik-ant), so recovery is not single-person dependent.npm deprecate, put the message in a script file rather than pasting it.State to restore to
If 2.0.0 is broken
npm unpublish is effectively unavailable (72h window, disallowed once anything depends on it). Rollback is dist-tag surgery, in this order:
1. Move
latestback — do this first, it stops the bleeding.Every
npx @modelcontextprotocol/inspectorimmediately resolves to 1.0.1 again. Note this re-pointslatestat a deprecated version, so installs will warn — correct and intended: a deprecation warning beats a broken tool.2. Deprecate the bad version, so anyone pinned to it is told why:
Deprecation is retroactive but mutable — liftable later with an empty message.
3. Ship 2.0.1 with the fix, which reclaims
latestautomatically (the version is not a prerelease, so #1834's tag derivation gives itlatest).Docker rollback
The container image is a separate artifact on the same release trigger. If the image is bad but npm is fine, re-point the registry tag rather than re-cutting a release; if both are bad, the release-level rollback covers each.
What is NOT a valid rollback
npm unpublish— unavailable in practice; do not plan around it.1.*tag ruleset (19859230) also blocks deleting or moving v1 tags outright; the 2.x tags are unprotected today, but deleting one still has no registry effect.main— does not unpublish, and breaks the merge-parent structure established in go-live 4/9: replace main's tree with v2 #1817.Rollback is not needed for
A failed publish (workflow errors before or during
npm publish) consumes nothing and needs no rollback — fix and re-cut. The dangerous state is a successful publish of a broken artifact, which is what the above addresses.The narrow bad case is a partial publish, but v2 is not an npm workspace — it is a single
npm publishof one package, so the multi-package partial failure that made v1'spublish-allrisky (#1815) does not exist here.Correction to this issue's last task
It reads:
The v1 tag is
v1-latest, notv1— npm rejects any dist-tag that parses as a SemVer range, andv1parses as1.x(found in #1816, fixed in #1829). The expected end state is:ci: derive the npm dist-tag from the version instead of defaulting to…
chore: 2.0.0-rc.1 (#1835)
chore: 2.0.0 (#1842)
cliffhall commentedon Jul 28, 2026
2.0.0 is published. Phase 5 complete.
npx @modelcontextprotocol/inspectornow resolves to v2 worldwide.Verification
latest→ 2.0.0v1-latest→ 1.0.1 (escape hatch intact)node:22container install fromlatest--helpand a real--cli tools/listagainst a live stdio server both worklatestmoved2.0.0@modelcontextprotocol/inspector@2.0.0The
1-pinned Docker tag — closing as satisfied by1.0.1This issue asked to confirm "a
1-pinned tag is preserved for v1 users". There is no1tag, and there never was — the workflow tags images by exact version only. What exists isghcr.io/modelcontextprotocol/inspector:1.0.1, multi-arch and intact at its own digest.That serves the purpose: v1 users have a working, stable pin. A floating
1would add a maintenance obligation (something must move it on every future v1 release) for little benefit on a line that is deprecated and takes security fixes only. Closing on that basis rather than creating the tag; if a floating1is ever wanted, it needs adding tov1/main's workflow, not just pushing once.What the RC process actually caught
Three release candidates, and they were not ceremony — the v2 publish job had never executed before, so every defect below was waiting for whoever cut the first v2 release:
ENEEDAUTH—NODE_AUTH_TOKENpointed at a non-existentNPM_TOKENsecret, writing an empty_authTokeninto setup-node's.npmrcand failing before OIDC was ever attempted. Would have failed 2.0.0 outright. (fix(ci): publish via OIDC trusted publishing, not a non-existent NPM_TOKEN #1836)--tagon publish —npm publishdefaults tolatestregardless of prerelease status, so cutting2.0.0-rc.1would have pointedlatestat a release candidate. Caught before the first RC ran; the RCs then proved the fix. (ci: derive the npm dist-tag from the version instead of defaulting to latest #1834)The RCs also prompted a dependency audit that cleared every prod-scope advisory (#1837) and three high-severity vite dev-server file-read advisories (#1841).
Each RC was validated by installing the published tarball into a cold
node:22container and driving it end to end.lateststayed on 1.0.1 through all three — the proof that the tag derivation worked.Rollback
Not needed. The plan remains valid if 2.0.0 turns out to be broken: dist-tag surgery, not unpublish.
Deferred, tracked
eslint-plugin-react-hooksdoes not accept eslint 10)npm ifails ERESOLVE)Both dev-scope, neither shipped. Their alerts are dismissed with per-alert reasoning —
tolerable_riskfor vitest,not_usedfor esbuild (its dev-server mode is never invoked here; esbuild is reached only as a bundler via tsup and vite).Next: #1819 (triage and bulk-close the v1 backlog — note it is 125 PRs, not ~30).