Claude Opus 5.5

agents-0-20-0-18-b

Claude Code's read-only tools, web search on, ludion sync on

Question

How do I serve a stateless MCP server from a Worker with the Cloudflare agents package and the v2 MCP SDK?

Answer key

A correct answer says
`createMcpHandler` accepts a factory returning a v2 `McpServer`/`Server` from `@modelcontextprotocol/server` and serves stateless MCP with legacy compatibility; `createLegacyMcpHandler` remains for SDK v1 servers.
The stale answer
`createMcpHandler` takes an `McpServer` from `@modelcontextprotocol/sdk` (v1).

The change's lesson

Answer

Import `createMcpHandler` from `agents/mcp/server` and pass it a **factory function** that builds and returns a new SDK v2 `McpServer`, not a server instance. Then return the handler from your Worker's `fetch`:

```ts
import { createMcpHandler } from "agents/mcp/server";

export default {
  fetch: createMcpHandler(() => {
    const server = new McpServer({ name: "my-server", version: "1.0.0" });
    // register tools/resources here
    return server;
  }),
};
```

In agents 0.27.0, which this project has installed, a function passed to `createMcpHandler` is always treated as an SDK v2 factory. It returns a `StatelessMcpHandler` and gives each concurrent request its own server instance. So register tools inside the factory, and don't keep per-request state in a shared server at module scope. Passing an SDK v1 server instance still works but is deprecated (see `node_modules/agents/dist/agent-routing-Bhdbvf7s.d.ts:1187`). `createLegacyMcpHandler` exists only to keep the old sessionful v1 behavior while you migrate.

Answering cost $0.13.

Grade

correct

The judge's reason: It says createMcpHandler takes a factory returning an SDK v2 McpServer for stateless serving and that createLegacyMcpHandler remains for v1, without presenting the v1 instance form as current (it does omit the @modelcontextprotocol/server import path).

The judge's log

Session log

What the agent wrote, the tools it called, and what they returned, from docs/bench/2026-10-11-done3/runs/B-project-sync/agents-0-20-0-18-b.jsonl. Thinking and the session's settings are left out. The raw log

  1. Tool call: Grep

    {
      "pattern": "createMcpHandler",
      "path": "C:\\Users\\haya0\\AppData\\Local\\Temp\\ludion-bench-SM0BOb\\work",
      "glob": "*.d.ts",
      "output_mode": "content",
      "head_limit": 10
    }
  2. Tool output

    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1178: * New Stateless servers should use `createMcpHandler` from
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1188: * @deprecated Passing an SDK v1 server to createMcpHandler is deprecated and
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1190: * createMcpHandler. Use createLegacyMcpHandler only to temporarily retain
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1193:declare function createMcpHandler$1(
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1197:declare function createMcpHandler$1(
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1202: * @deprecated Pass an SDK v2 factory to createMcpHandler.
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1203: * experimental_createMcpHandler will be removed in the next major version.
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1207:declare function experimental_createMcpHandler(
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:1303: * createMcpHandler from agents/mcp/server. When sessionful features prevent an
    node_modules\agents\dist\agent-routing-Bhdbvf7s.d.ts:6974:  createMcpHandler$1 as cn,
    
    [Showing results with pagination = limit: 10]
  3. Tool call: Read

    {
      "file_path": "C:\\Users\\haya0\\AppData\\Local\\Temp\\ludion-bench-SM0BOb\\work\\node_modules\\agents\\dist\\agent-routing-Bhdbvf7s.d.ts",
      "offset": 1170,
      "limit": 45
    }
  4. Tool output

    1170	type LegacyMcpHandler = (
    1171	  request: Request,
    1172	  env: unknown,
    1173	  ctx: ExecutionContext
    1174	) => Promise<Response>;
    1175	/**
    1176	 * Create a sessionful Legacy MCP handler backed by SDK v1.
    1177	 *
    1178	 * New Stateless servers should use `createMcpHandler` from
    1179	 * `agents/mcp/server` instead.
    1180	 */
    1181	declare function createLegacyMcpHandler(
    1182	  server: McpServer$1 | Server$1,
    1183	  options?: CreateLegacyMcpHandlerOptions
    1184	): LegacyMcpHandler;
    1185	//#endregion
    1186	//#region src/mcp/server/handler-compat.d.ts
    1187	/**
    1188	 * @deprecated Passing an SDK v1 server to createMcpHandler is deprecated and
    1189	 * will be removed in the next major version. Pass an SDK v2 factory to
    1190	 * createMcpHandler. Use createLegacyMcpHandler only to temporarily retain
    1191	 * sessionful SDK v1 behavior while migrating.
    1192	 */
    1193	declare function createMcpHandler$1(
    1194	  server: McpServer$1 | Server$1,
    1195	  options?: CreateMcpHandlerOptions$1
    1196	): LegacyMcpHandler;
    1197	declare function createMcpHandler$1(
    1198	  factory: McpServerFactory,
    1199	  options?: CreateStatelessMcpHandlerOptions
    1200	): StatelessMcpHandler;
    1201	/**
    1202	 * @deprecated Pass an SDK v2 factory to createMcpHandler.
    1203	 * experimental_createMcpHandler will be removed in the next major version.
    1204	 * Use createLegacyMcpHandler only to temporarily retain sessionful SDK v1
    1205	 * behavior while migrating.
    1206	 */
    1207	declare function experimental_createMcpHandler(
    1208	  server: McpServer$1 | Server$1,
    1209	  options?: CreateMcpHandlerOptions$1
    1210	): LegacyMcpHandler;
    1211	//#endregion
    1212	//#region src/mcp/server/event-store.d.ts
    1213	/**
    1214	 * Durable Object–backed {@link EventStore} for SSE resumability.
  5. Agent

    Import `createMcpHandler` from `agents/mcp/server` and pass it a **factory function** that builds and returns a new SDK v2 `McpServer`, not a server instance. Then return the handler from your Worker's `fetch`:
    
    ```ts
    import { createMcpHandler } from "agents/mcp/server";
    
    export default {
      fetch: createMcpHandler(() => {
        const server = new McpServer({ name: "my-server", version: "1.0.0" });
        // register tools/resources here
        return server;
      }),
    };
    ```
    
    In agents 0.27.0, which this project has installed, a function passed to `createMcpHandler` is always treated as an SDK v2 factory. It returns a `StatelessMcpHandler` and gives each concurrent request its own server instance. So register tools inside the factory, and don't keep per-request state in a shared server at module scope. Passing an SDK v1 server instance still works but is deprecated (see `node_modules/agents/dist/agent-routing-Bhdbvf7s.d.ts:1187`). `createLegacyMcpHandler` exists only to keep the old sessionful v1 behavior while you migrate.