chore: upgrade the MCP TypeScript SDK from 2.0.0-beta.5 to 2.0.0 - #1989
Conversation
The SDK shipped 2.0.0 final on 2026-07-27. Shipping the Inspector against a prerelease of its core protocol library is a supply-chain and reproducibility liability we no longer have a reason to carry: a beta is eligible for unpublish and deprecation in a way a stable release is not. Bumped in the root package.json only — client, core, server, server-legacy. Node resolution walks up, so the root install already serves every client; a per-client declaration would install a second copy that drifts from it (#1970). Verified after install: one copy of each at 2.0.0, no clients/*/node_modules/ @modelcontextprotocol/* at all. ext-apps is a separate package on its own ^1.7.4 line and is untouched. The beta.5 → 2.0.0 delta is seven commits. Reviewed each for call-site impact: - core/src/schemas.ts (+16/-16) is doc-comment only — every hunk rewrites a spec URL from a commit-pinned GitHub blob to the published 2026-07-28 page. No schema surface change, so nothing in core/mcp or core/json is affected. - client 2.0.0 wants zod ^4.2.0; we are on ^4.4.3, so no zod move and no risk of the #1896 dual-copy tsc heap blowup. verify:dep-lockstep stays green and the lockfile delta is exactly the four packages with no transitive churn. - fix(validators) honors declared draft-07/06 JSON Schema dialects instead of rejecting them, which can only widen the set of tool schemas we accept. - The SSE keep-alive and legacyWrap changes are server-side, exercised by the test servers rather than by client code. The one change with real behavioral reach is #2564: the negotiation probe now classifies HTTP 401/403 as an auth failure instead of legacy-era evidence. That is the upstream fix #1807 is blocked on, and it is left for that issue — the directAuthRecovery clause in inspectorClient.ts still intercepts the challenge before the classifier sees it, so this bump does not change connect behavior. #1807 can now delete the workaround and lean on the SDK verdict, but doing it here would smuggle an auth change into a dependency bump. Also corrected the two auth as-built specs, which still claimed beta.4 — already stale before this change. v2_new_spec_impact.md is deliberately left alone: it is a dated pre-upgrade analysis, and editing its premises would rewrite the record rather than update it. npm run ci passes end to end: validate, the per-file >=90 coverage gate, verify:build-gate, all six smokes (including web:app driving connect -> open app -> data-app-status="ready"), and 472 Storybook tests. Closes #1988 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3 Signed-off-by: cliffhall <cliff@futurescale.com>
There was a problem hiding this comment.
Pull request overview
Upgrades the shared MCP TypeScript SDK dependencies from beta.5 to stable 2.0.0.
Changes:
- Updates four root SDK dependencies and lockfile entries.
- Refreshes SDK-version references in two auth specifications.
- Leaves required packaging, showcase-config verification, and one stale EMA specification unresolved.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
package.json |
Pins four MCP SDK packages to 2.0.0. |
package-lock.json |
Resolves the updated SDK packages. |
specification/v2_auth_sdk_consolidation.md |
Updates the documented client version. |
specification/v2_auth_hardening.md |
Updates the documented client version. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Review caught that v2_auth_ema.md contradicted itself. Its "TypeScript SDK (implemented)" section claimed Inspector depends on `@modelcontextprotocol/sdk` v1.x only (`^1.29.0`) and that there is "no `@modelcontextprotocol/client` v2 dependency in the tree today" — while the subsection immediately below it documents which v2 client helpers the EMA legs have adopted. Checked rather than assumed: every module the section's table names imports the v2 client (emaFlow, idpOidc, resourceContext, tokenEndpoint, transportProvider, wire, and providers.ts), and there are zero v1 SDK imports in first-party code. The v1 SDK is present in the tree only as a peer pulled in by ext-apps, which AGENTS.md already states must never become a direct dependency. Rewrote the paragraph to say what is true and name the version, so it stays consistent with the two auth specs corrected in the previous commit. The per-row "v1 SDK" attributions in the table below it are wrong for the same reason, but correcting each one means auditing which SDK symbol each leg calls today — a real audit, not a version-string refresh, and out of scope for a dependency bump. Left for a follow-up rather than guessed at here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3 Signed-off-by: cliffhall <cliff@futurescale.com>
Review round 1 — responsesAll three comments were actionable and pointed at acceptance criteria from #1988. Mirroring here since inline threads get hidden once the fix is pushed. 1. Run 2. Exercise the era-sensitive showcase configs. Done — all 15 HTTP configs driven through the built CLI over a real transport, era derived from each config's This turned up a genuine bug — but not one this PR causes. I reverted the tree to 3. The per-row "v1 SDK" attributions in that table are wrong for the same reason and are deliberately left: correcting them means auditing which SDK symbol each EMA leg calls today, which is an audit rather than a version-string refresh. Same for the later checklist item. Flagged so it reads as a conscious deferral. Not changedThe suggestion that the smoke suite should cover the showcase configs is a fair observation and a real gap, but committing new smoke tooling is its own change, not part of a dependency bump. The verification above was a one-off harness. |
Closes #1988
Moves the four MCP SDK packages off the
2.0.0-beta.5prerelease onto 2.0.0 final (published 2026-07-27).The change
Root
package.jsononly, per the placement rule — Node resolution walks up, so the root install already serves every client and a per-client declaration would install a second copy that drifts (#1970). Verified post-install: one copy of each at2.0.0, andclients/*/node_modules/@modelcontextprotocol/*does not exist.ext-appsis a separate package on its own^1.7.4line and is untouched.The lockfile delta is exactly the four packages — 19 insertions, 19 deletions, no transitive churn.
Reviewing the delta
beta.5 → 2.0.0is seven commits. Each checked for call-site impact:core/src/schemas.ts(+16/−16)2026-07-28page. No schema surface change, socore/mcpandcore/jsonare unaffected.fix(validators): honor declared draft-07/06 JSON Schema dialects instead of rejecting themlegacyWrap,createMcpHandlertest-servers/, not client code.client@2.0.0wants^4.2.0; we are on^4.4.3. No move, so no risk of the #1896 dual-copytscheap blowup.verify:dep-lockstepstays green.fix(client)#2564: probe 401/403 → auth failure, not legacy evidenceOn #2564 and issue #1807
SDK PR #2564 is the upstream fix #1807 is blocked on. The probe classifier now gets explicit rows ahead of the JSON-RPC body parse: a 401/403 rejects as a typed
SdkHttpError(ClientHttpAuthentication/ClientHttpForbidden) carrying the status, rather than falling into the conservative legacy fallback.Deliberately not acted on in this PR. The
directAuthRecoveryclause ininspectorClient.tsstill setsinterceptAuthChallenges, so the challenge is converted to a typedAuthChallengeErrorbefore the classifier ever sees the 401 — connect behavior is unchanged by this bump. #1807 (milestone v2.4.0,waiting on sdk) can now delete that|| this.probesProtocolEra()workaround and lean on the SDK verdict, exactly as its in-code comment instructs. Folding an auth-path change into a dependency bump would make both harder to review and to revert.One thing #1807 will need to handle:
SdkHttpErrorcarries the status aterr.data.status, and its message reads…(HTTP 401).isUnauthorizedErrorincore/auth/utils.tscheckserr.status/err.codeand matches\bfailed\b[^\n]*\(401\), so it would not recognize the new error as-is. That is a note for #1807, not a defect introduced here — the intercept means the path is not reached today.Docs
Corrected the two auth as-built specs, which claimed beta.4 and so were already stale before this change.
specification/v2_new_spec_impact.mdis left alone on purpose: it is a dated pre-upgrade impact analysis ("currently depends onsdk@1.29.0", "stable release planned alongside the spec on July 28"). Editing its premises would rewrite the record rather than update it.Verification
npm run cipasses end to end —validate→ the per-file ≥90 coverage gate →verify:build-gate→ all six smokes → Storybook.smoke:web:appis the load-bearing one for a protocol-library bump: it drives connect → open app → widget handshake against a real composable server, so it covers the transport, the sandbox proxy, and the UI-protocol bridge in one assertion.No screenshots: this is a dependency bump with no UI change. The two headless-Chromium smokes above are the visual proof —
smoke:web:browserasserts a clean first paint andsmoke:web:appasserts a rendered widget, both against the prod bundle built on 2.0.0.