Skip to content

feat(mcp): add SDK v2 client and stateless server support#1557

Open
mattzcarey wants to merge 13 commits into
cloudflare:mainfrom
mattzcarey:chore/mcp-sdk-v2-upgrade
Open

feat(mcp): add SDK v2 client and stateless server support#1557
mattzcarey wants to merge 13 commits into
cloudflare:mainfrom
mattzcarey:chore/mcp-sdk-v2-upgrade

Conversation

@mattzcarey

@mattzcarey mattzcarey commented May 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Upgrade the Agents MCP stack to the split MCP SDK v2 packages while retaining the existing SDK v1 server and Legacy protocol paths.

import { McpServer } from "@modelcontextprotocol/server";
import { createMcpHandler } from "agents/mcp/server";

export default createMcpHandler(
  () => new McpServer({ name: "example", version: "1.0.0" })
);

Stateless server

  • adds the isolated agents/mcp/server entry for the Agents Worker wrapper;
  • uses exact-pinned @modelcontextprotocol/server@2.0.0-beta.5;
  • keeps McpServer owned by the upstream SDK rather than re-exporting it;
  • excludes McpAgent, WorkerTransport, MCP client transports, PartyServer, and SDK v1 from the Stateless bundle;
  • preserves Legacy compatibility by default, with legacy: "reject" for a Stateless-only endpoint;
  • serves Legacy compatibility through the SDK v2 web-standard transport rather than WorkerTransport;
  • preserves reverse-request fail-fast behavior, active-request cleanup, and 25-second SSE keepalives;
  • validates browser Origins by default and supports allowedOriginHostnames: "*" when trusted upstream middleware performs validation;
  • preserves callable Worker routing, CORS, auth context, and upstream fetch, close, notify, and bus controls.

The compatibility agents/mcp entry remains available. Its implementation is now separated into explicit compatibility and Legacy modules. createLegacyMcpHandler and WorkerTransport remain supported. McpAgent remains deprecated and feature-frozen.

Client

  • uses exact-pinned @modelcontextprotocol/client@2.0.0-beta.5;
  • negotiates Stateless or Legacy servers automatically;
  • supports Stateless Elicitation through SDK-owned multi-round-trip requests (MRTR);
  • keeps callTool, getPrompt, and readResource pending while input is collected;
  • exports elicitation client types from agents/mcp/client;
  • preserves Legacy pushed elicitation, Streamable HTTP, SSE, RPC, OAuth, recovery, and the deprecated v1-shaped manager overload;
  • persists Stateless discovery state in the beta.5 prior shape for safe HTTP restoration.

OAuth and integrations

  • preserves discovery-triggered authorization and issuer-bound OAuth state;
  • rediscovers changed authorization servers without reusing credentials from the prior issuer;
  • retains the explicit skipIssuerMetadataValidation compatibility option for trusted Legacy metadata;
  • keeps x402 compatible with both MCP client generations;
  • uses an SDK-neutral structural boundary in the Code Mode MCP connector;
  • makes @cloudflare/codemode an optional peer, with direct dependencies added to every workspace consumer.

Elicitation examples

  • examples/mcp-elicitation-mrtr: Stateless Elicitation, including a two-round tool flow;
  • examples/mcp-elicitation: Legacy Elicitation, retaining Durable Object state, WorkerTransport, pushed form/URL requests, and SSE replay.

Structure and coverage

  • adds a full in-process lifecycle test for discovery/initialization, catalogs, tool calls, prompts, resources, and close through Stateless and Legacy compatibility paths;
  • adds a bundle graph regression test for agents/mcp/server;
  • documents package boundaries, lifecycles, tradeoffs, and the conformance matrix in design/mcp.md;
  • updates the vendored Stateless conformance fixture provenance to SDK beta.5;
  • documents the single alpha.9 referee mismatch caused by beta.5 following the final discovery wire.

Lifecycle boundary

In-flight Stateless Elicitation remains memory-only. Durable Object hibernation, isolate restart, transport loss, or connection reconstruction rejects the active operation. This PR does not persist requestState or add a manual continuation API.

Verification

  • pnpm install --frozen-lockfile
  • pnpm run build
  • pnpm run check — exports, formatting, lint, and all 118 TypeScript projects
  • pnpm --filter agents run test — 125 files / 2,345 tests
  • official referee: @modelcontextprotocol/conformance@0.2.0-alpha.9
  • Stateless client: 32 scenarios — 27 clean / 5 documented expected failures
  • Legacy client: 18 scenarios — 16 clean / 2 SHOULD-level failures; earlier lanes 5/5 and 2/2 clean
  • optional client extensions: 3 documented expected failures
  • Stateless server: 39 clean / 1 documented beta.5-vs-alpha.9 referee mismatch
  • Legacy compatibility: 26 clean / 6 documented session/reverse-request failures
  • Legacy handler and McpAgent: 29 clean / 3 documented failures each
  • optional server tasks: 9 documented failures / 1 referee skip
  • Stateless Worker dry-run: 616 KiB / 120 KiB gzip, versus 2,839 KiB / 527 KiB through the compatibility barrel
  • draft documentation update: [Agents] Add MCP SDK v2 migration guide cloudflare-docs#32175

Fixes #1848.

@changeset-bot

changeset-bot Bot commented May 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c38957c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
agents Minor
@cloudflare/codemode Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@mattzcarey mattzcarey changed the title chore(mcp): migrate agents to MCP SDK v2 packages feat(mcp): add SDK v2 createMcpHandler with v1 compatibility Jul 7, 2026
@mattzcarey
mattzcarey force-pushed the chore/mcp-sdk-v2-upgrade branch from bbb79a9 to 384c432 Compare July 7, 2026 12:51
@pkg-pr-new

pkg-pr-new Bot commented Jul 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@1557

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@1557

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@1557

create-think

npm i https://pkg.pr.new/create-think@1557

hono-agents

npm i https://pkg.pr.new/hono-agents@1557

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@1557

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@1557

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@1557

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@1557

commit: c38957c

@mattzcarey
mattzcarey marked this pull request as ready for review July 7, 2026 13:03

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@mattzcarey mattzcarey changed the title feat(mcp): add SDK v2 createMcpHandler with v1 compatibility feat(mcp): add stateless SDK v2 handler with v1 compatibility Jul 14, 2026
@mattzcarey
mattzcarey force-pushed the chore/mcp-sdk-v2-upgrade branch from 42ce495 to 8059e94 Compare July 14, 2026 10:57
@mattzcarey mattzcarey changed the title feat(mcp): add stateless SDK v2 handler with v1 compatibility feat(mcp): add SDK v2 client and stateless server support Jul 14, 2026
@mattzcarey
mattzcarey force-pushed the chore/mcp-sdk-v2-upgrade branch 2 times, most recently from c86cbec to 80a8fbd Compare July 14, 2026 18:15
@mattzcarey
mattzcarey force-pushed the chore/mcp-sdk-v2-upgrade branch from d163561 to 36971d9 Compare July 20, 2026 18:13
The SDK v2 handler intentionally leaves deployment validation to its host, but the Agents Worker wrapper previously delegated present Origin headers without a guard. Validate them against localhost-class hostnames by default, expose an explicit browser-host allowlist, and keep Origin-less non-browser clients working.

Also allow the modern Mcp-Method and Mcp-Name headers in default CORS preflights and remove the now-clean v2 conformance baselines.
@mattzcarey
mattzcarey force-pushed the chore/mcp-sdk-v2-upgrade branch from 6be2cac to c38957c Compare July 22, 2026 15:19
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.

MCP v2 typescript sdk

1 participant