Skip to content

Migrate to MCP TypeScript SDK v2 (2.0.0-beta.1) - #14

Open
raymondfeng wants to merge 2 commits into
mainfrom
mcp-sdk-v2
Open

Migrate to MCP TypeScript SDK v2 (2.0.0-beta.1)#14
raymondfeng wants to merge 2 commits into
mainfrom
mcp-sdk-v2

Conversation

@raymondfeng

Copy link
Copy Markdown
Contributor

What

Migrates AgentBack's MCP stack from the monolithic @modelcontextprotocol/sdk@1.29 to the v2 package split (@modelcontextprotocol/{core,server,client,node,express} @ 2.0.0-beta.1). Done via the official @modelcontextprotocol/codemod v1-to-v2 plus hand-fixes for the semantic changes the codemod flags.

Status: v2 is beta — the API is settling until the stable release alongside the 2026-07-28 spec. Deps are pinned to exact 2.0.0-beta.1 (not ^). This is a spike/prep branch; hold merge until v2 goes stable, or merge to track the beta deliberately.

Why v2 is a migration, not a bump

@modelcontextprotocol/sdk@2 does not exist on npm — v2 shipped as ~9 new packages. Every import moves. The split also mirrors AgentBack's own host-neutral mcp vs mcp-http design (v2's /server vs /node vs /express).

Commit 1 — core migration

  • keys.ts: RequestHandlerExtraServerContext; the removed SDK RequestInfo type replaced by a stable local McpRequestInfo for the REQUEST_INFO binding.
  • mcp.server.ts requestContextFor: v2 flattened the per-request "extra" into ctx.mcpReq (id/signal/send/notify/_meta) and ctx.http (authInfo/req). Mapped authInfohttp.authInfo, and derive the stable {headers,url} REQUEST_INFO contract from the new http.req Fetch Request (keeps @agentback/payments et al. unchanged). progressFnFor relays via mcpReq.notify.
  • tools/list: v2 tightened the result to require a literal inputSchema.type:"object" (always true here); asserted at the one boundary.
  • mcp-connect: v2 Client.callTool dropped the middle resultSchema arg.

Commit 2 — OAuth auth to @modelcontextprotocol/express; drop server-legacy

  • mcp-http/index.ts: requireBearerAuth + OAuthTokenVerifier now from @modelcontextprotocol/express. Legacy metadataHandler dropped — v2's mcpAuthMetadataRouter also serves the authorization server's RFC 8414 metadata, which AgentBack (a pure resource server pointing at an external AS) does not own, so we serve the RFC 9728 protected-resource doc directly.
  • fetch.ts (edge mirror): the four legacy error subclasses consolidated into v2's single OAuthError discriminated by code.
  • Dual-package-identity fix: v2's client/server/express each bundle their own copy of the auth classes (no shared core), so instanceof only matches the same-package copy — a verifier throwing OAuthError from the wrong package reads as a 500. @agentback/mcp-http now re-exports the exact OAuthError its middleware recognizes; tests dogfood import {OAuthError} from '@agentback/mcp-http'.
  • @modelcontextprotocol/server-legacy is no longer a dependency of any package.

Verification

pnpm verify (build + typecheck:client + full test + validate-templates) — exit 0, 2604 passed | 33 skipped (skips are pre-existing env-gated).

Known follow-ups (intentionally not in this PR)

  • @modelcontextprotocol/ext-apps has no v2 build yethello-mcp-apps keeps sdk@1.29 transitively (the only remaining v1 SDK reference; contained to that one example).
  • Prose docs (packages/*/README.md, docs/guides/build-an-mcp-server.md) still show old @modelcontextprotocol/sdk/... import paths — not build-affecting.
  • Beta pins should move to a range / be re-verified when v2 hits latest.

🤖 Generated with Claude Code

raymondfeng and others added 2 commits July 11, 2026 21:40
v2 splits the monolithic @modelcontextprotocol/sdk into per-role/per-framework
packages. Migrate the 6 MCP packages + testing + hello-mcp off `sdk` onto
@modelcontextprotocol/{core,server,client,node,server-legacy} via the official
codemod (`@modelcontextprotocol/codemod v1-to-v2`) plus hand-fixes:

- keys.ts: RequestHandlerExtra -> ServerContext; the removed SDK `RequestInfo`
  type replaced by a stable local `McpRequestInfo` for the REQUEST_INFO binding.
- mcp.server.ts requestContextFor: v2 flattened the per-request "extra" into
  `ctx.mcpReq` (id/signal/send/notify/_meta) and `ctx.http` (authInfo/req).
  Map authInfo -> http.authInfo, and derive the {headers,url} REQUEST_INFO
  contract from the new `http.req` Fetch Request (keeps @agentback/payments
  et al. stable). progressFnFor now relays via `mcpReq.notify`.
- tools/list: v2 tightened the result to require `inputSchema.type:"object"`
  (always true here); assert at the one boundary via ListToolsResult.
- mcp-connect: v2 Client.callTool dropped the middle resultSchema arg.
- mcp-http OAuth resource-server bearer path stays on the FROZEN
  server-legacy/auth copy (functional, behavior-preserving); moving to
  @modelcontextprotocol/express is a documented follow-up (verifiers must
  throw the v2 OAuthError).

Deps pinned to exact 2.0.0-beta.1 (v2 is beta until the 2026-07-28 stable).
`pnpm verify` green: 2604 passed | 33 skipped.

Known follow-ups (not in this spike):
- Re-point mcp-http bearer auth to @modelcontextprotocol/express.
- @modelcontextprotocol/ext-apps has no v2 build yet -> hello-mcp-apps keeps
  sdk@1.29 transitively.
- Prose docs still reference the old `@modelcontextprotocol/sdk` import paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…press; drop server-legacy

Completes the v2 migration by removing the deprecated
@modelcontextprotocol/server-legacy dependency from mcp-http, mcp-client,
and mcp-connect entirely.

- index.ts: requireBearerAuth + OAuthTokenVerifier now import from
  @modelcontextprotocol/express (the maintained v2 home). The legacy
  metadataHandler is dropped: v2's mcpAuthMetadataRouter also serves the
  authorization SERVER's RFC 8414 metadata, which AgentBack — a pure resource
  server pointing at an external AS — does not own, so we serve the RFC 9728
  protected-resource document directly with a one-line route.
- fetch.ts: the edge/fetch bearer mirror consolidates the four legacy error
  subclasses (InvalidToken/InsufficientScope/OAuth/ServerError) into v2's
  single OAuthError, discriminated by `code` for the HTTP status mapping.
- All 5 integration-test verifiers throw v2 OAuthError.

Dual-package-identity fix: v2's client/server/express each bundle their own
copy of the auth classes (no shared @modelcontextprotocol/core), so
`instanceof` only matches the copy from the same package — a verifier throwing
OAuthError from the wrong package would be misread as a 500. mcp-http now
re-exports the exact OAuthError its middleware recognizes; the mcp-client and
mcp-connect tests dogfood it via `import {OAuthError} from '@agentback/mcp-http'`.

`pnpm verify` green: 2604 passed | 33 skipped. server-legacy no longer a dep.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant