agents 0.14.0 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/{agent-tool-types-LInzZfLo.d.ts → agent-tool-types-V25Z_HcX.d.ts} +275 -122
  2. package/dist/agent-tool-types.d.ts +13 -11
  3. package/dist/{agent-tools-BAdX1vdI.js → agent-tools-3zLG7MgA.js} +49 -7
  4. package/dist/agent-tools-3zLG7MgA.js.map +1 -0
  5. package/dist/{agent-tools-BE9xosUG.d.ts → agent-tools-C-9s151X.d.ts} +2 -2
  6. package/dist/agent-tools.d.ts +13 -11
  7. package/dist/agent-tools.js +8 -3
  8. package/dist/agent-tools.js.map +1 -1
  9. package/dist/browser/ai.d.ts +1 -1
  10. package/dist/browser/ai.js +1 -1
  11. package/dist/browser/ai.js.map +1 -1
  12. package/dist/browser/index.d.ts +1 -1
  13. package/dist/browser/index.js +1 -1
  14. package/dist/browser/tanstack-ai.d.ts +1 -1
  15. package/dist/browser/tanstack-ai.js +1 -1
  16. package/dist/browser/tanstack-ai.js.map +1 -1
  17. package/dist/chat/index.d.ts +115 -8
  18. package/dist/chat/index.js +10 -6
  19. package/dist/chat/index.js.map +1 -1
  20. package/dist/chat-sdk/index.d.ts +5 -5
  21. package/dist/chat-sdk/index.js +2 -2
  22. package/dist/chat-sdk/index.js.map +1 -1
  23. package/dist/{classPrivateFieldGet2-Evpt0SEr.js → classPrivateFieldGet2-Beqsfu2Z.js} +5 -5
  24. package/dist/{classPrivateMethodInitSpec-bG0tD96O.js → classPrivateMethodInitSpec-B5ko1s2R.js} +2 -2
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/{client-NradHZZz.js → client-FUizKzj2.js} +94 -21
  27. package/dist/client-FUizKzj2.js.map +1 -0
  28. package/dist/client.d.ts +1 -1
  29. package/dist/{compaction-helpers-DpP_XP9J.d.ts → compaction-helpers-BEUILPss.d.ts} +1 -1
  30. package/dist/{compaction-helpers-BjT2NKRZ.js → compaction-helpers-iiKMr2TQ.js} +1 -1
  31. package/dist/{compaction-helpers-BjT2NKRZ.js.map → compaction-helpers-iiKMr2TQ.js.map} +1 -1
  32. package/dist/{do-oauth-client-provider-CPm9rK5I.d.ts → do-oauth-client-provider-D4ZwyBDu.d.ts} +21 -1
  33. package/dist/{email-1fTSJwPm.d.ts → email-CL27preh.d.ts} +1 -1
  34. package/dist/email.d.ts +2 -2
  35. package/dist/email.js.map +1 -1
  36. package/dist/experimental/memory/session/index.d.ts +1 -1
  37. package/dist/experimental/memory/session/index.js +1 -1
  38. package/dist/experimental/memory/session/index.js.map +1 -1
  39. package/dist/experimental/memory/utils/index.d.ts +1 -1
  40. package/dist/experimental/memory/utils/index.js +2 -2
  41. package/dist/experimental/webmcp.js.map +1 -1
  42. package/dist/{index-Brdu5nMI.d.ts → index-CPe1OtI0.d.ts} +17 -1
  43. package/dist/index.d.ts +71 -69
  44. package/dist/index.js +288 -84
  45. package/dist/index.js.map +1 -1
  46. package/dist/{internal_context-CcZy2Em7.d.ts → internal_context-Dg4Cgjcu.d.ts} +1 -1
  47. package/dist/internal_context.d.ts +1 -1
  48. package/dist/mcp/client.d.ts +14 -14
  49. package/dist/mcp/client.js +1 -1
  50. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  51. package/dist/mcp/do-oauth-client-provider.js +143 -17
  52. package/dist/mcp/do-oauth-client-provider.js.map +1 -1
  53. package/dist/mcp/index.d.ts +30 -30
  54. package/dist/mcp/index.js +1 -1
  55. package/dist/mcp/index.js.map +1 -1
  56. package/dist/mcp/x402.js.map +1 -1
  57. package/dist/observability/index.d.ts +1 -1
  58. package/dist/observability/index.js.map +1 -1
  59. package/dist/react.d.ts +3 -3
  60. package/dist/react.js +1 -1
  61. package/dist/react.js.map +1 -1
  62. package/dist/{retries-ClWwxADl.d.ts → retries-CF_HKSlJ.d.ts} +1 -1
  63. package/dist/retries.d.ts +1 -1
  64. package/dist/schedule.js.map +1 -1
  65. package/dist/serializable.d.ts +1 -1
  66. package/dist/{shared-CpY1FLvm.d.ts → shared-4CAYLCTO.d.ts} +1 -1
  67. package/dist/{shared-DdOn6sp4.js → shared-wyII629d.js} +3 -3
  68. package/dist/{shared-DdOn6sp4.js.map → shared-wyII629d.js.map} +1 -1
  69. package/dist/skills/index.js +4 -4
  70. package/dist/skills/index.js.map +1 -1
  71. package/dist/sub-routing.d.ts +6 -6
  72. package/dist/sub-routing.js.map +1 -1
  73. package/dist/{tool-output-truncation-BF4AZQlw.js → tool-output-truncation-CNnnGZQ3.js} +1 -1
  74. package/dist/{tool-output-truncation-BF4AZQlw.js.map → tool-output-truncation-CNnnGZQ3.js.map} +1 -1
  75. package/dist/{types-B0GymtN_.d.ts → types-6Zo2zfoO.d.ts} +1 -1
  76. package/dist/types.d.ts +1 -1
  77. package/dist/utils.js.map +1 -1
  78. package/dist/vite.d.ts +15 -4
  79. package/dist/vite.js +37 -7
  80. package/dist/vite.js.map +1 -1
  81. package/dist/{workflow-types-DPkuBi--.d.ts → workflow-types-SrZK_o9p.d.ts} +1 -1
  82. package/dist/workflow-types.d.ts +1 -1
  83. package/dist/workflows.d.ts +11 -3
  84. package/dist/workflows.js +48 -22
  85. package/dist/workflows.js.map +1 -1
  86. package/package.json +14 -23
  87. package/dist/agent-tools-BAdX1vdI.js.map +0 -1
  88. package/dist/client-NradHZZz.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/mcp/sse-keepalive.ts","../../src/mcp/utils.ts","../../src/mcp/transport.ts","../../src/mcp/event-store.ts","../../src/mcp/client-transports.ts","../../src/mcp/worker-transport.ts","../../src/mcp/auth-context.ts","../../src/mcp/handler.ts","../../src/mcp/index.ts"],"sourcesContent":["/**\n * Shared SSE keepalive utility for MCP transports.\n *\n * Cloudflare's edge closes idle SSE responses after ~5 minutes. Writers\n * that may sit silent for that long (long-running tool calls, idle\n * standalone GET streams) arm a keepalive to keep the response under the\n * watchdog.\n *\n * See cloudflare/agents#1583.\n */\n\n/** Interval between SSE keepalive comment frames, in ms.\n *\n * The WHATWG SSE spec recommends a comment line every \"15 seconds or so\"\n * (html.spec.whatwg.org §9.2.7). 25s gives comfortable headroom below\n * both the ~30s post-handler background-work cancellation window on\n * Workers and the ~5min Cloudflare edge idle-stream watchdog.\n */\nexport const KEEPALIVE_INTERVAL_MS = 25_000;\n\n/** SSE comment frame the parser drops before any event dispatch. */\nexport const KEEPALIVE_FRAME = \": keepalive\\n\\n\";\n\n/**\n * Start an SSE keepalive on `writer`. Returns a `clearInterval` handle\n * that the stream cleanup must invoke when the stream closes.\n */\nexport function startKeepalive(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n encoder: TextEncoder\n): ReturnType<typeof setInterval> {\n const handle = setInterval(() => {\n writer\n .write(encoder.encode(KEEPALIVE_FRAME))\n .catch(() => clearInterval(handle));\n }, KEEPALIVE_INTERVAL_MS);\n return handle;\n}\n","import {\n JSONRPCMessageSchema,\n type JSONRPCMessage,\n type MessageExtraInfo,\n InitializeRequestSchema,\n isJSONRPCResultResponse,\n isJSONRPCNotification\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpAgent } from \".\";\nimport { getAgentByName } from \"..\";\nimport type { CORSOptions } from \"./types\";\nimport { MessageType } from \"../types\";\nimport { startKeepalive } from \"./sse-keepalive\";\n\n/**\n * Since we use WebSockets to bridge the client to the\n * MCP transport in the Agent, we use this header to signal\n * the method of the original request the user made, while\n * leaving the WS Upgrade request as GET.\n */\nexport const MCP_HTTP_METHOD_HEADER = \"cf-mcp-method\";\n\n/**\n * Since we use WebSockets to bridge the client to the\n * MCP transport in the Agent, we use this header to include\n * the original request body.\n */\nexport const MCP_MESSAGE_HEADER = \"cf-mcp-message\";\n\nconst MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024; // 4MB\n\nexport const createStreamingHttpHandler = (\n basePath: string,\n namespace: DurableObjectNamespace<McpAgent>,\n options: {\n corsOptions?: CORSOptions;\n jurisdiction?: DurableObjectJurisdiction;\n } = {}\n) => {\n let pathname = basePath;\n if (basePath === \"/\") pathname = \"/*\";\n\n const basePattern = new URLPattern({ pathname });\n return async (request: Request, ctx: ExecutionContext) => {\n const url = new URL(request.url);\n if (basePattern.test(url)) {\n if (request.method === \"POST\") {\n // Validate the Accept header\n const acceptHeader = request.headers.get(\"accept\");\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (\n !acceptHeader?.includes(\"application/json\") ||\n !acceptHeader.includes(\"text/event-stream\")\n ) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message:\n \"Not Acceptable: Client must accept both application/json and text/event-stream\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 406 });\n }\n\n const ct = request.headers.get(\"content-type\");\n if (!ct || !ct.includes(\"application/json\")) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message:\n \"Unsupported Media Type: Content-Type must be application/json\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 415 });\n }\n\n // Check content length against maximum allowed size\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 413 });\n }\n\n let sessionId = request.headers.get(\"mcp-session-id\");\n let rawMessage: unknown;\n\n try {\n rawMessage = await request.json();\n } catch (_error) {\n const body = JSON.stringify({\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // Make sure the message is an array to simplify logic\n let arrayMessage: unknown[];\n if (Array.isArray(rawMessage)) {\n arrayMessage = rawMessage;\n } else {\n arrayMessage = [rawMessage];\n }\n\n let messages: JSONRPCMessage[] = [];\n\n // Try to parse each message as JSON RPC. Fail if any message is invalid\n for (const msg of arrayMessage) {\n if (!JSONRPCMessageSchema.safeParse(msg).success) {\n const body = JSON.stringify({\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON-RPC message\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n }\n\n messages = arrayMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n\n // Before we pass the messages to the agent, there's another error condition we need to enforce\n // Check if this is an initialization request\n // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/\n const maybeInitializeRequest = messages.find(\n (msg) => InitializeRequestSchema.safeParse(msg).success\n );\n\n if (!!maybeInitializeRequest && sessionId) {\n const body = JSON.stringify({\n error: {\n code: -32600,\n message:\n \"Invalid Request: Initialization requests must not include a sessionId\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // The initialization request must be the only request in the batch\n if (!!maybeInitializeRequest && messages.length > 1) {\n const body = JSON.stringify({\n error: {\n code: -32600,\n message:\n \"Invalid Request: Only one initialization request is allowed\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n if (!maybeInitializeRequest && !sessionId) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // If we don't have a sessionId, we are serving an initialization request\n // and need to generate a new sessionId\n sessionId = sessionId ?? namespace.newUniqueId().toString();\n\n // Get the agent and set props\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`,\n {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n }\n );\n const isInitialized = await agent.getInitializeRequest();\n\n if (maybeInitializeRequest) {\n await agent.setInitializeRequest(maybeInitializeRequest);\n } else if (!isInitialized) {\n // if we have gotten here, then a session id that was never initialized\n // was provided\n const body = JSON.stringify({\n error: {\n code: -32001,\n message: \"Session not found\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 404 });\n }\n\n // We've evaluated all the error conditions! Now it's time to establish\n // all the streams\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Connect to the Durable Object via WebSocket\n const existingHeaders: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n existingHeaders[key] = value;\n });\n\n const req = new Request(request.url, {\n headers: {\n ...existingHeaders,\n [MCP_HTTP_METHOD_HEADER]: \"POST\",\n [MCP_MESSAGE_HEADER]: Buffer.from(\n JSON.stringify(messages)\n ).toString(\"base64\"),\n Upgrade: \"websocket\"\n }\n });\n const response = await agent.fetch(req);\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n\n await writer.close();\n const body = JSON.stringify({\n error: {\n code: -32001,\n message: \"Failed to establish WebSocket connection\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 500 });\n }\n\n // Accept the WebSocket\n ws.accept();\n\n // If there are no requests, we send the messages to the agent and\n // acknowledge the request with a 202 since we don't expect any\n // responses back through this connection. Decide this *before*\n // arming a keepalive on the SSE writer so we don't leak a timer.\n const hasOnlyNotificationsOrResponses = messages.every(\n (msg) => isJSONRPCNotification(msg) || isJSONRPCResultResponse(msg)\n );\n if (hasOnlyNotificationsOrResponses) {\n // closing the websocket will also close the SSE connection\n ws.close();\n\n return new Response(null, {\n headers: corsHeaders(request, options.corsOptions),\n status: 202\n });\n }\n\n // Long-running tool calls can sit silent for many seconds while\n // the DO runs the handler. Arm a keepalive on the response stream\n // so the Cloudflare edge ~5min idle watchdog doesn't close us\n // before the tool result arrives. POST streams are scoped to a\n // specific request id and can't be resumed via Last-Event-ID,\n // so there's no alternative recovery path here.\n const keepAlive = startKeepalive(writer, encoder);\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const data =\n typeof event.data === \"string\"\n ? event.data\n : new TextDecoder().decode(event.data);\n const message = JSON.parse(data);\n\n // We only forward events from the MCP server\n if (message.type !== MessageType.CF_MCP_AGENT_EVENT) {\n return;\n }\n\n // Send the message as an SSE event\n await writer.write(encoder.encode(message.event));\n\n // If we have received all the responses, close the connection\n if (message.close) {\n clearInterval(keepAlive);\n ws?.close();\n await writer.close().catch(() => {});\n }\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(_error: Event) {\n clearInterval(keepAlive);\n await writer.close().catch(() => {});\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n clearInterval(keepAlive);\n await writer.close().catch(() => {});\n }\n onClose().catch(console.error);\n });\n\n // Return the SSE response. We handle closing the stream in the ws \"message\"\n // handler\n return new Response(readable, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n \"mcp-session-id\": sessionId,\n ...corsHeaders(request, options.corsOptions)\n },\n status: 200\n });\n } else if (request.method === \"GET\") {\n // Validate the Accept header\n const acceptHeader = request.headers.get(\"accept\");\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Not Acceptable: Client must accept text/event-stream\"\n },\n id: null\n });\n return new Response(body, { status: 406 });\n }\n\n // Require sessionId\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (!sessionId)\n return new Response(\n JSON.stringify({\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null,\n jsonrpc: \"2.0\"\n }),\n { status: 400 }\n );\n\n // Create SSE stream\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`,\n {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n }\n );\n const isInitialized = await agent.getInitializeRequest();\n if (!isInitialized) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: { code: -32001, message: \"Session not found\" },\n id: null\n }),\n { status: 404 }\n );\n }\n\n const existingHeaders: Record<string, string> = {};\n request.headers.forEach((v, k) => {\n existingHeaders[k] = v;\n });\n\n const response = await agent.fetch(\n new Request(request.url, {\n headers: {\n ...existingHeaders,\n [MCP_HTTP_METHOD_HEADER]: \"GET\",\n Upgrade: \"websocket\"\n }\n })\n );\n\n const ws = response.webSocket;\n if (!ws) {\n await writer.close();\n return new Response(\"Failed to establish WS to DO\", {\n status: 500\n });\n }\n ws.accept();\n\n // Forward DO messages as SSE\n ws.addEventListener(\"message\", (event) => {\n try {\n async function onMessage(ev: MessageEvent) {\n const data =\n typeof ev.data === \"string\"\n ? ev.data\n : new TextDecoder().decode(ev.data);\n const message = JSON.parse(data);\n\n // We only forward events from the MCP server\n if (message.type !== MessageType.CF_MCP_AGENT_EVENT) {\n return;\n }\n await writer.write(encoder.encode(message.event));\n }\n onMessage(event).catch(console.error);\n } catch (e) {\n console.error(\"Error forwarding message to SSE:\", e);\n }\n });\n\n ws.addEventListener(\"error\", () => {\n writer.close().catch(() => {});\n });\n ws.addEventListener(\"close\", () => {\n writer.close().catch(() => {});\n });\n\n return new Response(readable, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n \"mcp-session-id\": sessionId,\n ...corsHeaders(request, options.corsOptions)\n },\n status: 200\n });\n } else if (request.method === \"DELETE\") {\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (!sessionId) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null\n }),\n { status: 400, headers: corsHeaders(request, options.corsOptions) }\n );\n }\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`,\n { jurisdiction: options.jurisdiction }\n );\n const isInitialized = await agent.getInitializeRequest();\n if (!isInitialized) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: { code: -32001, message: \"Session not found\" },\n id: null\n }),\n { status: 404, headers: corsHeaders(request, options.corsOptions) }\n );\n }\n // .destroy() passes an uncatchable Error, so we make sure we first return\n // the response to the client.\n ctx.waitUntil(\n agent.destroy().catch(() => {\n /* This will always throw. We silently catch here */\n })\n );\n return new Response(null, {\n status: 204,\n headers: corsHeaders(request, options.corsOptions)\n });\n }\n }\n\n // Route not found\n const body = JSON.stringify({\n error: {\n code: -32000,\n message: \"Not found\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 404 });\n };\n};\n\nexport const createLegacySseHandler = (\n basePath: string,\n namespace: DurableObjectNamespace<McpAgent>,\n options: {\n corsOptions?: CORSOptions;\n jurisdiction?: DurableObjectJurisdiction;\n } = {}\n) => {\n let pathname = basePath;\n if (basePath === \"/\") pathname = \"/*\";\n\n const basePattern = new URLPattern({ pathname });\n const messagePattern = new URLPattern({ pathname: `${basePath}/message` }); // SSE only\n return async (request: Request, ctx: ExecutionContext) => {\n const url = new URL(request.url);\n // Handle initial SSE connection\n if (request.method === \"GET\" && basePattern.test(url)) {\n // Use a session ID if one is passed in, or create a unique\n // session ID for this connection\n const sessionId =\n url.searchParams.get(\"sessionId\") || namespace.newUniqueId().toString();\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Send the endpoint event\n const endpointUrl = new URL(request.url);\n endpointUrl.pathname = encodeURI(`${basePath}/message`);\n endpointUrl.searchParams.set(\"sessionId\", sessionId);\n const relativeUrlWithSession =\n endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;\n const endpointMessage = `event: endpoint\\ndata: ${relativeUrlWithSession}\\n\\n`;\n writer.write(encoder.encode(endpointMessage));\n\n // Get the Durable Object\n const agent = await getAgentByName(namespace, `sse:${sessionId}`, {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n });\n\n // Connect to the Durable Object via WebSocket\n const existingHeaders: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n existingHeaders[key] = value;\n });\n const response = await agent.fetch(\n new Request(request.url, {\n headers: {\n ...existingHeaders,\n [MCP_HTTP_METHOD_HEADER]: \"SSE\",\n Upgrade: \"websocket\"\n }\n })\n );\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n await writer.close();\n return new Response(\"Failed to establish WebSocket connection\", {\n status: 500\n });\n }\n\n // Accept the WebSocket\n ws.accept();\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const message = JSON.parse(event.data);\n\n // validate that the message is a valid JSONRPC message\n const result = JSONRPCMessageSchema.safeParse(message);\n if (!result.success) {\n // The message was not a valid JSONRPC message, so we will drop it\n // PartyKit will broadcast state change messages to all connected clients\n // and we need to filter those out so they are not passed to MCP clients\n return;\n }\n\n // Send the message as an SSE event\n const messageText = `event: message\\ndata: ${JSON.stringify(result.data)}\\n\\n`;\n await writer.write(encoder.encode(messageText));\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(_error: Event) {\n try {\n await writer.close();\n } catch (_e) {\n // Ignore errors when closing\n }\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n try {\n await writer.close();\n } catch (error) {\n console.error(\"Error closing SSE connection:\", error);\n }\n }\n onClose().catch(console.error);\n });\n\n // Return the SSE response\n return new Response(readable, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n ...corsHeaders(request, options.corsOptions)\n }\n });\n }\n\n // Handle incoming MCP messages. These will be passed to McpAgent\n // but the response will be sent back via the open SSE connection\n // so we only need to return a 202 Accepted response for success\n if (request.method === \"POST\" && messagePattern.test(url)) {\n const sessionId = url.searchParams.get(\"sessionId\");\n if (!sessionId) {\n return new Response(\n `Missing sessionId. Expected POST to ${basePath} to initiate new one`,\n { status: 400 }\n );\n }\n\n const contentType = request.headers.get(\"content-type\") || \"\";\n if (!contentType.includes(\"application/json\")) {\n return new Response(`Unsupported content-type: ${contentType}`, {\n status: 400\n });\n }\n\n // check if the request body is too large\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") || \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n return new Response(`Request body too large: ${contentLength} bytes`, {\n status: 400\n });\n }\n\n // Get the Durable Object\n const agent = await getAgentByName(namespace, `sse:${sessionId}`, {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n });\n\n const messageBody = await request.json();\n\n // Build MessageExtraInfo with filtered headers\n const headers = Object.fromEntries(request.headers.entries());\n\n const extraInfo: MessageExtraInfo = {\n requestInfo: { headers }\n };\n\n const error = await agent.onSSEMcpMessage(\n sessionId,\n messageBody,\n extraInfo\n );\n\n if (error) {\n return new Response(error.message, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n ...corsHeaders(request, options.corsOptions)\n },\n status: 400\n });\n }\n\n return new Response(\"Accepted\", {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n ...corsHeaders(request, options.corsOptions)\n },\n status: 202\n });\n }\n\n return new Response(\"Not Found\", { status: 404 });\n };\n};\n\n/**\n * Auto-negotiating handler that serves both streamable HTTP and legacy SSE\n * on the same path. Streamable-HTTP-capable clients are preferred; legacy SSE\n * clients fall back transparently.\n *\n * Discrimination rules:\n * - POST to `{basePath}/message` → legacy SSE (the sub-path is SSE-only)\n * - POST to `{basePath}` → streamable HTTP\n * - GET with `mcp-session-id` header → streamable HTTP (standalone SSE reconnect)\n * - GET without `mcp-session-id` → legacy SSE (new SSE connection)\n * - DELETE → streamable HTTP (SSE has no session teardown)\n */\nexport const createAutoHandler = (\n basePath: string,\n namespace: DurableObjectNamespace<McpAgent>,\n options: {\n corsOptions?: CORSOptions;\n jurisdiction?: DurableObjectJurisdiction;\n } = {}\n) => {\n const handleStreamableHttp = createStreamingHttpHandler(\n basePath,\n namespace,\n options\n );\n const handleLegacySse = createLegacySseHandler(basePath, namespace, options);\n\n const messagePattern = new URLPattern({\n pathname: `${basePath}/message`\n });\n\n return async (request: Request, ctx: ExecutionContext) => {\n const url = new URL(request.url);\n\n if (request.method === \"DELETE\") {\n return handleStreamableHttp(request, ctx);\n }\n\n if (request.method === \"POST\" && messagePattern.test(url)) {\n return handleLegacySse(request, ctx);\n }\n\n if (request.method === \"POST\") {\n return handleStreamableHttp(request, ctx);\n }\n\n if (request.method === \"GET\" && request.headers.has(\"mcp-session-id\")) {\n return handleStreamableHttp(request, ctx);\n }\n\n if (request.method === \"GET\") {\n return handleLegacySse(request, ctx);\n }\n\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: {\n Allow: \"GET, POST, DELETE\",\n ...corsHeaders(request, options.corsOptions)\n }\n });\n };\n};\n\n// CORS helper functions\nexport function corsHeaders(_request: Request, corsOptions: CORSOptions = {}) {\n const origin = corsOptions.origin || \"*\";\n const headers =\n corsOptions.headers ||\n \"Content-Type, Accept, Authorization, mcp-session-id, mcp-protocol-version\";\n\n return {\n \"Access-Control-Allow-Headers\": headers,\n \"Access-Control-Allow-Methods\":\n corsOptions.methods || \"GET, POST, DELETE, OPTIONS\",\n \"Access-Control-Allow-Origin\": origin,\n \"Access-Control-Expose-Headers\":\n corsOptions.exposeHeaders || \"mcp-session-id\",\n \"Access-Control-Max-Age\": (corsOptions.maxAge || 86400).toString()\n };\n}\n\nexport function handleCORS(\n request: Request,\n corsOptions?: CORSOptions\n): Response | null {\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders(request, corsOptions) });\n }\n\n return null;\n}\n\nexport function isDurableObjectNamespace(\n namespace: unknown\n): namespace is DurableObjectNamespace<McpAgent> {\n return (\n typeof namespace === \"object\" &&\n namespace !== null &&\n \"newUniqueId\" in namespace &&\n typeof namespace.newUniqueId === \"function\" &&\n \"idFromName\" in namespace &&\n typeof namespace.idFromName === \"function\"\n );\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n type MessageExtraInfo,\n type RequestInfo,\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n type JSONRPCMessage,\n JSONRPCMessageSchema,\n type RequestId\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport type {\n EventStore,\n StreamId,\n EventId\n} from \"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js\";\nimport { getCurrentAgent, type Connection } from \"..\";\nimport type { McpAgent } from \".\";\nimport { MessageType } from \"../types\";\nimport { MCP_HTTP_METHOD_HEADER, MCP_MESSAGE_HEADER } from \"./utils\";\n\nexport type { EventStore, StreamId, EventId };\n\nexport class McpSSETransport implements Transport {\n sessionId: string;\n // Set by the server in `server.connect(transport)`\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n private _getWebSocket: () => WebSocket | null;\n private _started = false;\n constructor() {\n const { agent } = getCurrentAgent<McpAgent>();\n if (!agent)\n throw new Error(\"McpAgent was not found in Transport constructor\");\n\n this.sessionId = agent.getSessionId();\n this._getWebSocket = () => agent.getWebSocket();\n }\n\n async start() {\n // The transport does not manage the WebSocket connection since it's terminated\n // by the Durable Object in order to allow hibernation. There's nothing to initialize.\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n async send(message: JSONRPCMessage) {\n if (!this._started) {\n throw new Error(\"Transport not started\");\n }\n const websocket = this._getWebSocket();\n if (!websocket) {\n throw new Error(\"WebSocket not connected\");\n }\n try {\n websocket.send(JSON.stringify(message));\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n\n async close() {\n // Similar to start, the only thing to do is to pass the event on to the server\n this.onclose?.();\n }\n}\n\n/**\n * Configuration options for StreamableHTTPServerTransport\n */\nexport interface StreamableHTTPServerTransportOptions {\n /**\n * Event store for resumability support.\n * If provided, resumability will be enabled, allowing clients to\n * reconnect and resume messages.\n *\n * If the store also implements {@link ClearableEventStore.clearStream}\n * the transport will call it after the final response of a POST\n * stream is written, so storage stays bounded without any background\n * sweep. {@link DurableObjectEventStore} is the canonical example.\n */\n eventStore?: EventStore | ClearableEventStore;\n}\n\n/**\n * An {@link EventStore} that supports dropping all events for a single\n * stream id. Implemented by {@link DurableObjectEventStore}.\n */\nexport interface ClearableEventStore extends EventStore {\n clearStream(streamId: StreamId): Promise<void>;\n}\n\nfunction isClearableEventStore(\n store: EventStore | ClearableEventStore\n): store is ClearableEventStore {\n return typeof (store as ClearableEventStore).clearStream === \"function\";\n}\n\n/**\n * Adapted from: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/client/streamableHttp.ts\n * - Validation and initialization are removed as they're handled in `McpAgent.serve()` handler.\n * - Replaces the Node-style `req`/`res` with Worker's `Request`.\n * - Writes events as WS messages that the Worker forwards to the client as SSE events.\n * - Replaces the in-memory maps that track requestID/stream by using `connection.setState()` and `agent.getConnections()`.\n *\n * Besides these points, the implementation is the same and should be updated to match the original as new features are added.\n */\n/** Fixed streamId for the standalone GET listen stream. */\nconst STANDALONE_STREAM_ID = \"_GET_stream\";\n\n/** State persisted on each WebSocket connection by the transport. */\ntype TransportConnState = {\n /** Stable identifier for the SSE stream this connection serves.\n * Used as the event-store key. Survives WS reconnects via Last-Event-ID. */\n streamId?: string;\n /** True iff this connection is the standalone GET listen stream. */\n _standaloneSse?: boolean;\n /** Request ids whose responses must flow through this connection. */\n requestIds?: RequestId[];\n};\n\nexport class StreamableHTTPServerTransport implements Transport {\n private _started = false;\n private _eventStore?: EventStore | ClearableEventStore;\n\n // This tracks which messages on each POST stream have been answered.\n // It is fine that we do not persist this since it only supports backwards\n // compatibility for clients batching requests, which the spec discourages.\n // Keying by stream avoids colliding ids on independent POST streams sharing\n // completion state with one another.\n private _streamResponseIds: Map<string, Set<RequestId>> = new Map();\n\n sessionId: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n /**\n * Optional message interceptor that can intercept messages before they are passed to onmessage.\n * If the interceptor returns true, the message is considered handled and won't be forwarded.\n * This is used by McpAgent to intercept elicitation responses.\n */\n messageInterceptor?: (\n message: JSONRPCMessage,\n extra?: MessageExtraInfo\n ) => Promise<boolean>;\n\n constructor(options: StreamableHTTPServerTransportOptions) {\n const { agent } = getCurrentAgent<McpAgent>();\n if (!agent)\n throw new Error(\"McpAgent was not found in Transport constructor\");\n\n // Initialization is handled in `McpAgent.serve()` and agents are addressed by sessionId,\n // so we'll always have this available.\n this.sessionId = agent.getSessionId();\n this._eventStore = options.eventStore;\n }\n\n /**\n * Starts the transport. This is required by the Transport interface but is a no-op\n * for the Streamable HTTP transport as connections are managed per-request.\n */\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n /**\n * Handles GET requests for SSE stream.\n *\n * Two roles a GET can play:\n * 1. Fresh standalone listen stream — carries server-initiated\n * requests/notifications unrelated to any in-progress POST.\n * 2. Resumption of a previously-disconnected stream via\n * `Last-Event-ID`. The disconnected stream may have been the\n * standalone stream OR a POST tool-call response stream; per the\n * MCP 2025-03-26 spec the server replays missed messages \"on the\n * stream that was disconnected\" and continues delivering\n * subsequent messages on that same stream.\n *\n * To resume a POST stream we recover the original streamId from the\n * event-store and the original `requestIds` from durable storage,\n * then write them onto the new WS connection so `send()` keeps\n * routing in-flight tool responses to it.\n */\n async handleGetRequest(req: Request): Promise<void> {\n const { connection, agent } = getCurrentAgent<McpAgent>();\n if (!connection)\n throw new Error(\"Connection was not found in handleGetRequest\");\n if (!agent) throw new Error(\"Agent was not found in handleGetRequest\");\n\n const lastEventId = req.headers.get(\"last-event-id\");\n\n // Resume path: the client identifies which stream it lost via\n // Last-Event-ID. Recover the original streamId from the event\n // store and register this connection under it. Matches the SDK\n // reference implementation (typescript-sdk's `replayEvents`):\n // the resumed connection is mapped to the *original* streamId,\n // no dual-role tagging.\n //\n // Forward routing then depends on what kind of stream it was:\n // - active POST: persisted requestIds are restored so further\n // tool responses route to this new WS via state.requestIds.\n // - standalone listen stream: tag with _standaloneSse so\n // server-initiated notifications continue to land here.\n // - completed POST / unknown: this connection is a one-shot\n // replay channel. No future messages will be routed to it.\n //\n // In every resumable case we supersede any prior connection bound\n // to the same streamId by closing it, so there is at most one live\n // connection per stream. This keeps `send()` routing deterministic\n // and keeps us within the MCP rule that each message goes out on\n // exactly one stream.\n if (this._eventStore && lastEventId) {\n const resumedStreamId =\n await this._eventStore.getStreamIdForEventId?.(lastEventId);\n if (resumedStreamId) {\n const resumeState: TransportConnState = {\n streamId: resumedStreamId\n };\n if (resumedStreamId === STANDALONE_STREAM_ID) {\n resumeState._standaloneSse = true;\n } else {\n const persistedReqs =\n await agent.getStreamRequestIds(resumedStreamId);\n if (persistedReqs && persistedReqs.length > 0) {\n resumeState.requestIds = persistedReqs;\n }\n }\n this.supersedePriorStreamConnections(\n agent,\n connection.id,\n resumedStreamId\n );\n connection.setState(resumeState);\n await this.replayEvents(lastEventId);\n return;\n }\n }\n\n // Fresh standalone listen stream. The MCP spec allows only one\n // standalone GET per session, so supersede any existing one.\n this.supersedePriorStreamConnections(\n agent,\n connection.id,\n STANDALONE_STREAM_ID\n );\n const standaloneState: TransportConnState = {\n streamId: STANDALONE_STREAM_ID,\n _standaloneSse: true\n };\n connection.setState(standaloneState);\n }\n\n /**\n * Close any connection (other than `selfId`) currently bound to\n * `streamId`, so at most one live connection serves a given stream.\n * Closing rather than mutating sibling state mirrors how the SDK's\n * single `_streamMapping` entry gives last-writer-wins for free, and\n * keeps `send()` from routing to a stale bridge.\n */\n private supersedePriorStreamConnections(\n agent: McpAgent,\n selfId: string,\n streamId: string\n ): void {\n for (const other of agent.getConnections<TransportConnState>()) {\n if (other.id === selfId) continue;\n if (other.state?.streamId !== streamId) continue;\n other.close(1000, \"Superseded by resumed stream\");\n }\n }\n\n /**\n * Replays events that would have been sent after the specified event ID\n * Only used when resumability is enabled\n */\n private async replayEvents(lastEventId: string): Promise<void> {\n if (!this._eventStore) {\n return;\n }\n\n const { connection } = getCurrentAgent();\n if (!connection)\n throw new Error(\"Connection was not available in replayEvents\");\n\n try {\n await this._eventStore?.replayEventsAfter(lastEventId, {\n send: async (eventId: string, message: JSONRPCMessage) => {\n try {\n this.writeSSEEvent(connection, message, eventId);\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n });\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n\n /**\n * Writes an event to the SSE stream with proper formatting\n */\n private writeSSEEvent(\n connection: Connection,\n message: JSONRPCMessage,\n eventId?: string,\n close?: boolean\n ) {\n let eventData = \"event: message\\n\";\n // Include event ID if provided - this is important for resumability\n if (eventId) {\n eventData += `id: ${eventId}\\n`;\n }\n eventData += `data: ${JSON.stringify(message)}\\n\\n`;\n\n return connection.send(\n JSON.stringify({\n type: MessageType.CF_MCP_AGENT_EVENT,\n event: eventData,\n close\n })\n );\n }\n\n /**\n * Handles POST requests containing JSON-RPC messages\n */\n async handlePostRequest(\n req: Request & { auth?: AuthInfo },\n parsedBody: unknown\n ): Promise<void> {\n const authInfo: AuthInfo | undefined = req.auth;\n const requestInfo: RequestInfo = {\n headers: Object.fromEntries(req.headers.entries()),\n url: new URL(req.url)\n };\n // Remove headers that are not part of the original request\n delete requestInfo.headers[MCP_HTTP_METHOD_HEADER];\n delete requestInfo.headers[MCP_MESSAGE_HEADER];\n delete requestInfo.headers.upgrade;\n\n const rawMessage = parsedBody;\n let messages: JSONRPCMessage[];\n\n // handle batch and single messages\n if (Array.isArray(rawMessage)) {\n messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n } else {\n messages = [JSONRPCMessageSchema.parse(rawMessage)];\n }\n\n // check if it contains requests\n const hasRequests = messages.some(isJSONRPCRequest);\n\n if (!hasRequests) {\n // We process without sending anything\n for (const message of messages) {\n // check if message should be intercepted (i.e. elicitation responses)\n if (this.messageInterceptor) {\n const handled = await this.messageInterceptor(message, {\n authInfo,\n requestInfo\n });\n if (handled) {\n continue; // msg was handled by interceptor, skip onmessage\n }\n }\n this.onmessage?.(message, { authInfo, requestInfo });\n }\n } else if (hasRequests) {\n const { connection, agent } = getCurrentAgent<McpAgent>();\n if (!connection)\n throw new Error(\"Connection was not found in handlePostRequest\");\n if (!agent) throw new Error(\"Agent was not found in handlePostRequest\");\n\n // We need to track by request ID to maintain the connection\n const requestIds = messages\n .filter(isJSONRPCRequest)\n .map((message) => message.id);\n\n // The streamId is stable for the lifetime of this POST's stream.\n // We seed it with the WS connection id (unique per POST), and a\n // resumed GET later inherits the *same* streamId via Last-Event-ID.\n const streamId = connection.id;\n const postState: TransportConnState = { streamId, requestIds };\n connection.setState(postState);\n\n // Persist the mapping so a future GET-with-Last-Event-ID can\n // restore `requestIds` onto a fresh WS connection. Only relevant\n // when an event store is configured — without one the client has\n // no `id:` to resume from anyway. Cleaned up in `send()` on the\n // final response.\n if (this._eventStore) {\n await agent.setStreamRequestIds(streamId, requestIds);\n }\n\n // handle each message\n for (const message of messages) {\n if (this.messageInterceptor) {\n const handled = await this.messageInterceptor(message, {\n authInfo,\n requestInfo\n });\n if (handled) {\n continue; // Message was handled by interceptor, skip onmessage\n }\n }\n this.onmessage?.(message, { authInfo, requestInfo });\n }\n // The server SHOULD NOT close the SSE stream before sending all JSON-RPC responses\n // This will be handled by the send() method when responses are ready\n }\n }\n\n async close(): Promise<void> {\n // Close all SSE connections\n const { agent } = getCurrentAgent();\n if (!agent) throw new Error(\"Agent was not found in close\");\n\n for (const conn of agent.getConnections()) {\n conn.close(1000, \"Session closed\");\n }\n this.onclose?.();\n }\n\n /**\n * Store the event, decide whether this is the final response, write\n * the SSE frame iff a live connection is attached, then run cleanup.\n * Caller resolves `streamId` and `relatedIds` (from connection state\n * or persisted reverse lookup) and passes `liveConnection` as null\n * when the originating WS has dropped.\n */\n private async sendOnStream(\n agent: McpAgent,\n streamId: string,\n relatedIds: readonly RequestId[],\n liveConnection: Connection<TransportConnState> | null,\n message: JSONRPCMessage,\n requestId: RequestId\n ): Promise<void> {\n const eventId = await this._eventStore?.storeEvent(streamId, message);\n\n let shouldClose = false;\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n let responseIds = this._streamResponseIds.get(streamId);\n if (!responseIds) {\n responseIds = new Set<RequestId>();\n this._streamResponseIds.set(streamId, responseIds);\n }\n responseIds.add(requestId);\n shouldClose = relatedIds.every((id) => responseIds.has(id));\n if (shouldClose) this._streamResponseIds.delete(streamId);\n }\n\n // Write FIRST, clean up SECOND. Clearing before the write would\n // leave a mid-flight client with a wiped stream on reconnect.\n // `writeSSEEvent` is sync (enqueues, doesn't await), so the bytes\n // are committed before any cleanup await can interleave. Wrap in\n // try/catch so a dead WS can't skip cleanup and orphan the\n // stream-reqs + stored events.\n if (liveConnection) {\n try {\n this.writeSSEEvent(liveConnection, message, eventId, shouldClose);\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n\n if (shouldClose) {\n // A concurrent GET resume between these awaits would replay\n // events about to be deleted — benign.\n await agent.deleteStreamRequestIds(streamId);\n if (this._eventStore && isClearableEventStore(this._eventStore)) {\n await this._eventStore.clearStream(streamId);\n }\n }\n }\n\n async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId }\n ): Promise<void> {\n // Request-scoped (response / `relatedRequestId` notification) vs\n // server-initiated on the standalone GET stream. Two helpers.\n const isResponse =\n isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message);\n const requestId = isResponse ? message.id : options?.relatedRequestId;\n\n if (requestId === undefined) {\n if (isResponse) {\n throw new Error(\n \"Cannot send a response on a standalone SSE stream unless resuming a previous client request\"\n );\n }\n return this.sendStandalone(message);\n }\n\n return this.sendForRequest(message, requestId);\n }\n\n /**\n * Server-initiated message on the standalone GET stream. Stored under\n * a fixed streamId so it's replayable even when no live connection is\n * currently attached.\n *\n * Sent on exactly one stream, per MCP: \"the server MUST send each of\n * its JSON-RPC messages on only one of the connected streams; it MUST\n * NOT broadcast the same message across multiple streams.\"\n * `handleGetRequest` supersedes prior standalone connections, so\n * there is at most one to send on.\n */\n private async sendStandalone(message: JSONRPCMessage): Promise<void> {\n const { agent } = getCurrentAgent<McpAgent>();\n if (!agent) throw new Error(\"Agent was not found in send\");\n\n const eventId = await this._eventStore?.storeEvent(\n STANDALONE_STREAM_ID,\n message\n );\n\n const standalone = Array.from(\n agent.getConnections<TransportConnState>()\n ).find((conn) => conn.state?._standaloneSse);\n // No live standalone stream: the event is stored above and replays\n // when a client reconnects with Last-Event-ID. Per spec the server\n // MAY send on the stream, so dropping the live write is fine.\n if (standalone) {\n this.writeSSEEvent(standalone, message, eventId);\n }\n }\n\n /**\n * Message scoped to a specific in-flight client request: a tool\n * response, error, or progress notification. Resolves which stream\n * owns the request id (live POST connection, resumed GET, or\n * persisted reverse lookup for a dropped WS) and delegates to\n * {@link sendOnStream} for the actual store / write / cleanup.\n */\n private async sendForRequest(\n message: JSONRPCMessage,\n requestId: RequestId\n ): Promise<void> {\n const { agent, connection: originatingConnection } =\n getCurrentAgent<McpAgent>();\n if (!agent) throw new Error(\"Agent was not found in send\");\n\n // Pick the live connection that should receive this message. Normally\n // request ids uniquely identify a POST connection. If a client violates\n // that constraint, prefer the connection whose handler is currently\n // producing this message rather than leaking a plausible response to\n // the first matching POST stream. Only prefer an originating connection\n // while it is still live: after a POST stream disconnects, a resumed\n // GET connection inherits requestIds and must be allowed to receive\n // the eventual response.\n const matchingConnections = Array.from(\n agent.getConnections<TransportConnState>()\n ).filter((conn) => conn.state?.requestIds?.includes(requestId));\n const liveConnection =\n matchingConnections.find(\n (conn) => conn.id === originatingConnection?.id\n ) ?? (matchingConnections.length === 1 ? matchingConnections[0] : null);\n\n // Ambiguous routing: multiple live POST connections claim the same\n // request id, none of which is the originating connection. Terminate\n // each with a protocol error rather than guessing.\n if (!liveConnection && matchingConnections.length > 1) {\n const routingError: JSONRPCMessage = {\n jsonrpc: \"2.0\",\n id: requestId,\n error: { code: -32603, message: \"Internal error\" }\n };\n await Promise.all(\n matchingConnections.map((candidate) =>\n this.sendOnStream(\n agent,\n candidate.state?.streamId ?? candidate.id,\n candidate.state?.requestIds ?? [],\n candidate,\n routingError,\n requestId\n )\n )\n );\n return;\n }\n\n // Resolve streamId + relatedIds. Prefer the live connection's state;\n // when the originating WS has dropped fall back to the persisted\n // reverse lookup so the event can still be stored for replay —\n // mirrors the SDK's `_requestToStreamMapping` which outlives\n // connection loss.\n let streamId = liveConnection?.state?.streamId;\n let relatedIds = liveConnection?.state?.requestIds;\n if (!streamId) {\n const stored = await agent.getStreamForRequestId(requestId);\n if (!stored) {\n throw new Error(\n `No active stream found for request ID: ${String(requestId)}`\n );\n }\n streamId = stored.streamId;\n relatedIds = stored.requestIds;\n }\n\n await this.sendOnStream(\n agent,\n streamId,\n relatedIds ?? [],\n liveConnection,\n message,\n requestId\n );\n }\n}\n","import type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n EventStore,\n EventId,\n StreamId\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\n\n/**\n * Durable Object–backed {@link EventStore} for SSE resumability.\n *\n * Default for `McpAgent`. Override `McpAgent.getEventStore()` to swap\n * or disable.\n *\n * ## Storage layout\n *\n * Events are stored under `__mcp_event__:<streamId>:<seqHex>`, where\n * `<seqHex>` is a 16-char zero-padded counter so events in a stream\n * sort lexicographically and `getStreamIdForEventId` can recover the\n * stream from `eventId` without a storage hit.\n *\n * ## Lifecycle\n *\n * Each POST tool-call stream's events live only until the final\n * response is delivered. The transport calls {@link clearStream}\n * immediately after writing the close frame, so storage growth is\n * bounded by the in-flight POST streams plus the standalone GET\n * stream. There is no background sweep — quiescent agents do no work,\n * and the DO itself dies with the session.\n *\n * Standalone GET stream events (`_GET_stream`) are *not* cleared\n * automatically; they accumulate for the lifetime of the DO. Bounded\n * by session length in practice.\n *\n * Trade-off: if the client TCP connection dies *after* the close\n * frame has been enqueued on the WS but before the bytes reach the\n * client, the final message is unreplayable. Every earlier event in\n * the stream is still replayable while the in-flight stream is open.\n *\n * ## Stream id constraints\n *\n * `streamId` MUST NOT contain `:`. `storeEvent` asserts this so\n * embedders using custom stream ids fail loudly rather than risk\n * prefix-scan collisions (e.g. clearing `a` accidentally hitting\n * `a:b`). Default ids (`connection.id` UUIDs and the literal\n * `_GET_stream`) already satisfy this.\n */\nexport class DurableObjectEventStore implements EventStore {\n private static readonly EVENT_KEY_PREFIX = \"__mcp_event__:\";\n private static readonly SEQ_PAD = 16;\n /** DO storage caps multi-key delete at 128. */\n private static readonly DELETE_CHUNK = 128;\n /** Defensive ceiling on a single replay batch. A live stream's\n * event count is small (progress notifications + final result);\n * this is here so a pathological history can't OOM the DO. */\n private static readonly REPLAY_LIMIT = 1000;\n\n private readonly storage: DurableObjectStorage;\n\n /** In-memory seq counters per stream, rehydrated lazily from storage. */\n private readonly seqByStream = new Map<StreamId, number>();\n private readonly seqInit = new Map<StreamId, Promise<void>>();\n\n constructor(storage: DurableObjectStorage) {\n this.storage = storage;\n }\n\n async storeEvent(\n streamId: StreamId,\n message: JSONRPCMessage\n ): Promise<EventId> {\n if (streamId.includes(\":\")) {\n // Event keys are `__mcp_event__:<streamId>:<seqHex>` — a `:` in\n // streamId would let prefix scans cross stream boundaries.\n throw new Error(\n `DurableObjectEventStore: streamId must not contain ':' (got ${JSON.stringify(streamId)})`\n );\n }\n await this.ensureSeqLoaded(streamId);\n const seq = (this.seqByStream.get(streamId) ?? 0) + 1;\n this.seqByStream.set(streamId, seq);\n\n const seqHex = seq\n .toString(16)\n .padStart(DurableObjectEventStore.SEQ_PAD, \"0\");\n const eventId = `${streamId}:${seqHex}`;\n const eventKey = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${eventId}`;\n\n await this.storage.put(eventKey, message);\n return eventId;\n }\n\n async getStreamIdForEventId(eventId: EventId): Promise<StreamId | undefined> {\n const idx = eventId.lastIndexOf(\":\");\n return idx > 0 ? eventId.slice(0, idx) : undefined;\n }\n\n async replayEventsAfter(\n lastEventId: EventId,\n {\n send\n }: { send: (eventId: EventId, message: JSONRPCMessage) => Promise<void> }\n ): Promise<StreamId> {\n const streamId = await this.getStreamIdForEventId(lastEventId);\n if (!streamId) return \"\";\n\n const prefix = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${streamId}:`;\n // `list({ start })` is inclusive, and we want strictly-after\n // semantics. Appending `\\x00` (the smallest byte) to the last\n // event's key produces a key that sorts immediately after it, so\n // the list excludes the boundary event without a post-filter.\n const startKey = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${lastEventId}\\x00`;\n // DO `storage.list()` with no `limit` loads everything into memory.\n // Stream histories are normally small (progress events + result),\n // but cap the batch defensively. Clients can reconnect again to\n // drain past the cap if they ever produce that many events.\n const rows = await this.storage.list<JSONRPCMessage>({\n prefix,\n start: startKey,\n limit: DurableObjectEventStore.REPLAY_LIMIT\n });\n\n for (const [key, message] of rows) {\n const eventId = key.slice(\n DurableObjectEventStore.EVENT_KEY_PREFIX.length\n );\n await send(eventId, message);\n }\n return streamId;\n }\n\n /**\n * Drop the event log for a single stream. Called by the transport\n * immediately after a POST's final response has been written to the\n * wire — no future `Last-Event-ID` for this stream is expected to\n * resolve.\n *\n * Lists and deletes in chunks of {@link DELETE_CHUNK} (128, the DO\n * storage cap) so we never load the entire event log into memory.\n * After deleting, the next `list` call won't see the deleted keys,\n * so passing `start: <prefix>` again is enough — no cursor bookkeeping.\n */\n async clearStream(streamId: StreamId): Promise<void> {\n const prefix = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${streamId}:`;\n for (;;) {\n const rows = await this.storage.list({\n prefix,\n limit: DurableObjectEventStore.DELETE_CHUNK\n });\n if (rows.size === 0) break;\n await this.storage.delete([...rows.keys()]);\n }\n this.seqByStream.delete(streamId);\n this.seqInit.delete(streamId);\n }\n\n private async ensureSeqLoaded(streamId: StreamId): Promise<void> {\n if (this.seqByStream.has(streamId)) return;\n let pending = this.seqInit.get(streamId);\n if (!pending) {\n pending = (async () => {\n const prefix = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${streamId}:`;\n const rows = await this.storage.list({\n prefix,\n reverse: true,\n limit: 1\n });\n let seq = 0;\n for (const key of rows.keys()) {\n const parsed = Number.parseInt(key.slice(prefix.length), 16);\n if (Number.isFinite(parsed)) seq = parsed;\n }\n if (!this.seqByStream.has(streamId)) {\n this.seqByStream.set(streamId, seq);\n }\n })();\n this.seqInit.set(streamId, pending);\n }\n try {\n await pending;\n } finally {\n this.seqInit.delete(streamId);\n }\n }\n}\n","/**\n * Deprecated transport wrappers\n */\n\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { StreamableHTTPClientTransportOptions } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\nlet didWarnAboutSSEEdgeClientTransport = false;\n\n/**\n * @deprecated Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. This alias will be removed in the next major version.\n */\nexport class SSEEdgeClientTransport extends SSEClientTransport {\n constructor(url: URL, options: SSEClientTransportOptions) {\n super(url, options);\n if (!didWarnAboutSSEEdgeClientTransport) {\n didWarnAboutSSEEdgeClientTransport = true;\n console.warn(\n \"SSEEdgeClientTransport is deprecated. Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. SSEEdgeClientTransport will be removed in the next major version.\"\n );\n }\n }\n}\n\nlet didWarnAboutStreamableHTTPEdgeClientTransport = false;\n\n/**\n * @deprecated Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. This alias will be removed in the next major version.\n */\nexport class StreamableHTTPEdgeClientTransport extends StreamableHTTPClientTransport {\n constructor(url: URL, options: StreamableHTTPClientTransportOptions) {\n super(url, options);\n if (!didWarnAboutStreamableHTTPEdgeClientTransport) {\n didWarnAboutStreamableHTTPEdgeClientTransport = true;\n console.warn(\n \"StreamableHTTPEdgeClientTransport is deprecated. Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. StreamableHTTPEdgeClientTransport will be removed in the next major version.\"\n );\n }\n }\n}\n","/**\n * Based on webStandardStreamableHttp.ts (https://github.com/modelcontextprotocol/typescript-sdk/blob/main/packages/server/src/server/webStandardStreamableHttp.ts)\n */\n\nimport type {\n Transport,\n TransportSendOptions\n} from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n JSONRPCMessage,\n RequestId,\n RequestInfo,\n MessageExtraInfo,\n InitializeRequestParams\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n isInitializeRequest,\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n JSONRPCMessageSchema,\n SUPPORTED_PROTOCOL_VERSIONS\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { CORSOptions } from \"./types\";\nimport type {\n EventStore,\n EventId\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { startKeepalive } from \"./sse-keepalive\";\n\nconst MCP_PROTOCOL_VERSION_HEADER = \"MCP-Protocol-Version\";\n\nconst RESTORE_REQUEST_ID = \"__restore__\";\n\ninterface StreamMapping {\n writer?: WritableStreamDefaultWriter<Uint8Array>;\n encoder?: TextEncoder;\n resolveJson?: (response: Response) => void;\n cleanup: () => void;\n}\n\nexport interface MCPStorageApi {\n get(): Promise<TransportState | undefined> | TransportState | undefined;\n set(state: TransportState): Promise<void> | void;\n}\n\nexport interface TransportState {\n sessionId?: string;\n initialized: boolean;\n initializeParams?: InitializeRequestParams;\n}\n\nexport interface WorkerTransportOptions {\n /**\n * Function that generates a session ID for the transport.\n * The session ID SHOULD be globally unique and cryptographically secure.\n * Return undefined to disable session management (stateless mode).\n */\n sessionIdGenerator?: () => string;\n /**\n * Enable traditional Request/Response mode, this will disable streaming.\n */\n enableJsonResponse?: boolean;\n /**\n * Callback fired when a new session is initialized.\n */\n onsessioninitialized?: (sessionId: string) => void;\n /**\n * Callback fired when a session is closed via DELETE request.\n */\n onsessionclosed?: (sessionId: string) => void;\n corsOptions?: CORSOptions;\n /**\n * Optional storage api for persisting transport state.\n * Use this to store session state in Durable Object/Agent storage\n * so it survives hibernation/restart.\n */\n storage?: MCPStorageApi;\n /**\n * Event store for SSE resumability.\n *\n * When set, the transport assigns a globally-unique `id:` to each SSE\n * event and replays missed events when a client reconnects with the\n * `Last-Event-ID` header. Both GET (standalone listen stream) and POST\n * (tool response stream) events are stored and replayable per the\n * MCP 2025-03-26 spec.\n *\n * Configuring an event store **disables the server-side keepalive**\n * on the standalone GET stream — idle drops are recovered by\n * reconnect rather than prevented by writing bytes. Without an event\n * store, the GET stream still gets the 25s comment-frame keepalive\n * so long-lived idle listeners aren't closed by the Cloudflare edge\n * ~5min watchdog.\n *\n * POST response streams always get the keepalive regardless of this\n * setting: in-progress tool calls have no way to recover\n * mid-execution without staying connected, so we don't let the\n * stream drop in the first place.\n *\n * Bring your own {@link EventStore} implementation — e.g.\n * `new DurableObjectEventStore(this.ctx.storage)` when embedding\n * `WorkerTransport` inside a Durable Object / Agent. See\n * cloudflare/agents#1583.\n */\n eventStore?: EventStore;\n /**\n * Retry interval in milliseconds to suggest to clients in SSE retry field.\n * Controls client reconnection timing for polling behavior.\n */\n retryInterval?: number;\n}\n\nexport class WorkerTransport implements Transport {\n started = false;\n private initialized = false;\n private sessionIdGenerator?: () => string;\n private enableJsonResponse = false;\n private onsessioninitialized?: (sessionId: string) => void;\n private onsessionclosed?: (sessionId: string) => void;\n private standaloneSseStreamId = \"_GET_stream\";\n private streamMapping = new Map<string, StreamMapping>();\n private requestToStreamMapping = new Map<RequestId, string>();\n private requestResponseMap = new Map<RequestId, JSONRPCMessage>();\n private corsOptions?: CORSOptions;\n private storage?: MCPStorageApi;\n private stateRestored = false;\n private eventStore?: EventStore;\n private retryInterval?: number;\n private initializeParams?: TransportState[\"initializeParams\"];\n\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n constructor(options?: WorkerTransportOptions) {\n this.sessionIdGenerator = options?.sessionIdGenerator;\n this.enableJsonResponse = options?.enableJsonResponse ?? false;\n this.onsessioninitialized = options?.onsessioninitialized;\n this.onsessionclosed = options?.onsessionclosed;\n this.corsOptions = options?.corsOptions;\n this.storage = options?.storage;\n this.eventStore = options?.eventStore;\n this.retryInterval = options?.retryInterval;\n }\n\n /**\n * Restore transport state from persistent storage.\n * This is automatically called on start.\n */\n private async restoreState() {\n if (!this.storage || this.stateRestored) {\n return;\n }\n\n const state = await Promise.resolve(this.storage.get());\n\n if (state) {\n this.sessionId = state.sessionId;\n this.initialized = state.initialized;\n\n // Restore _clientCapabilities on the Server instance by replaying the original initialize request\n if (state.initializeParams && this.onmessage) {\n this.onmessage({\n jsonrpc: \"2.0\",\n id: RESTORE_REQUEST_ID,\n method: \"initialize\",\n params: state.initializeParams\n });\n }\n }\n\n this.stateRestored = true;\n }\n\n /**\n * Persist current transport state to storage.\n */\n private async saveState() {\n if (!this.storage) {\n return;\n }\n\n const state: TransportState = {\n sessionId: this.sessionId,\n initialized: this.initialized,\n initializeParams: this.initializeParams\n };\n\n await Promise.resolve(this.storage.set(state));\n }\n\n async start(): Promise<void> {\n if (this.started) {\n throw new Error(\"Transport already started\");\n }\n this.started = true;\n }\n\n /**\n * Validates the MCP-Protocol-Version header on incoming requests.\n *\n * This performs a simple check: if a version header is present, it must be\n * in the SUPPORTED_PROTOCOL_VERSIONS list. We do not track the negotiated\n * version or enforce version consistency across requests - the SDK handles\n * version negotiation during initialization, and we simply reject any\n * explicitly unsupported versions.\n *\n * - Header present and supported: Accept\n * - Header present and unsupported: 400 Bad Request\n * - Header missing: Accept (version validation is optional)\n */\n private validateProtocolVersion(request: Request): Response | undefined {\n const protocolVersion = request.headers.get(MCP_PROTOCOL_VERSION_HEADER);\n\n if (\n protocolVersion !== null &&\n !SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)\n ) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(\", \")})`\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n return undefined;\n }\n\n private getHeaders({ forPreflight }: { forPreflight?: boolean } = {}): Record<\n string,\n string\n > {\n const defaults: CORSOptions = {\n origin: \"*\",\n headers:\n \"Content-Type, Accept, Authorization, mcp-session-id, MCP-Protocol-Version\",\n methods: \"GET, POST, DELETE, OPTIONS\",\n exposeHeaders: \"mcp-session-id\",\n maxAge: 86400\n };\n\n const options = { ...defaults, ...this.corsOptions };\n\n // For OPTIONS preflight, return all CORS headers\n if (forPreflight) {\n return {\n \"Access-Control-Allow-Origin\": options.origin!,\n \"Access-Control-Allow-Headers\": options.headers!,\n \"Access-Control-Allow-Methods\": options.methods!,\n \"Access-Control-Max-Age\": options.maxAge!.toString()\n };\n }\n\n // For actual requests, only return origin and expose headers\n return {\n \"Access-Control-Allow-Origin\": options.origin!,\n \"Access-Control-Expose-Headers\": options.exposeHeaders!\n };\n }\n\n async handleRequest(\n request: Request,\n parsedBody?: unknown\n ): Promise<Response> {\n await this.restoreState();\n\n switch (request.method) {\n case \"OPTIONS\":\n return this.handleOptionsRequest(request);\n case \"GET\":\n return this.handleGetRequest(request);\n case \"POST\":\n return this.handlePostRequest(request, parsedBody);\n case \"DELETE\":\n return this.handleDeleteRequest(request);\n default:\n return this.handleUnsupportedRequest();\n }\n }\n\n private async handleGetRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"Accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Not Acceptable: Client must accept text/event-stream\"\n },\n id: null\n }),\n {\n status: 406,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const sessionError = this.validateSession(request);\n if (sessionError) {\n return sessionError;\n }\n\n // Validate protocol version on subsequent requests\n const versionError = this.validateProtocolVersion(request);\n if (versionError) {\n return versionError;\n }\n\n let streamId = this.standaloneSseStreamId;\n\n // Check for resumability via Last-Event-ID\n const lastEventId = request.headers.get(\"Last-Event-ID\");\n if (lastEventId && this.eventStore) {\n // Get the stream ID for this event if available\n const eventStreamId =\n await this.eventStore.getStreamIdForEventId?.(lastEventId);\n if (eventStreamId) {\n streamId = eventStreamId;\n }\n }\n\n if (this.streamMapping.get(streamId) !== undefined) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Conflict: Only one SSE stream is allowed per session\"\n },\n id: null\n }),\n {\n status: 409,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n const headers = new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n ...this.getHeaders()\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n // Keepalive policy on the standalone GET stream:\n // - eventStore configured → no keepalive. Idle drops are\n // recovered by clients reconnecting with Last-Event-ID.\n // - no eventStore → arm a 25s comment-frame keepalive so the\n // stream isn't closed by the Cloudflare edge ~5min idle\n // watchdog. Without an event store there is no recovery path,\n // so this preserves the pre-fix behaviour for callers who\n // haven't opted into resumability.\n // See cloudflare/agents#1583.\n const keepAlive = this.eventStore\n ? undefined\n : startKeepalive(writer, encoder);\n // `cleanup` reads `streamId` lazily so it stays correct across the\n // eventStore remap below.\n const cleanup = () => {\n if (keepAlive !== undefined) clearInterval(keepAlive);\n this.streamMapping.delete(streamId);\n writer.close().catch(() => {});\n };\n this.streamMapping.set(streamId, { writer, encoder, cleanup });\n\n // Write priming event with retry interval if configured\n if (this.retryInterval !== undefined) {\n await writer.write(encoder.encode(`retry: ${this.retryInterval}\\n\\n`));\n }\n\n // Replay events if resuming and eventStore is configured\n if (lastEventId && this.eventStore) {\n const replayedStreamId = await this.eventStore.replayEventsAfter(\n lastEventId,\n {\n send: async (eventId: EventId, message: JSONRPCMessage) => {\n const data = `id: ${eventId}\\nevent: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(encoder.encode(data));\n }\n }\n );\n // Update stream ID if different from what we had. Reuse the same\n // `cleanup` closure as above so any future teardown work (e.g.\n // tearing down a keepalive) is impossible to leak in this branch.\n if (replayedStreamId !== streamId) {\n this.streamMapping.delete(streamId);\n streamId = replayedStreamId;\n this.streamMapping.set(streamId, { writer, encoder, cleanup });\n }\n }\n\n return new Response(readable, { headers });\n }\n\n private async handlePostRequest(\n request: Request,\n parsedBody?: unknown\n ): Promise<Response> {\n const acceptHeader = request.headers.get(\"Accept\");\n if (\n !acceptHeader?.includes(\"application/json\") ||\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Not Acceptable: Client must accept both application/json and text/event-stream\"\n },\n id: null\n }),\n {\n status: 406,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const contentType = request.headers.get(\"Content-Type\");\n if (!contentType?.includes(\"application/json\")) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Unsupported Media Type: Content-Type must be application/json\"\n },\n id: null\n }),\n {\n status: 415,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n let rawMessage = parsedBody;\n if (rawMessage === undefined) {\n try {\n rawMessage = await request.json();\n } catch {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n }\n\n let messages: JSONRPCMessage[];\n try {\n if (Array.isArray(rawMessage)) {\n messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n } else {\n messages = [JSONRPCMessageSchema.parse(rawMessage)];\n }\n } catch {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON-RPC message\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const requestInfo: RequestInfo = {\n headers: Object.fromEntries(request.headers.entries()),\n url: new URL(request.url)\n };\n\n const isInitializationRequest = messages.some(isInitializeRequest);\n\n if (isInitializationRequest) {\n if (this.initialized && this.sessionId !== undefined) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message: \"Invalid Request: Server already initialized\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n if (messages.length > 1) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message:\n \"Invalid Request: Only one initialization request is allowed\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n this.sessionId = this.sessionIdGenerator?.();\n this.initialized = true;\n\n const initMessage = messages.find(isInitializeRequest);\n if (initMessage && isInitializeRequest(initMessage)) {\n this.initializeParams = {\n capabilities: initMessage.params.capabilities,\n clientInfo: initMessage.params.clientInfo,\n protocolVersion: initMessage.params.protocolVersion\n };\n }\n\n await this.saveState();\n\n if (this.sessionId && this.onsessioninitialized) {\n this.onsessioninitialized(this.sessionId);\n }\n }\n\n if (!isInitializationRequest) {\n const sessionError = this.validateSession(request);\n if (sessionError) {\n return sessionError;\n }\n\n // Validate protocol version on subsequent requests\n const versionError = this.validateProtocolVersion(request);\n if (versionError) {\n return versionError;\n }\n }\n\n const hasRequests = messages.some(isJSONRPCRequest);\n\n if (!hasRequests) {\n for (const message of messages) {\n this.onmessage?.(message, { requestInfo });\n }\n return new Response(null, {\n status: 202,\n headers: { ...this.getHeaders() }\n });\n }\n\n const streamId = crypto.randomUUID();\n\n if (this.enableJsonResponse) {\n return new Promise<Response>((resolve) => {\n this.streamMapping.set(streamId, {\n resolveJson: resolve,\n cleanup: () => {\n this.streamMapping.delete(streamId);\n }\n });\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this.requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n for (const message of messages) {\n this.onmessage?.(message, { requestInfo });\n }\n });\n }\n\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n const headers = new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n ...this.getHeaders()\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n // POST response streams are scoped to a request id and can't be\n // resumed via Last-Event-ID, so we keepalive unconditionally so\n // long-running tool calls survive the ~5min Cloudflare edge idle\n // watchdog. See cloudflare/agents#1583.\n const keepAlive = startKeepalive(writer, encoder);\n this.streamMapping.set(streamId, {\n writer,\n encoder,\n cleanup: () => {\n clearInterval(keepAlive);\n this.streamMapping.delete(streamId);\n writer.close().catch(() => {});\n }\n });\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this.requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n for (const message of messages) {\n this.onmessage?.(message, { requestInfo });\n }\n\n return new Response(readable, { headers });\n }\n\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionError = this.validateSession(request);\n if (sessionError) {\n return sessionError;\n }\n\n // Validate protocol version on subsequent requests\n const versionError = this.validateProtocolVersion(request);\n if (versionError) {\n return versionError;\n }\n\n // Capture session ID before closing\n const closedSessionId = this.sessionId;\n\n await this.close();\n\n // Fire onsessionclosed callback if configured\n if (closedSessionId && this.onsessionclosed) {\n this.onsessionclosed(closedSessionId);\n }\n\n return new Response(null, {\n status: 200,\n headers: { ...this.getHeaders() }\n });\n }\n\n private handleOptionsRequest(_request: Request): Response {\n return new Response(null, {\n status: 200,\n headers: { ...this.getHeaders({ forPreflight: true }) }\n });\n }\n\n private handleUnsupportedRequest(): Response {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Method not allowed.\"\n },\n id: null\n }),\n {\n status: 405,\n headers: {\n Allow: \"GET, POST, DELETE, OPTIONS\",\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n private validateSession(request: Request): Response | undefined {\n if (this.sessionIdGenerator === undefined) {\n return undefined;\n }\n\n if (!this.initialized) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Server not initialized\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const sessionId = request.headers.get(\"mcp-session-id\");\n\n if (!sessionId) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n if (sessionId !== this.sessionId) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32001,\n message: \"Session not found\"\n },\n id: null\n }),\n {\n status: 404,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n return undefined;\n }\n\n async close(): Promise<void> {\n for (const { cleanup } of this.streamMapping.values()) {\n cleanup();\n }\n\n this.streamMapping.clear();\n this.requestResponseMap.clear();\n this.onclose?.();\n }\n\n /**\n * Close an SSE stream for a specific request, triggering client reconnection.\n * Use this to implement polling behavior during long-running operations -\n * client will reconnect after the retry interval specified in the priming event.\n */\n closeSSEStream(requestId: RequestId): void {\n const streamId = this.requestToStreamMapping.get(requestId);\n if (!streamId) {\n return;\n }\n\n const stream = this.streamMapping.get(streamId);\n if (stream) {\n stream.cleanup();\n }\n\n // Clean up request mappings for this stream\n for (const [reqId, sid] of this.requestToStreamMapping.entries()) {\n if (sid === streamId) {\n this.requestToStreamMapping.delete(reqId);\n this.requestResponseMap.delete(reqId);\n }\n }\n }\n\n async send(\n message: JSONRPCMessage,\n options?: TransportSendOptions\n ): Promise<void> {\n // Check relatedRequestId FIRST to route server-to-client requests through the same stream as the originating client request\n let requestId: RequestId | undefined = options?.relatedRequestId;\n\n // Then override with message.id for responses/errors\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n requestId = message.id;\n }\n\n if (requestId === RESTORE_REQUEST_ID) {\n return;\n }\n\n if (requestId === undefined) {\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n throw new Error(\n \"Cannot send a response on a standalone SSE stream unless resuming a previous client request\"\n );\n }\n\n const standaloneSse = this.streamMapping.get(this.standaloneSseStreamId);\n if (standaloneSse === undefined) {\n return;\n }\n\n if (standaloneSse.writer && standaloneSse.encoder) {\n // Store event for resumability if eventStore is configured\n let eventId: EventId | undefined;\n if (this.eventStore) {\n eventId = await this.eventStore.storeEvent(\n this.standaloneSseStreamId,\n message\n );\n }\n\n const idLine = eventId ? `id: ${eventId}\\n` : \"\";\n const data = `${idLine}event: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await standaloneSse.writer.write(standaloneSse.encoder.encode(data));\n }\n return;\n }\n\n const streamId = this.requestToStreamMapping.get(requestId);\n if (!streamId) {\n throw new Error(\n `No connection established for request ID: ${String(requestId)}`\n );\n }\n\n const response = this.streamMapping.get(streamId);\n if (!response) {\n throw new Error(\n `No connection established for request ID: ${String(requestId)}`\n );\n }\n\n if (!this.enableJsonResponse) {\n if (response.writer && response.encoder) {\n // Store event for resumability if eventStore is configured\n let eventId: EventId | undefined;\n if (this.eventStore) {\n eventId = await this.eventStore.storeEvent(streamId, message);\n }\n\n const idLine = eventId ? `id: ${eventId}\\n` : \"\";\n const data = `${idLine}event: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await response.writer.write(response.encoder.encode(data));\n }\n }\n\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n this.requestResponseMap.set(requestId, message);\n\n const relatedIds = Array.from(this.requestToStreamMapping.entries())\n .filter(([, sid]) => sid === streamId)\n .map(([id]) => id);\n\n const allResponsesReady = relatedIds.every((id) =>\n this.requestResponseMap.has(id)\n );\n\n if (allResponsesReady) {\n if (this.enableJsonResponse && response.resolveJson) {\n const responses = relatedIds.map(\n (id) => this.requestResponseMap.get(id)!\n );\n\n const headers = new Headers({\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n const body = responses.length === 1 ? responses[0] : responses;\n response.resolveJson(new Response(JSON.stringify(body), { headers }));\n } else {\n response.cleanup();\n }\n\n for (const id of relatedIds) {\n this.requestResponseMap.delete(id);\n this.requestToStreamMapping.delete(id);\n }\n }\n }\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport interface McpAuthContext {\n props: Record<string, unknown>;\n}\n\nconst authContextStorage = new AsyncLocalStorage<McpAuthContext>();\n\nexport function getMcpAuthContext(): McpAuthContext | undefined {\n return authContextStorage.getStore();\n}\n\nexport function runWithAuthContext<T>(context: McpAuthContext, fn: () => T): T {\n return authContextStorage.run(context, fn);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n WorkerTransport,\n type WorkerTransportOptions\n} from \"./worker-transport\";\nimport { runWithAuthContext, type McpAuthContext } from \"./auth-context\";\n\nexport interface CreateMcpHandlerOptions extends WorkerTransportOptions {\n /**\n * The route path that this MCP handler should respond to.\n * If specified, the handler will only process requests that match this route.\n * @default \"/mcp\"\n */\n route?: string;\n /**\n * An optional auth context to use for handling MCP requests.\n * If not provided, the handler will look for props in the execution context.\n */\n authContext?: McpAuthContext;\n /**\n * An optional transport to use for handling MCP requests.\n * If not provided, a WorkerTransport will be created with the provided WorkerTransportOptions.\n */\n transport?: WorkerTransport;\n}\n\nexport function createMcpHandler(\n server: McpServer | Server,\n options: CreateMcpHandlerOptions = {}\n): (\n request: Request,\n env: unknown,\n ctx: ExecutionContext\n) => Promise<Response> {\n const route = options.route ?? \"/mcp\";\n\n return async (\n request: Request,\n _env: unknown,\n ctx: ExecutionContext\n ): Promise<Response> => {\n const url = new URL(request.url);\n if (route && url.pathname !== route) {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n const transport =\n options.transport ??\n new WorkerTransport({\n sessionIdGenerator: options.sessionIdGenerator,\n enableJsonResponse: options.enableJsonResponse,\n onsessioninitialized: options.onsessioninitialized,\n corsOptions: options.corsOptions,\n storage: options.storage\n });\n\n const buildAuthContext = () => {\n if (options.authContext) {\n return options.authContext;\n }\n\n if (ctx.props && Object.keys(ctx.props).length > 0) {\n return {\n props: ctx.props as Record<string, unknown>\n };\n }\n\n return undefined;\n };\n\n const handleRequest = async () => {\n return await transport.handleRequest(request);\n };\n\n const authContext = buildAuthContext();\n\n // Guard for stateful usage where a pre-connected transport is passed via options.\n // If someone passes a transport that's already connected to this server, skip reconnecting.\n // Note: If a developer incorrectly uses a global server with per-request transports,\n // the MCP SDK 1.26.0+ will throw an error when trying to connect an already-connected server.\n if (!transport.started) {\n // Check if server is already connected (McpServer has isConnected(), Server uses transport getter)\n const isServerConnected =\n server instanceof McpServer\n ? server.isConnected()\n : server.transport !== undefined;\n\n if (isServerConnected) {\n throw new Error(\n \"Server is already connected to a transport. Create a new McpServer instance per request for stateless handlers.\"\n );\n }\n\n await server.connect(transport);\n }\n\n try {\n if (authContext) {\n return await runWithAuthContext(authContext, handleRequest);\n } else {\n return await handleRequest();\n }\n } catch (error) {\n console.error(\"MCP handler error:\", error);\n\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32603,\n message:\n error instanceof Error ? error.message : \"Internal server error\"\n },\n id: null\n }),\n { status: 500, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n };\n}\n\nlet didWarnAboutExperimentalCreateMcpHandler = false;\n\n/**\n * @deprecated This has been renamed to createMcpHandler, and experimental_createMcpHandler will be removed in the next major version\n */\nexport function experimental_createMcpHandler(\n server: McpServer | Server,\n options: CreateMcpHandlerOptions = {}\n): (\n request: Request,\n env: unknown,\n ctx: ExecutionContext\n) => Promise<Response> {\n if (!didWarnAboutExperimentalCreateMcpHandler) {\n didWarnAboutExperimentalCreateMcpHandler = true;\n console.warn(\n \"experimental_createMcpHandler is deprecated, use createMcpHandler instead. experimental_createMcpHandler will be removed in the next major version.\"\n );\n }\n return createMcpHandler(server, options);\n}\n","import type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n JSONRPCMessage,\n MessageExtraInfo,\n RequestId\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n JSONRPCMessageSchema,\n isJSONRPCErrorResponse,\n isJSONRPCResultResponse,\n type ElicitResult\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Connection, ConnectionContext } from \"../\";\nimport { Agent } from \"../index\";\nimport type { BaseTransportType, MaybePromise, ServeOptions } from \"./types\";\nimport {\n createAutoHandler,\n createLegacySseHandler,\n createStreamingHttpHandler,\n handleCORS,\n isDurableObjectNamespace,\n MCP_HTTP_METHOD_HEADER,\n MCP_MESSAGE_HEADER\n} from \"./utils\";\nimport { McpSSETransport, StreamableHTTPServerTransport } from \"./transport\";\nimport type { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { DurableObjectEventStore } from \"./event-store\";\nimport { RPCServerTransport, type RPCServerTransportOptions } from \"./rpc\";\n\nexport abstract class McpAgent<\n Env extends Cloudflare.Env = Cloudflare.Env,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>\n> extends Agent<Env, State, Props> {\n private _transport?: Transport;\n private _pendingElicitations = new Map<\n string,\n { resolve: (result: ElicitResult) => void; reject: (err: Error) => void }\n >();\n props?: Props;\n\n // MCP WebSocket connections are transport bridges — they use their own\n // protocol and don't need agent identity, state sync, or other protocol\n // messages. Regular WebSocket connections are left untouched.\n override shouldSendProtocolMessages(\n _connection: Connection,\n ctx: ConnectionContext\n ): boolean {\n return !ctx.request.headers.get(MCP_HTTP_METHOD_HEADER);\n }\n\n abstract server: MaybePromise<McpServer | Server>;\n abstract init(): Promise<void>;\n\n /*\n * Helpers\n */\n\n async setInitializeRequest(initializeRequest: JSONRPCMessage) {\n await this.ctx.storage.put(\"initializeRequest\", initializeRequest);\n }\n\n async getInitializeRequest() {\n return this.ctx.storage.get<JSONRPCMessage>(\"initializeRequest\");\n }\n\n /**\n * Storage key prefix for the `streamId -> requestIds` mapping used\n * to support POST stream resumption across WebSocket reconnects.\n *\n * @internal\n */\n private static readonly STREAM_REQS_KEY_PREFIX = \"__mcp_stream_reqs__:\";\n\n /** Persist the `requestIds` for a POST stream. @internal */\n async setStreamRequestIds(\n streamId: string,\n requestIds: RequestId[]\n ): Promise<void> {\n await this.ctx.storage.put<RequestId[]>(\n `${McpAgent.STREAM_REQS_KEY_PREFIX}${streamId}`,\n requestIds\n );\n }\n\n /** Read the persisted `requestIds` for a POST stream. @internal */\n async getStreamRequestIds(\n streamId: string\n ): Promise<RequestId[] | undefined> {\n return this.ctx.storage.get<RequestId[]>(\n `${McpAgent.STREAM_REQS_KEY_PREFIX}${streamId}`\n );\n }\n\n /** Drop the persisted `requestIds` for a POST stream. @internal */\n async deleteStreamRequestIds(streamId: string): Promise<void> {\n await this.ctx.storage.delete(\n `${McpAgent.STREAM_REQS_KEY_PREFIX}${streamId}`\n );\n }\n\n /**\n * Reverse lookup: find which POST stream a given `requestId` belongs\n * to, and return the stream's full `requestIds` list in the same\n * pass. Used by the transport when the originating WS has dropped,\n * so `send()` can still record events for replay and decide whether\n * the stream is fully responded — mirrors the SDK's\n * `_requestToStreamMapping` which outlives connection loss.\n *\n * Returning `requestIds` alongside `streamId` lets `send()` skip a\n * second `getStreamRequestIds` read on the same key.\n *\n * O(n) in the number of in-flight POST streams — single-digit in\n * practice since each stream is cleaned up on its final response.\n * The `limit` is a defensive ceiling so an abandoned-POST leak can't\n * unbounded-load this scan; if you hit it, something else has gone\n * wrong and `send()` will throw `No active stream found`.\n *\n * @internal\n */\n async getStreamForRequestId(\n requestId: RequestId\n ): Promise<{ streamId: string; requestIds: RequestId[] } | undefined> {\n const STREAM_REQS_SCAN_LIMIT = 1000;\n const rows = await this.ctx.storage.list<RequestId[]>({\n prefix: McpAgent.STREAM_REQS_KEY_PREFIX,\n limit: STREAM_REQS_SCAN_LIMIT\n });\n if (rows.size === STREAM_REQS_SCAN_LIMIT) {\n console.warn(\n `McpAgent: getStreamForRequestId hit the ${STREAM_REQS_SCAN_LIMIT}-key scan cap; ` +\n `stale __mcp_stream_reqs__ entries may be accumulating from abandoned POSTs`\n );\n }\n for (const [key, requestIds] of rows) {\n if (requestIds?.includes(requestId)) {\n return {\n streamId: key.slice(McpAgent.STREAM_REQS_KEY_PREFIX.length),\n requestIds\n };\n }\n }\n return undefined;\n }\n\n /** Read the transport type for this agent.\n * This relies on the naming scheme being `sse:${sessionId}`,\n * `streamable-http:${sessionId}`, or `rpc:${sessionId}`.\n */\n getTransportType(): BaseTransportType {\n const [t, ..._] = this.name.split(\":\");\n switch (t) {\n case \"sse\":\n return \"sse\";\n case \"streamable-http\":\n return \"streamable-http\";\n case \"rpc\":\n return \"rpc\";\n default:\n throw new Error(\n \"Invalid transport type. McpAgent must be addressed with a valid protocol.\"\n );\n }\n }\n\n /** Read the sessionId for this agent.\n * This relies on the naming scheme being `sse:${sessionId}`\n * or `streamable-http:${sessionId}`.\n */\n getSessionId(): string {\n const [_, sessionId] = this.name.split(\":\");\n if (!sessionId) {\n throw new Error(\n \"Invalid session id. McpAgent must be addressed with a valid session id.\"\n );\n }\n return sessionId;\n }\n\n /** Get the unique WebSocket. SSE transport only. */\n getWebSocket() {\n const websockets = Array.from(this.getConnections());\n if (websockets.length === 0) {\n return null;\n }\n return websockets[0];\n }\n\n /**\n * Returns options for configuring the RPC server transport.\n * Override this method to customize RPC transport behavior (e.g., timeout).\n *\n * @example\n * ```typescript\n * class MyMCP extends McpAgent {\n * protected getRpcTransportOptions() {\n * return { timeout: 120000 }; // 2 minutes\n * }\n * }\n * ```\n */\n protected getRpcTransportOptions(): RPCServerTransportOptions {\n return {};\n }\n\n /**\n * Returns the {@link EventStore} for SSE resumability. Defaults to a\n * {@link DurableObjectEventStore} backed by this agent's storage,\n * letting clients reconnect with `Last-Event-ID` after the Cloudflare\n * edge closes an idle SSE stream (~5 minute watchdog) instead of\n * relying on a server-side keepalive that would block hibernation.\n *\n * Per-stream events are cleared by the transport immediately after\n * the final response is written to the wire, so there's no\n * background cleanup — storage cost is bounded by the in-flight\n * streams alone.\n *\n * Override to disable (`return undefined`) or swap implementations.\n */\n protected getEventStore(): EventStore | undefined {\n return new DurableObjectEventStore(this.ctx.storage);\n }\n\n /** Returns a new transport matching the type of the Agent. */\n private initTransport() {\n switch (this.getTransportType()) {\n case \"sse\": {\n return new McpSSETransport();\n }\n case \"streamable-http\": {\n const transport = new StreamableHTTPServerTransport({\n eventStore: this.getEventStore()\n });\n transport.messageInterceptor = (message) => {\n return Promise.resolve(this._handleElicitationResponse(message));\n };\n return transport;\n }\n case \"rpc\": {\n return new RPCServerTransport(this.getRpcTransportOptions());\n }\n }\n }\n\n /** Update and store the props */\n async updateProps(props?: Props) {\n await this.ctx.storage.put(\"props\", props ?? {});\n this.props = props;\n }\n\n async reinitializeServer() {\n // If the agent was previously initialized, we have to populate\n // the server again by sending the initialize request to make\n // client information available to the server.\n const initializeRequest = await this.getInitializeRequest();\n if (initializeRequest) {\n this._transport?.onmessage?.(initializeRequest);\n }\n }\n\n /*\n * Base Agent / Partykit Server overrides\n */\n\n /** Sets up the MCP transport and server every time the Agent is started.*/\n async onStart(props?: Props) {\n if (props) {\n // Fresh start with props — save to storage (also sets this.props)\n await this.updateProps(props);\n } else {\n // Hibernation recovery — restore props from storage\n this.props = await this.ctx.storage.get(\"props\");\n }\n\n await this.init();\n const server = await this.server;\n // Connect to the MCP server\n this._transport = this.initTransport();\n\n if (!this._transport) {\n throw new Error(\"Failed to initialize transport\");\n }\n await server.connect(this._transport);\n\n await this.reinitializeServer();\n }\n\n /** Validates new WebSocket connections. */\n async onConnect(\n conn: Connection,\n { request: req }: ConnectionContext\n ): Promise<void> {\n switch (this.getTransportType()) {\n case \"sse\": {\n // For SSE connections, we can only have one open connection per session\n // If we get an upgrade while already connected, we should error\n const websockets = Array.from(this.getConnections());\n if (websockets.length > 1) {\n conn.close(1008, \"Websocket already connected\");\n return;\n }\n break;\n }\n case \"streamable-http\":\n if (this._transport instanceof StreamableHTTPServerTransport) {\n switch (req.headers.get(MCP_HTTP_METHOD_HEADER)) {\n case \"POST\": {\n // This returns the response directly to the client\n const payloadHeader = req.headers.get(MCP_MESSAGE_HEADER);\n let rawPayload: string;\n\n if (!payloadHeader) {\n rawPayload = \"{}\";\n } else {\n try {\n rawPayload = Buffer.from(payloadHeader, \"base64\").toString(\n \"utf-8\"\n );\n } catch (_error) {\n throw new Error(\n \"Internal Server Error: Failed to decode MCP message header\"\n );\n }\n }\n\n const parsedBody = JSON.parse(rawPayload);\n this._transport?.handlePostRequest(req, parsedBody);\n break;\n }\n case \"GET\":\n this._transport?.handleGetRequest(req);\n break;\n }\n }\n }\n }\n\n /*\n * Transport ingress and routing\n */\n\n /** Handles MCP Messages for the legacy SSE transport. */\n async onSSEMcpMessage(\n _sessionId: string,\n messageBody: unknown,\n extraInfo?: MessageExtraInfo\n ): Promise<Error | null> {\n // Since we address the DO via both the protocol and the session id,\n // this should never happen, but let's enforce it just in case\n if (this.getTransportType() !== \"sse\") {\n return new Error(\"Internal Server Error: Expected SSE transport\");\n }\n\n try {\n let parsedMessage: JSONRPCMessage;\n try {\n parsedMessage = JSONRPCMessageSchema.parse(messageBody);\n } catch (error) {\n this._transport?.onerror?.(error as Error);\n throw error;\n }\n\n // Check if this is an elicitation response before passing to transport\n if (this._handleElicitationResponse(parsedMessage)) {\n return null; // Message was handled by elicitation system\n }\n\n this._transport?.onmessage?.(parsedMessage, extraInfo);\n return null;\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n this._transport?.onerror?.(error as Error);\n return error as Error;\n }\n }\n\n /** Elicit user input with a message and schema */\n async elicitInput(\n params: {\n message: string;\n requestedSchema: unknown;\n },\n options?: { relatedRequestId?: RequestId }\n ): Promise<ElicitResult> {\n const requestId = `elicit_${Math.random().toString(36).substring(2, 11)}`;\n\n const elicitRequest = {\n jsonrpc: \"2.0\" as const,\n id: requestId,\n method: \"elicitation/create\",\n params: {\n message: params.message,\n requestedSchema: params.requestedSchema\n }\n };\n\n // Create a Promise that will be resolved when the response arrives.\n // timeoutId is hoisted so error paths below can clear it and avoid\n // an unhandled rejection on the orphaned responsePromise.\n let timeoutId: ReturnType<typeof setTimeout>;\n const responsePromise = new Promise<ElicitResult>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n this._pendingElicitations.delete(requestId);\n reject(new Error(\"Elicitation request timed out\"));\n }, 60000);\n\n this._pendingElicitations.set(requestId, {\n resolve: (result: ElicitResult) => {\n clearTimeout(timeoutId);\n this._pendingElicitations.delete(requestId);\n resolve(result);\n },\n reject: (err: Error) => {\n clearTimeout(timeoutId);\n this._pendingElicitations.delete(requestId);\n reject(err);\n }\n });\n });\n\n const cleanup = () => {\n clearTimeout(timeoutId);\n this._pendingElicitations.delete(requestId);\n };\n\n // Keep the DO alive while we wait for the user's elicitation response.\n // An unresolved Promise alone isn't enough to prevent hibernation.\n return this.keepAliveWhile(async () => {\n // Send through MCP transport\n if (this._transport) {\n try {\n await this._transport.send(elicitRequest, options);\n } catch (error) {\n cleanup();\n throw error;\n }\n } else {\n const connections = this.getConnections();\n if (!connections || Array.from(connections).length === 0) {\n cleanup();\n throw new Error(\"No active connections available for elicitation\");\n }\n\n const connectionList = Array.from(connections);\n for (const connection of connectionList) {\n try {\n connection.send(JSON.stringify(elicitRequest));\n } catch (error) {\n console.error(\"Failed to send elicitation request:\", error);\n }\n }\n }\n\n return responsePromise;\n });\n }\n\n /** Handle elicitation responses via in-memory resolver */\n private _handleElicitationResponse(message: JSONRPCMessage): boolean {\n if (isJSONRPCResultResponse(message) && message.result) {\n const requestId = message.id?.toString();\n if (!requestId || !requestId.startsWith(\"elicit_\")) return false;\n\n const pending = this._pendingElicitations.get(requestId);\n if (!pending) return false;\n\n pending.resolve(message.result as ElicitResult);\n return true;\n }\n\n if (isJSONRPCErrorResponse(message)) {\n const requestId = message.id?.toString();\n if (!requestId || !requestId.startsWith(\"elicit_\")) return false;\n\n const pending = this._pendingElicitations.get(requestId);\n if (!pending) return false;\n\n pending.resolve({\n action: \"cancel\",\n content: {\n error: message.error.message || \"Elicitation request failed\"\n }\n });\n return true;\n }\n\n return false;\n }\n\n /**\n * Handle an RPC message for MCP\n * This method is called by the RPC stub to process MCP messages\n * @param message The JSON-RPC message(s) to handle\n * @returns The response message(s) or undefined\n */\n async handleMcpMessage(\n message: JSONRPCMessage | JSONRPCMessage[]\n ): Promise<JSONRPCMessage | JSONRPCMessage[] | undefined> {\n await this.__unsafe_ensureInitialized();\n\n if (!(this._transport instanceof RPCServerTransport)) {\n throw new Error(\"Expected RPC transport\");\n }\n\n const transport = this._transport;\n\n // RPC waits are intentionally in-memory. While a request/continuation is\n // pending, keep the object alive so hibernation does not drop the resolver\n // maps or the suspended tool stack. Making this sleep/resume across\n // hibernation would require a durable continuation model instead.\n return await this.keepAliveWhile(async () => {\n // Intercept elicitation responses before they reach the transport.\n // Mirrors what onSSEMcpMessage() and StreamableHTTPServerTransport's\n // messageInterceptor already do for their respective transports.\n if (!Array.isArray(message)) {\n const parseResult = JSONRPCMessageSchema.safeParse(message);\n if (\n parseResult.success &&\n this._handleElicitationResponse(parseResult.data)\n ) {\n // Resolved a pending elicitation — now wait for the tool handler\n // to send its next message (another elicitation request or the\n // final tool result).\n return await transport._awaitPendingResponse();\n }\n }\n\n return await transport.handle(message);\n });\n }\n\n /** Return a handler for the given path for this MCP.\n * Defaults to Streamable HTTP transport.\n */\n static serve(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n transport = \"streamable-http\",\n jurisdiction\n }: ServeOptions = {}\n ) {\n return {\n async fetch<Env>(\n this: void,\n request: Request,\n env: Env,\n ctx: ExecutionContext\n ): Promise<Response> {\n // Handle CORS preflight\n const corsResponse = handleCORS(request, corsOptions);\n if (corsResponse) {\n return corsResponse;\n }\n\n const bindingValue = env[binding as keyof typeof env] as unknown;\n\n // Ensure we have a binding of some sort\n if (bindingValue == null || typeof bindingValue !== \"object\") {\n throw new Error(\n `Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`\n );\n }\n\n // Ensure that the binding is to a DurableObject\n if (!isDurableObjectNamespace(bindingValue)) {\n throw new Error(\n `Invalid McpAgent binding for ${binding}. Make sure it's a Durable Object binding.`\n );\n }\n\n const namespace =\n bindingValue satisfies DurableObjectNamespace<McpAgent>;\n\n switch (transport) {\n case \"streamable-http\": {\n const handleStreamableHttp = createStreamingHttpHandler(\n path,\n namespace,\n { corsOptions, jurisdiction }\n );\n return handleStreamableHttp(request, ctx);\n }\n case \"sse\": {\n const handleLegacySse = createLegacySseHandler(path, namespace, {\n corsOptions,\n jurisdiction\n });\n return handleLegacySse(request, ctx);\n }\n case \"auto\": {\n const handleAuto = createAutoHandler(path, namespace, {\n corsOptions,\n jurisdiction\n });\n return handleAuto(request, ctx);\n }\n default:\n return new Response(\n \"Invalid MCP transport mode. Only `streamable-http`, `sse`, or `auto` are allowed.\",\n { status: 500 }\n );\n }\n }\n };\n }\n /**\n * Legacy api\n **/\n static mount(path: string, opts: Omit<ServeOptions, \"transport\"> = {}) {\n return McpAgent.serveSSE(path, opts);\n }\n\n static serveSSE(path: string, opts: Omit<ServeOptions, \"transport\"> = {}) {\n return McpAgent.serve(path, { ...opts, transport: \"sse\" });\n }\n}\n\nexport {\n SSEEdgeClientTransport,\n StreamableHTTPEdgeClientTransport\n} from \"./client-transports\";\nexport {\n RPC_DO_PREFIX,\n RPCClientTransport,\n RPCServerTransport,\n type RPCClientTransportOptions,\n type RPCServerTransportOptions\n} from \"./rpc\";\n\nexport {\n ElicitRequestSchema,\n type ElicitRequest,\n type ElicitResult\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type {\n MCPClientOAuthResult,\n MCPClientOAuthCallbackConfig,\n MCPServerOptions,\n MCPConnectionResult,\n MCPDiscoverResult\n} from \"./client\";\n\nexport { normalizeServerId, MCP_SERVER_ID_MAX_LENGTH } from \"./client\";\n\nexport type { McpClientOptions } from \"./types\";\n\nexport {\n createMcpHandler,\n experimental_createMcpHandler,\n type CreateMcpHandlerOptions\n} from \"./handler\";\n\nexport { getMcpAuthContext, type McpAuthContext } from \"./auth-context\";\n\nexport { DurableObjectEventStore } from \"./event-store\";\nexport type { ClearableEventStore } from \"./transport\";\n\nexport {\n WorkerTransport,\n type WorkerTransportOptions,\n type TransportState\n} from \"./worker-transport\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/mcp/sse-keepalive.ts","../../src/mcp/utils.ts","../../src/mcp/transport.ts","../../src/mcp/event-store.ts","../../src/mcp/client-transports.ts","../../src/mcp/worker-transport.ts","../../src/mcp/auth-context.ts","../../src/mcp/handler.ts","../../src/mcp/index.ts"],"sourcesContent":["/**\n * Shared SSE keepalive utility for MCP transports.\n *\n * Cloudflare's edge closes idle SSE responses after ~5 minutes. Writers\n * that may sit silent for that long (long-running tool calls, idle\n * standalone GET streams) arm a keepalive to keep the response under the\n * watchdog.\n *\n * See cloudflare/agents#1583.\n */\n\n/** Interval between SSE keepalive comment frames, in ms.\n *\n * The WHATWG SSE spec recommends a comment line every \"15 seconds or so\"\n * (html.spec.whatwg.org §9.2.7). 25s gives comfortable headroom below\n * both the ~30s post-handler background-work cancellation window on\n * Workers and the ~5min Cloudflare edge idle-stream watchdog.\n */\nexport const KEEPALIVE_INTERVAL_MS = 25_000;\n\n/** SSE comment frame the parser drops before any event dispatch. */\nexport const KEEPALIVE_FRAME = \": keepalive\\n\\n\";\n\n/**\n * Start an SSE keepalive on `writer`. Returns a `clearInterval` handle\n * that the stream cleanup must invoke when the stream closes.\n */\nexport function startKeepalive(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n encoder: TextEncoder\n): ReturnType<typeof setInterval> {\n const handle = setInterval(() => {\n writer\n .write(encoder.encode(KEEPALIVE_FRAME))\n .catch(() => clearInterval(handle));\n }, KEEPALIVE_INTERVAL_MS);\n return handle;\n}\n","import {\n JSONRPCMessageSchema,\n type JSONRPCMessage,\n type MessageExtraInfo,\n InitializeRequestSchema,\n isJSONRPCResultResponse,\n isJSONRPCNotification\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpAgent } from \".\";\nimport { getAgentByName } from \"..\";\nimport type { CORSOptions } from \"./types\";\nimport { MessageType } from \"../types\";\nimport { startKeepalive } from \"./sse-keepalive\";\n\n/**\n * Since we use WebSockets to bridge the client to the\n * MCP transport in the Agent, we use this header to signal\n * the method of the original request the user made, while\n * leaving the WS Upgrade request as GET.\n */\nexport const MCP_HTTP_METHOD_HEADER = \"cf-mcp-method\";\n\n/**\n * Since we use WebSockets to bridge the client to the\n * MCP transport in the Agent, we use this header to include\n * the original request body.\n */\nexport const MCP_MESSAGE_HEADER = \"cf-mcp-message\";\n\nconst MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024; // 4MB\n\nexport const createStreamingHttpHandler = (\n basePath: string,\n namespace: DurableObjectNamespace<McpAgent>,\n options: {\n corsOptions?: CORSOptions;\n jurisdiction?: DurableObjectJurisdiction;\n } = {}\n) => {\n let pathname = basePath;\n if (basePath === \"/\") pathname = \"/*\";\n\n const basePattern = new URLPattern({ pathname });\n return async (request: Request, ctx: ExecutionContext) => {\n const url = new URL(request.url);\n if (basePattern.test(url)) {\n if (request.method === \"POST\") {\n // Validate the Accept header\n const acceptHeader = request.headers.get(\"accept\");\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (\n !acceptHeader?.includes(\"application/json\") ||\n !acceptHeader.includes(\"text/event-stream\")\n ) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message:\n \"Not Acceptable: Client must accept both application/json and text/event-stream\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 406 });\n }\n\n const ct = request.headers.get(\"content-type\");\n if (!ct || !ct.includes(\"application/json\")) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message:\n \"Unsupported Media Type: Content-Type must be application/json\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 415 });\n }\n\n // Check content length against maximum allowed size\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 413 });\n }\n\n let sessionId = request.headers.get(\"mcp-session-id\");\n let rawMessage: unknown;\n\n try {\n rawMessage = await request.json();\n } catch (_error) {\n const body = JSON.stringify({\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // Make sure the message is an array to simplify logic\n let arrayMessage: unknown[];\n if (Array.isArray(rawMessage)) {\n arrayMessage = rawMessage;\n } else {\n arrayMessage = [rawMessage];\n }\n\n let messages: JSONRPCMessage[] = [];\n\n // Try to parse each message as JSON RPC. Fail if any message is invalid\n for (const msg of arrayMessage) {\n if (!JSONRPCMessageSchema.safeParse(msg).success) {\n const body = JSON.stringify({\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON-RPC message\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n }\n\n messages = arrayMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n\n // Before we pass the messages to the agent, there's another error condition we need to enforce\n // Check if this is an initialization request\n // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/\n const maybeInitializeRequest = messages.find(\n (msg) => InitializeRequestSchema.safeParse(msg).success\n );\n\n if (!!maybeInitializeRequest && sessionId) {\n const body = JSON.stringify({\n error: {\n code: -32600,\n message:\n \"Invalid Request: Initialization requests must not include a sessionId\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // The initialization request must be the only request in the batch\n if (!!maybeInitializeRequest && messages.length > 1) {\n const body = JSON.stringify({\n error: {\n code: -32600,\n message:\n \"Invalid Request: Only one initialization request is allowed\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n if (!maybeInitializeRequest && !sessionId) {\n const body = JSON.stringify({\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 400 });\n }\n\n // If we don't have a sessionId, we are serving an initialization request\n // and need to generate a new sessionId\n sessionId = sessionId ?? namespace.newUniqueId().toString();\n\n // Get the agent and set props\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`,\n {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n }\n );\n const isInitialized = await agent.getInitializeRequest();\n\n if (maybeInitializeRequest) {\n await agent.setInitializeRequest(maybeInitializeRequest);\n } else if (!isInitialized) {\n // if we have gotten here, then a session id that was never initialized\n // was provided\n const body = JSON.stringify({\n error: {\n code: -32001,\n message: \"Session not found\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 404 });\n }\n\n // We've evaluated all the error conditions! Now it's time to establish\n // all the streams\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Connect to the Durable Object via WebSocket\n const existingHeaders: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n existingHeaders[key] = value;\n });\n\n const req = new Request(request.url, {\n headers: {\n ...existingHeaders,\n [MCP_HTTP_METHOD_HEADER]: \"POST\",\n [MCP_MESSAGE_HEADER]: Buffer.from(\n JSON.stringify(messages)\n ).toString(\"base64\"),\n Upgrade: \"websocket\"\n }\n });\n const response = await agent.fetch(req);\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n\n await writer.close();\n const body = JSON.stringify({\n error: {\n code: -32001,\n message: \"Failed to establish WebSocket connection\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 500 });\n }\n\n // Accept the WebSocket\n ws.accept();\n\n // If there are no requests, we send the messages to the agent and\n // acknowledge the request with a 202 since we don't expect any\n // responses back through this connection. Decide this *before*\n // arming a keepalive on the SSE writer so we don't leak a timer.\n const hasOnlyNotificationsOrResponses = messages.every(\n (msg) => isJSONRPCNotification(msg) || isJSONRPCResultResponse(msg)\n );\n if (hasOnlyNotificationsOrResponses) {\n // closing the websocket will also close the SSE connection\n ws.close();\n\n return new Response(null, {\n headers: corsHeaders(request, options.corsOptions),\n status: 202\n });\n }\n\n // Long-running tool calls can sit silent for many seconds while\n // the DO runs the handler. Arm a keepalive on the response stream\n // so the Cloudflare edge ~5min idle watchdog doesn't close us\n // before the tool result arrives. POST streams are scoped to a\n // specific request id and can't be resumed via Last-Event-ID,\n // so there's no alternative recovery path here.\n const keepAlive = startKeepalive(writer, encoder);\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const data =\n typeof event.data === \"string\"\n ? event.data\n : new TextDecoder().decode(event.data);\n const message = JSON.parse(data);\n\n // We only forward events from the MCP server\n if (message.type !== MessageType.CF_MCP_AGENT_EVENT) {\n return;\n }\n\n // Send the message as an SSE event\n await writer.write(encoder.encode(message.event));\n\n // If we have received all the responses, close the connection\n if (message.close) {\n clearInterval(keepAlive);\n ws?.close();\n await writer.close().catch(() => {});\n }\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(_error: Event) {\n clearInterval(keepAlive);\n await writer.close().catch(() => {});\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n clearInterval(keepAlive);\n await writer.close().catch(() => {});\n }\n onClose().catch(console.error);\n });\n\n // Return the SSE response. We handle closing the stream in the ws \"message\"\n // handler\n return new Response(readable, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n \"mcp-session-id\": sessionId,\n ...corsHeaders(request, options.corsOptions)\n },\n status: 200\n });\n } else if (request.method === \"GET\") {\n // Validate the Accept header\n const acceptHeader = request.headers.get(\"accept\");\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Not Acceptable: Client must accept text/event-stream\"\n },\n id: null\n });\n return new Response(body, { status: 406 });\n }\n\n // Require sessionId\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (!sessionId)\n return new Response(\n JSON.stringify({\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null,\n jsonrpc: \"2.0\"\n }),\n { status: 400 }\n );\n\n // Create SSE stream\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`,\n {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n }\n );\n const isInitialized = await agent.getInitializeRequest();\n if (!isInitialized) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: { code: -32001, message: \"Session not found\" },\n id: null\n }),\n { status: 404 }\n );\n }\n\n const existingHeaders: Record<string, string> = {};\n request.headers.forEach((v, k) => {\n existingHeaders[k] = v;\n });\n\n const response = await agent.fetch(\n new Request(request.url, {\n headers: {\n ...existingHeaders,\n [MCP_HTTP_METHOD_HEADER]: \"GET\",\n Upgrade: \"websocket\"\n }\n })\n );\n\n const ws = response.webSocket;\n if (!ws) {\n await writer.close();\n return new Response(\"Failed to establish WS to DO\", {\n status: 500\n });\n }\n ws.accept();\n\n // Forward DO messages as SSE\n ws.addEventListener(\"message\", (event) => {\n try {\n async function onMessage(ev: MessageEvent) {\n const data =\n typeof ev.data === \"string\"\n ? ev.data\n : new TextDecoder().decode(ev.data);\n const message = JSON.parse(data);\n\n // We only forward events from the MCP server\n if (message.type !== MessageType.CF_MCP_AGENT_EVENT) {\n return;\n }\n await writer.write(encoder.encode(message.event));\n }\n onMessage(event).catch(console.error);\n } catch (e) {\n console.error(\"Error forwarding message to SSE:\", e);\n }\n });\n\n ws.addEventListener(\"error\", () => {\n writer.close().catch(() => {});\n });\n ws.addEventListener(\"close\", () => {\n writer.close().catch(() => {});\n });\n\n return new Response(readable, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n \"mcp-session-id\": sessionId,\n ...corsHeaders(request, options.corsOptions)\n },\n status: 200\n });\n } else if (request.method === \"DELETE\") {\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (!sessionId) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null\n }),\n { status: 400, headers: corsHeaders(request, options.corsOptions) }\n );\n }\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`,\n { jurisdiction: options.jurisdiction }\n );\n const isInitialized = await agent.getInitializeRequest();\n if (!isInitialized) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: { code: -32001, message: \"Session not found\" },\n id: null\n }),\n { status: 404, headers: corsHeaders(request, options.corsOptions) }\n );\n }\n // .destroy() passes an uncatchable Error, so we make sure we first return\n // the response to the client.\n ctx.waitUntil(\n agent.destroy().catch(() => {\n /* This will always throw. We silently catch here */\n })\n );\n return new Response(null, {\n status: 204,\n headers: corsHeaders(request, options.corsOptions)\n });\n }\n }\n\n // Route not found\n const body = JSON.stringify({\n error: {\n code: -32000,\n message: \"Not found\"\n },\n id: null,\n jsonrpc: \"2.0\"\n });\n return new Response(body, { status: 404 });\n };\n};\n\nexport const createLegacySseHandler = (\n basePath: string,\n namespace: DurableObjectNamespace<McpAgent>,\n options: {\n corsOptions?: CORSOptions;\n jurisdiction?: DurableObjectJurisdiction;\n } = {}\n) => {\n let pathname = basePath;\n if (basePath === \"/\") pathname = \"/*\";\n\n const basePattern = new URLPattern({ pathname });\n const messagePattern = new URLPattern({ pathname: `${basePath}/message` }); // SSE only\n return async (request: Request, ctx: ExecutionContext) => {\n const url = new URL(request.url);\n // Handle initial SSE connection\n if (request.method === \"GET\" && basePattern.test(url)) {\n // Use a session ID if one is passed in, or create a unique\n // session ID for this connection\n const sessionId =\n url.searchParams.get(\"sessionId\") || namespace.newUniqueId().toString();\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Send the endpoint event\n const endpointUrl = new URL(request.url);\n endpointUrl.pathname = encodeURI(`${basePath}/message`);\n endpointUrl.searchParams.set(\"sessionId\", sessionId);\n const relativeUrlWithSession =\n endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;\n const endpointMessage = `event: endpoint\\ndata: ${relativeUrlWithSession}\\n\\n`;\n writer.write(encoder.encode(endpointMessage));\n\n // Get the Durable Object\n const agent = await getAgentByName(namespace, `sse:${sessionId}`, {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n });\n\n // Connect to the Durable Object via WebSocket\n const existingHeaders: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n existingHeaders[key] = value;\n });\n const response = await agent.fetch(\n new Request(request.url, {\n headers: {\n ...existingHeaders,\n [MCP_HTTP_METHOD_HEADER]: \"SSE\",\n Upgrade: \"websocket\"\n }\n })\n );\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n await writer.close();\n return new Response(\"Failed to establish WebSocket connection\", {\n status: 500\n });\n }\n\n // Accept the WebSocket\n ws.accept();\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const message = JSON.parse(event.data);\n\n // validate that the message is a valid JSONRPC message\n const result = JSONRPCMessageSchema.safeParse(message);\n if (!result.success) {\n // The message was not a valid JSONRPC message, so we will drop it\n // PartyKit will broadcast state change messages to all connected clients\n // and we need to filter those out so they are not passed to MCP clients\n return;\n }\n\n // Send the message as an SSE event\n const messageText = `event: message\\ndata: ${JSON.stringify(result.data)}\\n\\n`;\n await writer.write(encoder.encode(messageText));\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(_error: Event) {\n try {\n await writer.close();\n } catch (_e) {\n // Ignore errors when closing\n }\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n try {\n await writer.close();\n } catch (error) {\n console.error(\"Error closing SSE connection:\", error);\n }\n }\n onClose().catch(console.error);\n });\n\n // Return the SSE response\n return new Response(readable, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n ...corsHeaders(request, options.corsOptions)\n }\n });\n }\n\n // Handle incoming MCP messages. These will be passed to McpAgent\n // but the response will be sent back via the open SSE connection\n // so we only need to return a 202 Accepted response for success\n if (request.method === \"POST\" && messagePattern.test(url)) {\n const sessionId = url.searchParams.get(\"sessionId\");\n if (!sessionId) {\n return new Response(\n `Missing sessionId. Expected POST to ${basePath} to initiate new one`,\n { status: 400 }\n );\n }\n\n const contentType = request.headers.get(\"content-type\") || \"\";\n if (!contentType.includes(\"application/json\")) {\n return new Response(`Unsupported content-type: ${contentType}`, {\n status: 400\n });\n }\n\n // check if the request body is too large\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") || \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n return new Response(`Request body too large: ${contentLength} bytes`, {\n status: 400\n });\n }\n\n // Get the Durable Object\n const agent = await getAgentByName(namespace, `sse:${sessionId}`, {\n props: ctx.props as Record<string, unknown> | undefined,\n jurisdiction: options.jurisdiction\n });\n\n const messageBody = await request.json();\n\n // Build MessageExtraInfo with filtered headers\n const headers = Object.fromEntries(request.headers.entries());\n\n const extraInfo: MessageExtraInfo = {\n requestInfo: { headers }\n };\n\n const error = await agent.onSSEMcpMessage(\n sessionId,\n messageBody,\n extraInfo\n );\n\n if (error) {\n return new Response(error.message, {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n ...corsHeaders(request, options.corsOptions)\n },\n status: 400\n });\n }\n\n return new Response(\"Accepted\", {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n ...corsHeaders(request, options.corsOptions)\n },\n status: 202\n });\n }\n\n return new Response(\"Not Found\", { status: 404 });\n };\n};\n\n/**\n * Auto-negotiating handler that serves both streamable HTTP and legacy SSE\n * on the same path. Streamable-HTTP-capable clients are preferred; legacy SSE\n * clients fall back transparently.\n *\n * Discrimination rules:\n * - POST to `{basePath}/message` → legacy SSE (the sub-path is SSE-only)\n * - POST to `{basePath}` → streamable HTTP\n * - GET with `mcp-session-id` header → streamable HTTP (standalone SSE reconnect)\n * - GET without `mcp-session-id` → legacy SSE (new SSE connection)\n * - DELETE → streamable HTTP (SSE has no session teardown)\n */\nexport const createAutoHandler = (\n basePath: string,\n namespace: DurableObjectNamespace<McpAgent>,\n options: {\n corsOptions?: CORSOptions;\n jurisdiction?: DurableObjectJurisdiction;\n } = {}\n) => {\n const handleStreamableHttp = createStreamingHttpHandler(\n basePath,\n namespace,\n options\n );\n const handleLegacySse = createLegacySseHandler(basePath, namespace, options);\n\n const messagePattern = new URLPattern({\n pathname: `${basePath}/message`\n });\n\n return async (request: Request, ctx: ExecutionContext) => {\n const url = new URL(request.url);\n\n if (request.method === \"DELETE\") {\n return handleStreamableHttp(request, ctx);\n }\n\n if (request.method === \"POST\" && messagePattern.test(url)) {\n return handleLegacySse(request, ctx);\n }\n\n if (request.method === \"POST\") {\n return handleStreamableHttp(request, ctx);\n }\n\n if (request.method === \"GET\" && request.headers.has(\"mcp-session-id\")) {\n return handleStreamableHttp(request, ctx);\n }\n\n if (request.method === \"GET\") {\n return handleLegacySse(request, ctx);\n }\n\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: {\n Allow: \"GET, POST, DELETE\",\n ...corsHeaders(request, options.corsOptions)\n }\n });\n };\n};\n\n// CORS helper functions\nexport function corsHeaders(_request: Request, corsOptions: CORSOptions = {}) {\n const origin = corsOptions.origin || \"*\";\n const headers =\n corsOptions.headers ||\n \"Content-Type, Accept, Authorization, mcp-session-id, mcp-protocol-version\";\n\n return {\n \"Access-Control-Allow-Headers\": headers,\n \"Access-Control-Allow-Methods\":\n corsOptions.methods || \"GET, POST, DELETE, OPTIONS\",\n \"Access-Control-Allow-Origin\": origin,\n \"Access-Control-Expose-Headers\":\n corsOptions.exposeHeaders || \"mcp-session-id\",\n \"Access-Control-Max-Age\": (corsOptions.maxAge || 86400).toString()\n };\n}\n\nexport function handleCORS(\n request: Request,\n corsOptions?: CORSOptions\n): Response | null {\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders(request, corsOptions) });\n }\n\n return null;\n}\n\nexport function isDurableObjectNamespace(\n namespace: unknown\n): namespace is DurableObjectNamespace<McpAgent> {\n return (\n typeof namespace === \"object\" &&\n namespace !== null &&\n \"newUniqueId\" in namespace &&\n typeof namespace.newUniqueId === \"function\" &&\n \"idFromName\" in namespace &&\n typeof namespace.idFromName === \"function\"\n );\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n type MessageExtraInfo,\n type RequestInfo,\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n type JSONRPCMessage,\n JSONRPCMessageSchema,\n type RequestId\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport type {\n EventStore,\n StreamId,\n EventId\n} from \"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js\";\nimport { getCurrentAgent, type Connection } from \"..\";\nimport type { McpAgent } from \".\";\nimport { MessageType } from \"../types\";\nimport { MCP_HTTP_METHOD_HEADER, MCP_MESSAGE_HEADER } from \"./utils\";\n\nexport type { EventStore, StreamId, EventId };\n\nexport class McpSSETransport implements Transport {\n sessionId: string;\n // Set by the server in `server.connect(transport)`\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n private _getWebSocket: () => WebSocket | null;\n private _started = false;\n constructor() {\n const { agent } = getCurrentAgent<McpAgent>();\n if (!agent)\n throw new Error(\"McpAgent was not found in Transport constructor\");\n\n this.sessionId = agent.getSessionId();\n this._getWebSocket = () => agent.getWebSocket();\n }\n\n async start() {\n // The transport does not manage the WebSocket connection since it's terminated\n // by the Durable Object in order to allow hibernation. There's nothing to initialize.\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n async send(message: JSONRPCMessage) {\n if (!this._started) {\n throw new Error(\"Transport not started\");\n }\n const websocket = this._getWebSocket();\n if (!websocket) {\n throw new Error(\"WebSocket not connected\");\n }\n try {\n websocket.send(JSON.stringify(message));\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n\n async close() {\n // Similar to start, the only thing to do is to pass the event on to the server\n this.onclose?.();\n }\n}\n\n/**\n * Configuration options for StreamableHTTPServerTransport\n */\nexport interface StreamableHTTPServerTransportOptions {\n /**\n * Event store for resumability support.\n * If provided, resumability will be enabled, allowing clients to\n * reconnect and resume messages.\n *\n * If the store also implements {@link ClearableEventStore.clearStream}\n * the transport will call it after the final response of a POST\n * stream is written, so storage stays bounded without any background\n * sweep. {@link DurableObjectEventStore} is the canonical example.\n */\n eventStore?: EventStore | ClearableEventStore;\n}\n\n/**\n * An {@link EventStore} that supports dropping all events for a single\n * stream id. Implemented by {@link DurableObjectEventStore}.\n */\nexport interface ClearableEventStore extends EventStore {\n clearStream(streamId: StreamId): Promise<void>;\n}\n\nfunction isClearableEventStore(\n store: EventStore | ClearableEventStore\n): store is ClearableEventStore {\n return typeof (store as ClearableEventStore).clearStream === \"function\";\n}\n\n/**\n * Adapted from: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/client/streamableHttp.ts\n * - Validation and initialization are removed as they're handled in `McpAgent.serve()` handler.\n * - Replaces the Node-style `req`/`res` with Worker's `Request`.\n * - Writes events as WS messages that the Worker forwards to the client as SSE events.\n * - Replaces the in-memory maps that track requestID/stream by using `connection.setState()` and `agent.getConnections()`.\n *\n * Besides these points, the implementation is the same and should be updated to match the original as new features are added.\n */\n/** Fixed streamId for the standalone GET listen stream. */\nconst STANDALONE_STREAM_ID = \"_GET_stream\";\n\n/** State persisted on each WebSocket connection by the transport. */\ntype TransportConnState = {\n /** Stable identifier for the SSE stream this connection serves.\n * Used as the event-store key. Survives WS reconnects via Last-Event-ID. */\n streamId?: string;\n /** True iff this connection is the standalone GET listen stream. */\n _standaloneSse?: boolean;\n /** Request ids whose responses must flow through this connection. */\n requestIds?: RequestId[];\n};\n\nexport class StreamableHTTPServerTransport implements Transport {\n private _started = false;\n private _eventStore?: EventStore | ClearableEventStore;\n\n // This tracks which messages on each POST stream have been answered.\n // It is fine that we do not persist this since it only supports backwards\n // compatibility for clients batching requests, which the spec discourages.\n // Keying by stream avoids colliding ids on independent POST streams sharing\n // completion state with one another.\n private _streamResponseIds: Map<string, Set<RequestId>> = new Map();\n\n sessionId: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n /**\n * Optional message interceptor that can intercept messages before they are passed to onmessage.\n * If the interceptor returns true, the message is considered handled and won't be forwarded.\n * This is used by McpAgent to intercept elicitation responses.\n */\n messageInterceptor?: (\n message: JSONRPCMessage,\n extra?: MessageExtraInfo\n ) => Promise<boolean>;\n\n constructor(options: StreamableHTTPServerTransportOptions) {\n const { agent } = getCurrentAgent<McpAgent>();\n if (!agent)\n throw new Error(\"McpAgent was not found in Transport constructor\");\n\n // Initialization is handled in `McpAgent.serve()` and agents are addressed by sessionId,\n // so we'll always have this available.\n this.sessionId = agent.getSessionId();\n this._eventStore = options.eventStore;\n }\n\n /**\n * Starts the transport. This is required by the Transport interface but is a no-op\n * for the Streamable HTTP transport as connections are managed per-request.\n */\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n /**\n * Handles GET requests for SSE stream.\n *\n * Two roles a GET can play:\n * 1. Fresh standalone listen stream — carries server-initiated\n * requests/notifications unrelated to any in-progress POST.\n * 2. Resumption of a previously-disconnected stream via\n * `Last-Event-ID`. The disconnected stream may have been the\n * standalone stream OR a POST tool-call response stream; per the\n * MCP 2025-03-26 spec the server replays missed messages \"on the\n * stream that was disconnected\" and continues delivering\n * subsequent messages on that same stream.\n *\n * To resume a POST stream we recover the original streamId from the\n * event-store and the original `requestIds` from durable storage,\n * then write them onto the new WS connection so `send()` keeps\n * routing in-flight tool responses to it.\n */\n async handleGetRequest(req: Request): Promise<void> {\n const { connection, agent } = getCurrentAgent<McpAgent>();\n if (!connection)\n throw new Error(\"Connection was not found in handleGetRequest\");\n if (!agent) throw new Error(\"Agent was not found in handleGetRequest\");\n\n const lastEventId = req.headers.get(\"last-event-id\");\n\n // Resume path: the client identifies which stream it lost via\n // Last-Event-ID. Recover the original streamId from the event\n // store and register this connection under it. Matches the SDK\n // reference implementation (typescript-sdk's `replayEvents`):\n // the resumed connection is mapped to the *original* streamId,\n // no dual-role tagging.\n //\n // Forward routing then depends on what kind of stream it was:\n // - active POST: persisted requestIds are restored so further\n // tool responses route to this new WS via state.requestIds.\n // - standalone listen stream: tag with _standaloneSse so\n // server-initiated notifications continue to land here.\n // - completed POST / unknown: this connection is a one-shot\n // replay channel. No future messages will be routed to it.\n //\n // In every resumable case we supersede any prior connection bound\n // to the same streamId by closing it, so there is at most one live\n // connection per stream. This keeps `send()` routing deterministic\n // and keeps us within the MCP rule that each message goes out on\n // exactly one stream.\n if (this._eventStore && lastEventId) {\n const resumedStreamId =\n await this._eventStore.getStreamIdForEventId?.(lastEventId);\n if (resumedStreamId) {\n const resumeState: TransportConnState = {\n streamId: resumedStreamId\n };\n if (resumedStreamId === STANDALONE_STREAM_ID) {\n resumeState._standaloneSse = true;\n } else {\n const persistedReqs =\n await agent.getStreamRequestIds(resumedStreamId);\n if (persistedReqs && persistedReqs.length > 0) {\n resumeState.requestIds = persistedReqs;\n }\n }\n this.supersedePriorStreamConnections(\n agent,\n connection.id,\n resumedStreamId\n );\n connection.setState(resumeState);\n await this.replayEvents(lastEventId);\n return;\n }\n }\n\n // Fresh standalone listen stream. The MCP spec allows only one\n // standalone GET per session, so supersede any existing one.\n this.supersedePriorStreamConnections(\n agent,\n connection.id,\n STANDALONE_STREAM_ID\n );\n const standaloneState: TransportConnState = {\n streamId: STANDALONE_STREAM_ID,\n _standaloneSse: true\n };\n connection.setState(standaloneState);\n }\n\n /**\n * Close any connection (other than `selfId`) currently bound to\n * `streamId`, so at most one live connection serves a given stream.\n * Closing rather than mutating sibling state mirrors how the SDK's\n * single `_streamMapping` entry gives last-writer-wins for free, and\n * keeps `send()` from routing to a stale bridge.\n */\n private supersedePriorStreamConnections(\n agent: McpAgent,\n selfId: string,\n streamId: string\n ): void {\n for (const other of agent.getConnections<TransportConnState>()) {\n if (other.id === selfId) continue;\n if (other.state?.streamId !== streamId) continue;\n other.close(1000, \"Superseded by resumed stream\");\n }\n }\n\n /**\n * Replays events that would have been sent after the specified event ID\n * Only used when resumability is enabled\n */\n private async replayEvents(lastEventId: string): Promise<void> {\n if (!this._eventStore) {\n return;\n }\n\n const { connection } = getCurrentAgent();\n if (!connection)\n throw new Error(\"Connection was not available in replayEvents\");\n\n try {\n await this._eventStore?.replayEventsAfter(lastEventId, {\n send: async (eventId: string, message: JSONRPCMessage) => {\n try {\n this.writeSSEEvent(connection, message, eventId);\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n });\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n\n /**\n * Writes an event to the SSE stream with proper formatting\n */\n private writeSSEEvent(\n connection: Connection,\n message: JSONRPCMessage,\n eventId?: string,\n close?: boolean\n ) {\n let eventData = \"event: message\\n\";\n // Include event ID if provided - this is important for resumability\n if (eventId) {\n eventData += `id: ${eventId}\\n`;\n }\n eventData += `data: ${JSON.stringify(message)}\\n\\n`;\n\n return connection.send(\n JSON.stringify({\n type: MessageType.CF_MCP_AGENT_EVENT,\n event: eventData,\n close\n })\n );\n }\n\n /**\n * Handles POST requests containing JSON-RPC messages\n */\n async handlePostRequest(\n req: Request & { auth?: AuthInfo },\n parsedBody: unknown\n ): Promise<void> {\n const authInfo: AuthInfo | undefined = req.auth;\n const requestInfo: RequestInfo = {\n headers: Object.fromEntries(req.headers.entries()),\n url: new URL(req.url)\n };\n // Remove headers that are not part of the original request\n delete requestInfo.headers[MCP_HTTP_METHOD_HEADER];\n delete requestInfo.headers[MCP_MESSAGE_HEADER];\n delete requestInfo.headers.upgrade;\n\n const rawMessage = parsedBody;\n let messages: JSONRPCMessage[];\n\n // handle batch and single messages\n if (Array.isArray(rawMessage)) {\n messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n } else {\n messages = [JSONRPCMessageSchema.parse(rawMessage)];\n }\n\n // check if it contains requests\n const hasRequests = messages.some(isJSONRPCRequest);\n\n if (!hasRequests) {\n // We process without sending anything\n for (const message of messages) {\n // check if message should be intercepted (i.e. elicitation responses)\n if (this.messageInterceptor) {\n const handled = await this.messageInterceptor(message, {\n authInfo,\n requestInfo\n });\n if (handled) {\n continue; // msg was handled by interceptor, skip onmessage\n }\n }\n this.onmessage?.(message, { authInfo, requestInfo });\n }\n } else if (hasRequests) {\n const { connection, agent } = getCurrentAgent<McpAgent>();\n if (!connection)\n throw new Error(\"Connection was not found in handlePostRequest\");\n if (!agent) throw new Error(\"Agent was not found in handlePostRequest\");\n\n // We need to track by request ID to maintain the connection\n const requestIds = messages\n .filter(isJSONRPCRequest)\n .map((message) => message.id);\n\n // The streamId is stable for the lifetime of this POST's stream.\n // We seed it with the WS connection id (unique per POST), and a\n // resumed GET later inherits the *same* streamId via Last-Event-ID.\n const streamId = connection.id;\n const postState: TransportConnState = { streamId, requestIds };\n connection.setState(postState);\n\n // Persist the mapping so a future GET-with-Last-Event-ID can\n // restore `requestIds` onto a fresh WS connection. Only relevant\n // when an event store is configured — without one the client has\n // no `id:` to resume from anyway. Cleaned up in `send()` on the\n // final response.\n if (this._eventStore) {\n await agent.setStreamRequestIds(streamId, requestIds);\n }\n\n // handle each message\n for (const message of messages) {\n if (this.messageInterceptor) {\n const handled = await this.messageInterceptor(message, {\n authInfo,\n requestInfo\n });\n if (handled) {\n continue; // Message was handled by interceptor, skip onmessage\n }\n }\n this.onmessage?.(message, { authInfo, requestInfo });\n }\n // The server SHOULD NOT close the SSE stream before sending all JSON-RPC responses\n // This will be handled by the send() method when responses are ready\n }\n }\n\n async close(): Promise<void> {\n // Close all SSE connections\n const { agent } = getCurrentAgent();\n if (!agent) throw new Error(\"Agent was not found in close\");\n\n for (const conn of agent.getConnections()) {\n conn.close(1000, \"Session closed\");\n }\n this.onclose?.();\n }\n\n /**\n * Store the event, decide whether this is the final response, write\n * the SSE frame iff a live connection is attached, then run cleanup.\n * Caller resolves `streamId` and `relatedIds` (from connection state\n * or persisted reverse lookup) and passes `liveConnection` as null\n * when the originating WS has dropped.\n */\n private async sendOnStream(\n agent: McpAgent,\n streamId: string,\n relatedIds: readonly RequestId[],\n liveConnection: Connection<TransportConnState> | null,\n message: JSONRPCMessage,\n requestId: RequestId\n ): Promise<void> {\n const eventId = await this._eventStore?.storeEvent(streamId, message);\n\n let shouldClose = false;\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n let responseIds = this._streamResponseIds.get(streamId);\n if (!responseIds) {\n responseIds = new Set<RequestId>();\n this._streamResponseIds.set(streamId, responseIds);\n }\n responseIds.add(requestId);\n shouldClose = relatedIds.every((id) => responseIds.has(id));\n if (shouldClose) this._streamResponseIds.delete(streamId);\n }\n\n // Write FIRST, clean up SECOND. Clearing before the write would\n // leave a mid-flight client with a wiped stream on reconnect.\n // `writeSSEEvent` is sync (enqueues, doesn't await), so the bytes\n // are committed before any cleanup await can interleave. Wrap in\n // try/catch so a dead WS can't skip cleanup and orphan the\n // stream-reqs + stored events.\n if (liveConnection) {\n try {\n this.writeSSEEvent(liveConnection, message, eventId, shouldClose);\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n\n if (shouldClose) {\n // A concurrent GET resume between these awaits would replay\n // events about to be deleted — benign.\n await agent.deleteStreamRequestIds(streamId);\n if (this._eventStore && isClearableEventStore(this._eventStore)) {\n await this._eventStore.clearStream(streamId);\n }\n }\n }\n\n async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId }\n ): Promise<void> {\n // Request-scoped (response / `relatedRequestId` notification) vs\n // server-initiated on the standalone GET stream. Two helpers.\n const isResponse =\n isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message);\n const requestId = isResponse ? message.id : options?.relatedRequestId;\n\n if (requestId === undefined) {\n if (isResponse) {\n throw new Error(\n \"Cannot send a response on a standalone SSE stream unless resuming a previous client request\"\n );\n }\n return this.sendStandalone(message);\n }\n\n return this.sendForRequest(message, requestId);\n }\n\n /**\n * Server-initiated message on the standalone GET stream. Stored under\n * a fixed streamId so it's replayable even when no live connection is\n * currently attached.\n *\n * Sent on exactly one stream, per MCP: \"the server MUST send each of\n * its JSON-RPC messages on only one of the connected streams; it MUST\n * NOT broadcast the same message across multiple streams.\"\n * `handleGetRequest` supersedes prior standalone connections, so\n * there is at most one to send on.\n */\n private async sendStandalone(message: JSONRPCMessage): Promise<void> {\n const { agent } = getCurrentAgent<McpAgent>();\n if (!agent) throw new Error(\"Agent was not found in send\");\n\n const eventId = await this._eventStore?.storeEvent(\n STANDALONE_STREAM_ID,\n message\n );\n\n const standalone = Array.from(\n agent.getConnections<TransportConnState>()\n ).find((conn) => conn.state?._standaloneSse);\n // No live standalone stream: the event is stored above and replays\n // when a client reconnects with Last-Event-ID. Per spec the server\n // MAY send on the stream, so dropping the live write is fine.\n if (standalone) {\n this.writeSSEEvent(standalone, message, eventId);\n }\n }\n\n /**\n * Message scoped to a specific in-flight client request: a tool\n * response, error, or progress notification. Resolves which stream\n * owns the request id (live POST connection, resumed GET, or\n * persisted reverse lookup for a dropped WS) and delegates to\n * {@link sendOnStream} for the actual store / write / cleanup.\n */\n private async sendForRequest(\n message: JSONRPCMessage,\n requestId: RequestId\n ): Promise<void> {\n const { agent, connection: originatingConnection } =\n getCurrentAgent<McpAgent>();\n if (!agent) throw new Error(\"Agent was not found in send\");\n\n // Pick the live connection that should receive this message. Normally\n // request ids uniquely identify a POST connection. If a client violates\n // that constraint, prefer the connection whose handler is currently\n // producing this message rather than leaking a plausible response to\n // the first matching POST stream. Only prefer an originating connection\n // while it is still live: after a POST stream disconnects, a resumed\n // GET connection inherits requestIds and must be allowed to receive\n // the eventual response.\n const matchingConnections = Array.from(\n agent.getConnections<TransportConnState>()\n ).filter((conn) => conn.state?.requestIds?.includes(requestId));\n const liveConnection =\n matchingConnections.find(\n (conn) => conn.id === originatingConnection?.id\n ) ?? (matchingConnections.length === 1 ? matchingConnections[0] : null);\n\n // Ambiguous routing: multiple live POST connections claim the same\n // request id, none of which is the originating connection. Terminate\n // each with a protocol error rather than guessing.\n if (!liveConnection && matchingConnections.length > 1) {\n const routingError: JSONRPCMessage = {\n jsonrpc: \"2.0\",\n id: requestId,\n error: { code: -32603, message: \"Internal error\" }\n };\n await Promise.all(\n matchingConnections.map((candidate) =>\n this.sendOnStream(\n agent,\n candidate.state?.streamId ?? candidate.id,\n candidate.state?.requestIds ?? [],\n candidate,\n routingError,\n requestId\n )\n )\n );\n return;\n }\n\n // Resolve streamId + relatedIds. Prefer the live connection's state;\n // when the originating WS has dropped fall back to the persisted\n // reverse lookup so the event can still be stored for replay —\n // mirrors the SDK's `_requestToStreamMapping` which outlives\n // connection loss.\n let streamId = liveConnection?.state?.streamId;\n let relatedIds = liveConnection?.state?.requestIds;\n if (!streamId) {\n const stored = await agent.getStreamForRequestId(requestId);\n if (!stored) {\n throw new Error(\n `No active stream found for request ID: ${String(requestId)}`\n );\n }\n streamId = stored.streamId;\n relatedIds = stored.requestIds;\n }\n\n await this.sendOnStream(\n agent,\n streamId,\n relatedIds ?? [],\n liveConnection,\n message,\n requestId\n );\n }\n}\n","import type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n EventStore,\n EventId,\n StreamId\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\n\n/**\n * Durable Object–backed {@link EventStore} for SSE resumability.\n *\n * Default for `McpAgent`. Override `McpAgent.getEventStore()` to swap\n * or disable.\n *\n * ## Storage layout\n *\n * Events are stored under `__mcp_event__:<streamId>:<seqHex>`, where\n * `<seqHex>` is a 16-char zero-padded counter so events in a stream\n * sort lexicographically and `getStreamIdForEventId` can recover the\n * stream from `eventId` without a storage hit.\n *\n * ## Lifecycle\n *\n * Each POST tool-call stream's events live only until the final\n * response is delivered. The transport calls {@link clearStream}\n * immediately after writing the close frame, so storage growth is\n * bounded by the in-flight POST streams plus the standalone GET\n * stream. There is no background sweep — quiescent agents do no work,\n * and the DO itself dies with the session.\n *\n * Standalone GET stream events (`_GET_stream`) are *not* cleared\n * automatically; they accumulate for the lifetime of the DO. Bounded\n * by session length in practice.\n *\n * Trade-off: if the client TCP connection dies *after* the close\n * frame has been enqueued on the WS but before the bytes reach the\n * client, the final message is unreplayable. Every earlier event in\n * the stream is still replayable while the in-flight stream is open.\n *\n * ## Stream id constraints\n *\n * `streamId` MUST NOT contain `:`. `storeEvent` asserts this so\n * embedders using custom stream ids fail loudly rather than risk\n * prefix-scan collisions (e.g. clearing `a` accidentally hitting\n * `a:b`). Default ids (`connection.id` UUIDs and the literal\n * `_GET_stream`) already satisfy this.\n */\nexport class DurableObjectEventStore implements EventStore {\n private static readonly EVENT_KEY_PREFIX = \"__mcp_event__:\";\n private static readonly SEQ_PAD = 16;\n /** DO storage caps multi-key delete at 128. */\n private static readonly DELETE_CHUNK = 128;\n /** Defensive ceiling on a single replay batch. A live stream's\n * event count is small (progress notifications + final result);\n * this is here so a pathological history can't OOM the DO. */\n private static readonly REPLAY_LIMIT = 1000;\n\n private readonly storage: DurableObjectStorage;\n\n /** In-memory seq counters per stream, rehydrated lazily from storage. */\n private readonly seqByStream = new Map<StreamId, number>();\n private readonly seqInit = new Map<StreamId, Promise<void>>();\n\n constructor(storage: DurableObjectStorage) {\n this.storage = storage;\n }\n\n async storeEvent(\n streamId: StreamId,\n message: JSONRPCMessage\n ): Promise<EventId> {\n if (streamId.includes(\":\")) {\n // Event keys are `__mcp_event__:<streamId>:<seqHex>` — a `:` in\n // streamId would let prefix scans cross stream boundaries.\n throw new Error(\n `DurableObjectEventStore: streamId must not contain ':' (got ${JSON.stringify(streamId)})`\n );\n }\n await this.ensureSeqLoaded(streamId);\n const seq = (this.seqByStream.get(streamId) ?? 0) + 1;\n this.seqByStream.set(streamId, seq);\n\n const seqHex = seq\n .toString(16)\n .padStart(DurableObjectEventStore.SEQ_PAD, \"0\");\n const eventId = `${streamId}:${seqHex}`;\n const eventKey = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${eventId}`;\n\n await this.storage.put(eventKey, message);\n return eventId;\n }\n\n async getStreamIdForEventId(eventId: EventId): Promise<StreamId | undefined> {\n const idx = eventId.lastIndexOf(\":\");\n return idx > 0 ? eventId.slice(0, idx) : undefined;\n }\n\n async replayEventsAfter(\n lastEventId: EventId,\n {\n send\n }: { send: (eventId: EventId, message: JSONRPCMessage) => Promise<void> }\n ): Promise<StreamId> {\n const streamId = await this.getStreamIdForEventId(lastEventId);\n if (!streamId) return \"\";\n\n const prefix = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${streamId}:`;\n // `list({ start })` is inclusive, and we want strictly-after\n // semantics. Appending `\\x00` (the smallest byte) to the last\n // event's key produces a key that sorts immediately after it, so\n // the list excludes the boundary event without a post-filter.\n const startKey = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${lastEventId}\\x00`;\n // DO `storage.list()` with no `limit` loads everything into memory.\n // Stream histories are normally small (progress events + result),\n // but cap the batch defensively. Clients can reconnect again to\n // drain past the cap if they ever produce that many events.\n const rows = await this.storage.list<JSONRPCMessage>({\n prefix,\n start: startKey,\n limit: DurableObjectEventStore.REPLAY_LIMIT\n });\n\n for (const [key, message] of rows) {\n const eventId = key.slice(\n DurableObjectEventStore.EVENT_KEY_PREFIX.length\n );\n await send(eventId, message);\n }\n return streamId;\n }\n\n /**\n * Drop the event log for a single stream. Called by the transport\n * immediately after a POST's final response has been written to the\n * wire — no future `Last-Event-ID` for this stream is expected to\n * resolve.\n *\n * Lists and deletes in chunks of {@link DELETE_CHUNK} (128, the DO\n * storage cap) so we never load the entire event log into memory.\n * After deleting, the next `list` call won't see the deleted keys,\n * so passing `start: <prefix>` again is enough — no cursor bookkeeping.\n */\n async clearStream(streamId: StreamId): Promise<void> {\n const prefix = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${streamId}:`;\n for (;;) {\n const rows = await this.storage.list({\n prefix,\n limit: DurableObjectEventStore.DELETE_CHUNK\n });\n if (rows.size === 0) break;\n await this.storage.delete([...rows.keys()]);\n }\n this.seqByStream.delete(streamId);\n this.seqInit.delete(streamId);\n }\n\n private async ensureSeqLoaded(streamId: StreamId): Promise<void> {\n if (this.seqByStream.has(streamId)) return;\n let pending = this.seqInit.get(streamId);\n if (!pending) {\n pending = (async () => {\n const prefix = `${DurableObjectEventStore.EVENT_KEY_PREFIX}${streamId}:`;\n const rows = await this.storage.list({\n prefix,\n reverse: true,\n limit: 1\n });\n let seq = 0;\n for (const key of rows.keys()) {\n const parsed = Number.parseInt(key.slice(prefix.length), 16);\n if (Number.isFinite(parsed)) seq = parsed;\n }\n if (!this.seqByStream.has(streamId)) {\n this.seqByStream.set(streamId, seq);\n }\n })();\n this.seqInit.set(streamId, pending);\n }\n try {\n await pending;\n } finally {\n this.seqInit.delete(streamId);\n }\n }\n}\n","/**\n * Deprecated transport wrappers\n */\n\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { StreamableHTTPClientTransportOptions } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\nlet didWarnAboutSSEEdgeClientTransport = false;\n\n/**\n * @deprecated Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. This alias will be removed in the next major version.\n */\nexport class SSEEdgeClientTransport extends SSEClientTransport {\n constructor(url: URL, options: SSEClientTransportOptions) {\n super(url, options);\n if (!didWarnAboutSSEEdgeClientTransport) {\n didWarnAboutSSEEdgeClientTransport = true;\n console.warn(\n \"SSEEdgeClientTransport is deprecated. Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. SSEEdgeClientTransport will be removed in the next major version.\"\n );\n }\n }\n}\n\nlet didWarnAboutStreamableHTTPEdgeClientTransport = false;\n\n/**\n * @deprecated Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. This alias will be removed in the next major version.\n */\nexport class StreamableHTTPEdgeClientTransport extends StreamableHTTPClientTransport {\n constructor(url: URL, options: StreamableHTTPClientTransportOptions) {\n super(url, options);\n if (!didWarnAboutStreamableHTTPEdgeClientTransport) {\n didWarnAboutStreamableHTTPEdgeClientTransport = true;\n console.warn(\n \"StreamableHTTPEdgeClientTransport is deprecated. Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. StreamableHTTPEdgeClientTransport will be removed in the next major version.\"\n );\n }\n }\n}\n","/**\n * Based on webStandardStreamableHttp.ts (https://github.com/modelcontextprotocol/typescript-sdk/blob/main/packages/server/src/server/webStandardStreamableHttp.ts)\n */\n\nimport type {\n Transport,\n TransportSendOptions\n} from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n JSONRPCMessage,\n RequestId,\n RequestInfo,\n MessageExtraInfo,\n InitializeRequestParams\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n isInitializeRequest,\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n JSONRPCMessageSchema,\n SUPPORTED_PROTOCOL_VERSIONS\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { CORSOptions } from \"./types\";\nimport type {\n EventStore,\n EventId\n} from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { startKeepalive } from \"./sse-keepalive\";\n\nconst MCP_PROTOCOL_VERSION_HEADER = \"MCP-Protocol-Version\";\n\nconst RESTORE_REQUEST_ID = \"__restore__\";\n\ninterface StreamMapping {\n writer?: WritableStreamDefaultWriter<Uint8Array>;\n encoder?: TextEncoder;\n resolveJson?: (response: Response) => void;\n cleanup: () => void;\n}\n\nexport interface MCPStorageApi {\n get(): Promise<TransportState | undefined> | TransportState | undefined;\n set(state: TransportState): Promise<void> | void;\n}\n\nexport interface TransportState {\n sessionId?: string;\n initialized: boolean;\n initializeParams?: InitializeRequestParams;\n}\n\nexport interface WorkerTransportOptions {\n /**\n * Function that generates a session ID for the transport.\n * The session ID SHOULD be globally unique and cryptographically secure.\n * Return undefined to disable session management (stateless mode).\n */\n sessionIdGenerator?: () => string;\n /**\n * Enable traditional Request/Response mode, this will disable streaming.\n */\n enableJsonResponse?: boolean;\n /**\n * Callback fired when a new session is initialized.\n */\n onsessioninitialized?: (sessionId: string) => void;\n /**\n * Callback fired when a session is closed via DELETE request.\n */\n onsessionclosed?: (sessionId: string) => void;\n corsOptions?: CORSOptions;\n /**\n * Optional storage api for persisting transport state.\n * Use this to store session state in Durable Object/Agent storage\n * so it survives hibernation/restart.\n */\n storage?: MCPStorageApi;\n /**\n * Event store for SSE resumability.\n *\n * When set, the transport assigns a globally-unique `id:` to each SSE\n * event and replays missed events when a client reconnects with the\n * `Last-Event-ID` header. Both GET (standalone listen stream) and POST\n * (tool response stream) events are stored and replayable per the\n * MCP 2025-03-26 spec.\n *\n * Configuring an event store **disables the server-side keepalive**\n * on the standalone GET stream — idle drops are recovered by\n * reconnect rather than prevented by writing bytes. Without an event\n * store, the GET stream still gets the 25s comment-frame keepalive\n * so long-lived idle listeners aren't closed by the Cloudflare edge\n * ~5min watchdog.\n *\n * POST response streams always get the keepalive regardless of this\n * setting: in-progress tool calls have no way to recover\n * mid-execution without staying connected, so we don't let the\n * stream drop in the first place.\n *\n * Bring your own {@link EventStore} implementation — e.g.\n * `new DurableObjectEventStore(this.ctx.storage)` when embedding\n * `WorkerTransport` inside a Durable Object / Agent. See\n * cloudflare/agents#1583.\n */\n eventStore?: EventStore;\n /**\n * Retry interval in milliseconds to suggest to clients in SSE retry field.\n * Controls client reconnection timing for polling behavior.\n */\n retryInterval?: number;\n}\n\nexport class WorkerTransport implements Transport {\n started = false;\n private initialized = false;\n private sessionIdGenerator?: () => string;\n private enableJsonResponse = false;\n private onsessioninitialized?: (sessionId: string) => void;\n private onsessionclosed?: (sessionId: string) => void;\n private standaloneSseStreamId = \"_GET_stream\";\n private streamMapping = new Map<string, StreamMapping>();\n private requestToStreamMapping = new Map<RequestId, string>();\n private requestResponseMap = new Map<RequestId, JSONRPCMessage>();\n private corsOptions?: CORSOptions;\n private storage?: MCPStorageApi;\n private stateRestored = false;\n private eventStore?: EventStore;\n private retryInterval?: number;\n private initializeParams?: TransportState[\"initializeParams\"];\n\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n constructor(options?: WorkerTransportOptions) {\n this.sessionIdGenerator = options?.sessionIdGenerator;\n this.enableJsonResponse = options?.enableJsonResponse ?? false;\n this.onsessioninitialized = options?.onsessioninitialized;\n this.onsessionclosed = options?.onsessionclosed;\n this.corsOptions = options?.corsOptions;\n this.storage = options?.storage;\n this.eventStore = options?.eventStore;\n this.retryInterval = options?.retryInterval;\n }\n\n /**\n * Restore transport state from persistent storage.\n * This is automatically called on start.\n */\n private async restoreState() {\n if (!this.storage || this.stateRestored) {\n return;\n }\n\n const state = await Promise.resolve(this.storage.get());\n\n if (state) {\n this.sessionId = state.sessionId;\n this.initialized = state.initialized;\n\n // Restore _clientCapabilities on the Server instance by replaying the original initialize request\n if (state.initializeParams && this.onmessage) {\n this.onmessage({\n jsonrpc: \"2.0\",\n id: RESTORE_REQUEST_ID,\n method: \"initialize\",\n params: state.initializeParams\n });\n }\n }\n\n this.stateRestored = true;\n }\n\n /**\n * Persist current transport state to storage.\n */\n private async saveState() {\n if (!this.storage) {\n return;\n }\n\n const state: TransportState = {\n sessionId: this.sessionId,\n initialized: this.initialized,\n initializeParams: this.initializeParams\n };\n\n await Promise.resolve(this.storage.set(state));\n }\n\n async start(): Promise<void> {\n if (this.started) {\n throw new Error(\"Transport already started\");\n }\n this.started = true;\n }\n\n /**\n * Validates the MCP-Protocol-Version header on incoming requests.\n *\n * This performs a simple check: if a version header is present, it must be\n * in the SUPPORTED_PROTOCOL_VERSIONS list. We do not track the negotiated\n * version or enforce version consistency across requests - the SDK handles\n * version negotiation during initialization, and we simply reject any\n * explicitly unsupported versions.\n *\n * - Header present and supported: Accept\n * - Header present and unsupported: 400 Bad Request\n * - Header missing: Accept (version validation is optional)\n */\n private validateProtocolVersion(request: Request): Response | undefined {\n const protocolVersion = request.headers.get(MCP_PROTOCOL_VERSION_HEADER);\n\n if (\n protocolVersion !== null &&\n !SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)\n ) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(\", \")})`\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n return undefined;\n }\n\n private getHeaders({ forPreflight }: { forPreflight?: boolean } = {}): Record<\n string,\n string\n > {\n const defaults: CORSOptions = {\n origin: \"*\",\n headers:\n \"Content-Type, Accept, Authorization, mcp-session-id, MCP-Protocol-Version\",\n methods: \"GET, POST, DELETE, OPTIONS\",\n exposeHeaders: \"mcp-session-id\",\n maxAge: 86400\n };\n\n const options = { ...defaults, ...this.corsOptions };\n\n // For OPTIONS preflight, return all CORS headers\n if (forPreflight) {\n return {\n \"Access-Control-Allow-Origin\": options.origin!,\n \"Access-Control-Allow-Headers\": options.headers!,\n \"Access-Control-Allow-Methods\": options.methods!,\n \"Access-Control-Max-Age\": options.maxAge!.toString()\n };\n }\n\n // For actual requests, only return origin and expose headers\n return {\n \"Access-Control-Allow-Origin\": options.origin!,\n \"Access-Control-Expose-Headers\": options.exposeHeaders!\n };\n }\n\n async handleRequest(\n request: Request,\n parsedBody?: unknown\n ): Promise<Response> {\n await this.restoreState();\n\n switch (request.method) {\n case \"OPTIONS\":\n return this.handleOptionsRequest(request);\n case \"GET\":\n return this.handleGetRequest(request);\n case \"POST\":\n return this.handlePostRequest(request, parsedBody);\n case \"DELETE\":\n return this.handleDeleteRequest(request);\n default:\n return this.handleUnsupportedRequest();\n }\n }\n\n private async handleGetRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"Accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Not Acceptable: Client must accept text/event-stream\"\n },\n id: null\n }),\n {\n status: 406,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const sessionError = this.validateSession(request);\n if (sessionError) {\n return sessionError;\n }\n\n // Validate protocol version on subsequent requests\n const versionError = this.validateProtocolVersion(request);\n if (versionError) {\n return versionError;\n }\n\n let streamId = this.standaloneSseStreamId;\n\n // Check for resumability via Last-Event-ID\n const lastEventId = request.headers.get(\"Last-Event-ID\");\n if (lastEventId && this.eventStore) {\n // Get the stream ID for this event if available\n const eventStreamId =\n await this.eventStore.getStreamIdForEventId?.(lastEventId);\n if (eventStreamId) {\n streamId = eventStreamId;\n }\n }\n\n if (this.streamMapping.get(streamId) !== undefined) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Conflict: Only one SSE stream is allowed per session\"\n },\n id: null\n }),\n {\n status: 409,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n const headers = new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n ...this.getHeaders()\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n // Keepalive policy on the standalone GET stream:\n // - eventStore configured → no keepalive. Idle drops are\n // recovered by clients reconnecting with Last-Event-ID.\n // - no eventStore → arm a 25s comment-frame keepalive so the\n // stream isn't closed by the Cloudflare edge ~5min idle\n // watchdog. Without an event store there is no recovery path,\n // so this preserves the pre-fix behaviour for callers who\n // haven't opted into resumability.\n // See cloudflare/agents#1583.\n const keepAlive = this.eventStore\n ? undefined\n : startKeepalive(writer, encoder);\n // `cleanup` reads `streamId` lazily so it stays correct across the\n // eventStore remap below.\n const cleanup = () => {\n if (keepAlive !== undefined) clearInterval(keepAlive);\n this.streamMapping.delete(streamId);\n writer.close().catch(() => {});\n };\n this.streamMapping.set(streamId, { writer, encoder, cleanup });\n\n // Write priming event with retry interval if configured\n if (this.retryInterval !== undefined) {\n await writer.write(encoder.encode(`retry: ${this.retryInterval}\\n\\n`));\n }\n\n // Replay events if resuming and eventStore is configured\n if (lastEventId && this.eventStore) {\n const replayedStreamId = await this.eventStore.replayEventsAfter(\n lastEventId,\n {\n send: async (eventId: EventId, message: JSONRPCMessage) => {\n const data = `id: ${eventId}\\nevent: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(encoder.encode(data));\n }\n }\n );\n // Update stream ID if different from what we had. Reuse the same\n // `cleanup` closure as above so any future teardown work (e.g.\n // tearing down a keepalive) is impossible to leak in this branch.\n if (replayedStreamId !== streamId) {\n this.streamMapping.delete(streamId);\n streamId = replayedStreamId;\n this.streamMapping.set(streamId, { writer, encoder, cleanup });\n }\n }\n\n return new Response(readable, { headers });\n }\n\n private async handlePostRequest(\n request: Request,\n parsedBody?: unknown\n ): Promise<Response> {\n const acceptHeader = request.headers.get(\"Accept\");\n if (\n !acceptHeader?.includes(\"application/json\") ||\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Not Acceptable: Client must accept both application/json and text/event-stream\"\n },\n id: null\n }),\n {\n status: 406,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const contentType = request.headers.get(\"Content-Type\");\n if (!contentType?.includes(\"application/json\")) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Unsupported Media Type: Content-Type must be application/json\"\n },\n id: null\n }),\n {\n status: 415,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n let rawMessage = parsedBody;\n if (rawMessage === undefined) {\n try {\n rawMessage = await request.json();\n } catch {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n }\n\n let messages: JSONRPCMessage[];\n try {\n if (Array.isArray(rawMessage)) {\n messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n } else {\n messages = [JSONRPCMessageSchema.parse(rawMessage)];\n }\n } catch {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON-RPC message\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const requestInfo: RequestInfo = {\n headers: Object.fromEntries(request.headers.entries()),\n url: new URL(request.url)\n };\n\n const isInitializationRequest = messages.some(isInitializeRequest);\n\n if (isInitializationRequest) {\n if (this.initialized && this.sessionId !== undefined) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message: \"Invalid Request: Server already initialized\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n if (messages.length > 1) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message:\n \"Invalid Request: Only one initialization request is allowed\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n this.sessionId = this.sessionIdGenerator?.();\n this.initialized = true;\n\n const initMessage = messages.find(isInitializeRequest);\n if (initMessage && isInitializeRequest(initMessage)) {\n this.initializeParams = {\n capabilities: initMessage.params.capabilities,\n clientInfo: initMessage.params.clientInfo,\n protocolVersion: initMessage.params.protocolVersion\n };\n }\n\n await this.saveState();\n\n if (this.sessionId && this.onsessioninitialized) {\n this.onsessioninitialized(this.sessionId);\n }\n }\n\n if (!isInitializationRequest) {\n const sessionError = this.validateSession(request);\n if (sessionError) {\n return sessionError;\n }\n\n // Validate protocol version on subsequent requests\n const versionError = this.validateProtocolVersion(request);\n if (versionError) {\n return versionError;\n }\n }\n\n const hasRequests = messages.some(isJSONRPCRequest);\n\n if (!hasRequests) {\n for (const message of messages) {\n this.onmessage?.(message, { requestInfo });\n }\n return new Response(null, {\n status: 202,\n headers: { ...this.getHeaders() }\n });\n }\n\n const streamId = crypto.randomUUID();\n\n if (this.enableJsonResponse) {\n return new Promise<Response>((resolve) => {\n this.streamMapping.set(streamId, {\n resolveJson: resolve,\n cleanup: () => {\n this.streamMapping.delete(streamId);\n }\n });\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this.requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n for (const message of messages) {\n this.onmessage?.(message, { requestInfo });\n }\n });\n }\n\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n const headers = new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n ...this.getHeaders()\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n // POST response streams are scoped to a request id and can't be\n // resumed via Last-Event-ID, so we keepalive unconditionally so\n // long-running tool calls survive the ~5min Cloudflare edge idle\n // watchdog. See cloudflare/agents#1583.\n const keepAlive = startKeepalive(writer, encoder);\n this.streamMapping.set(streamId, {\n writer,\n encoder,\n cleanup: () => {\n clearInterval(keepAlive);\n this.streamMapping.delete(streamId);\n writer.close().catch(() => {});\n }\n });\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this.requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n for (const message of messages) {\n this.onmessage?.(message, { requestInfo });\n }\n\n return new Response(readable, { headers });\n }\n\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionError = this.validateSession(request);\n if (sessionError) {\n return sessionError;\n }\n\n // Validate protocol version on subsequent requests\n const versionError = this.validateProtocolVersion(request);\n if (versionError) {\n return versionError;\n }\n\n // Capture session ID before closing\n const closedSessionId = this.sessionId;\n\n await this.close();\n\n // Fire onsessionclosed callback if configured\n if (closedSessionId && this.onsessionclosed) {\n this.onsessionclosed(closedSessionId);\n }\n\n return new Response(null, {\n status: 200,\n headers: { ...this.getHeaders() }\n });\n }\n\n private handleOptionsRequest(_request: Request): Response {\n return new Response(null, {\n status: 200,\n headers: { ...this.getHeaders({ forPreflight: true }) }\n });\n }\n\n private handleUnsupportedRequest(): Response {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Method not allowed.\"\n },\n id: null\n }),\n {\n status: 405,\n headers: {\n Allow: \"GET, POST, DELETE, OPTIONS\",\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n private validateSession(request: Request): Response | undefined {\n if (this.sessionIdGenerator === undefined) {\n return undefined;\n }\n\n if (!this.initialized) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Server not initialized\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n const sessionId = request.headers.get(\"mcp-session-id\");\n\n if (!sessionId) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\"\n },\n id: null\n }),\n {\n status: 400,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n if (sessionId !== this.sessionId) {\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32001,\n message: \"Session not found\"\n },\n id: null\n }),\n {\n status: 404,\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n }\n }\n );\n }\n\n return undefined;\n }\n\n async close(): Promise<void> {\n for (const { cleanup } of this.streamMapping.values()) {\n cleanup();\n }\n\n this.streamMapping.clear();\n this.requestResponseMap.clear();\n this.onclose?.();\n }\n\n /**\n * Close an SSE stream for a specific request, triggering client reconnection.\n * Use this to implement polling behavior during long-running operations -\n * client will reconnect after the retry interval specified in the priming event.\n */\n closeSSEStream(requestId: RequestId): void {\n const streamId = this.requestToStreamMapping.get(requestId);\n if (!streamId) {\n return;\n }\n\n const stream = this.streamMapping.get(streamId);\n if (stream) {\n stream.cleanup();\n }\n\n // Clean up request mappings for this stream\n for (const [reqId, sid] of this.requestToStreamMapping.entries()) {\n if (sid === streamId) {\n this.requestToStreamMapping.delete(reqId);\n this.requestResponseMap.delete(reqId);\n }\n }\n }\n\n async send(\n message: JSONRPCMessage,\n options?: TransportSendOptions\n ): Promise<void> {\n // Check relatedRequestId FIRST to route server-to-client requests through the same stream as the originating client request\n let requestId: RequestId | undefined = options?.relatedRequestId;\n\n // Then override with message.id for responses/errors\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n requestId = message.id;\n }\n\n if (requestId === RESTORE_REQUEST_ID) {\n return;\n }\n\n if (requestId === undefined) {\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n throw new Error(\n \"Cannot send a response on a standalone SSE stream unless resuming a previous client request\"\n );\n }\n\n const standaloneSse = this.streamMapping.get(this.standaloneSseStreamId);\n if (standaloneSse === undefined) {\n return;\n }\n\n if (standaloneSse.writer && standaloneSse.encoder) {\n // Store event for resumability if eventStore is configured\n let eventId: EventId | undefined;\n if (this.eventStore) {\n eventId = await this.eventStore.storeEvent(\n this.standaloneSseStreamId,\n message\n );\n }\n\n const idLine = eventId ? `id: ${eventId}\\n` : \"\";\n const data = `${idLine}event: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await standaloneSse.writer.write(standaloneSse.encoder.encode(data));\n }\n return;\n }\n\n const streamId = this.requestToStreamMapping.get(requestId);\n if (!streamId) {\n throw new Error(\n `No connection established for request ID: ${String(requestId)}`\n );\n }\n\n const response = this.streamMapping.get(streamId);\n if (!response) {\n throw new Error(\n `No connection established for request ID: ${String(requestId)}`\n );\n }\n\n if (!this.enableJsonResponse) {\n if (response.writer && response.encoder) {\n // Store event for resumability if eventStore is configured\n let eventId: EventId | undefined;\n if (this.eventStore) {\n eventId = await this.eventStore.storeEvent(streamId, message);\n }\n\n const idLine = eventId ? `id: ${eventId}\\n` : \"\";\n const data = `${idLine}event: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await response.writer.write(response.encoder.encode(data));\n }\n }\n\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n this.requestResponseMap.set(requestId, message);\n\n const relatedIds = Array.from(this.requestToStreamMapping.entries())\n .filter(([, sid]) => sid === streamId)\n .map(([id]) => id);\n\n const allResponsesReady = relatedIds.every((id) =>\n this.requestResponseMap.has(id)\n );\n\n if (allResponsesReady) {\n if (this.enableJsonResponse && response.resolveJson) {\n const responses = relatedIds.map(\n (id) => this.requestResponseMap.get(id)!\n );\n\n const headers = new Headers({\n \"Content-Type\": \"application/json\",\n ...this.getHeaders()\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n const body = responses.length === 1 ? responses[0] : responses;\n response.resolveJson(new Response(JSON.stringify(body), { headers }));\n } else {\n response.cleanup();\n }\n\n for (const id of relatedIds) {\n this.requestResponseMap.delete(id);\n this.requestToStreamMapping.delete(id);\n }\n }\n }\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport interface McpAuthContext {\n props: Record<string, unknown>;\n}\n\nconst authContextStorage = new AsyncLocalStorage<McpAuthContext>();\n\nexport function getMcpAuthContext(): McpAuthContext | undefined {\n return authContextStorage.getStore();\n}\n\nexport function runWithAuthContext<T>(context: McpAuthContext, fn: () => T): T {\n return authContextStorage.run(context, fn);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n WorkerTransport,\n type WorkerTransportOptions\n} from \"./worker-transport\";\nimport { runWithAuthContext, type McpAuthContext } from \"./auth-context\";\n\nexport interface CreateMcpHandlerOptions extends WorkerTransportOptions {\n /**\n * The route path that this MCP handler should respond to.\n * If specified, the handler will only process requests that match this route.\n * @default \"/mcp\"\n */\n route?: string;\n /**\n * An optional auth context to use for handling MCP requests.\n * If not provided, the handler will look for props in the execution context.\n */\n authContext?: McpAuthContext;\n /**\n * An optional transport to use for handling MCP requests.\n * If not provided, a WorkerTransport will be created with the provided WorkerTransportOptions.\n */\n transport?: WorkerTransport;\n}\n\nexport function createMcpHandler(\n server: McpServer | Server,\n options: CreateMcpHandlerOptions = {}\n): (\n request: Request,\n env: unknown,\n ctx: ExecutionContext\n) => Promise<Response> {\n const route = options.route ?? \"/mcp\";\n\n return async (\n request: Request,\n _env: unknown,\n ctx: ExecutionContext\n ): Promise<Response> => {\n const url = new URL(request.url);\n if (route && url.pathname !== route) {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n const transport =\n options.transport ??\n new WorkerTransport({\n sessionIdGenerator: options.sessionIdGenerator,\n enableJsonResponse: options.enableJsonResponse,\n onsessioninitialized: options.onsessioninitialized,\n corsOptions: options.corsOptions,\n storage: options.storage\n });\n\n const buildAuthContext = () => {\n if (options.authContext) {\n return options.authContext;\n }\n\n if (ctx.props && Object.keys(ctx.props).length > 0) {\n return {\n props: ctx.props as Record<string, unknown>\n };\n }\n\n return undefined;\n };\n\n const handleRequest = async () => {\n return await transport.handleRequest(request);\n };\n\n const authContext = buildAuthContext();\n\n // Guard for stateful usage where a pre-connected transport is passed via options.\n // If someone passes a transport that's already connected to this server, skip reconnecting.\n // Note: If a developer incorrectly uses a global server with per-request transports,\n // the MCP SDK 1.26.0+ will throw an error when trying to connect an already-connected server.\n if (!transport.started) {\n // Check if server is already connected (McpServer has isConnected(), Server uses transport getter)\n const isServerConnected =\n server instanceof McpServer\n ? server.isConnected()\n : server.transport !== undefined;\n\n if (isServerConnected) {\n throw new Error(\n \"Server is already connected to a transport. Create a new McpServer instance per request for stateless handlers.\"\n );\n }\n\n await server.connect(transport);\n }\n\n try {\n if (authContext) {\n return await runWithAuthContext(authContext, handleRequest);\n } else {\n return await handleRequest();\n }\n } catch (error) {\n console.error(\"MCP handler error:\", error);\n\n return new Response(\n JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32603,\n message:\n error instanceof Error ? error.message : \"Internal server error\"\n },\n id: null\n }),\n { status: 500, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n };\n}\n\nlet didWarnAboutExperimentalCreateMcpHandler = false;\n\n/**\n * @deprecated This has been renamed to createMcpHandler, and experimental_createMcpHandler will be removed in the next major version\n */\nexport function experimental_createMcpHandler(\n server: McpServer | Server,\n options: CreateMcpHandlerOptions = {}\n): (\n request: Request,\n env: unknown,\n ctx: ExecutionContext\n) => Promise<Response> {\n if (!didWarnAboutExperimentalCreateMcpHandler) {\n didWarnAboutExperimentalCreateMcpHandler = true;\n console.warn(\n \"experimental_createMcpHandler is deprecated, use createMcpHandler instead. experimental_createMcpHandler will be removed in the next major version.\"\n );\n }\n return createMcpHandler(server, options);\n}\n","import type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n JSONRPCMessage,\n MessageExtraInfo,\n RequestId\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n JSONRPCMessageSchema,\n isJSONRPCErrorResponse,\n isJSONRPCResultResponse,\n type ElicitResult\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Connection, ConnectionContext } from \"../\";\nimport { Agent } from \"../index\";\nimport type { BaseTransportType, MaybePromise, ServeOptions } from \"./types\";\nimport {\n createAutoHandler,\n createLegacySseHandler,\n createStreamingHttpHandler,\n handleCORS,\n isDurableObjectNamespace,\n MCP_HTTP_METHOD_HEADER,\n MCP_MESSAGE_HEADER\n} from \"./utils\";\nimport { McpSSETransport, StreamableHTTPServerTransport } from \"./transport\";\nimport type { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { DurableObjectEventStore } from \"./event-store\";\nimport { RPCServerTransport, type RPCServerTransportOptions } from \"./rpc\";\n\nexport abstract class McpAgent<\n Env extends Cloudflare.Env = Cloudflare.Env,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>\n> extends Agent<Env, State, Props> {\n private _transport?: Transport;\n private _pendingElicitations = new Map<\n string,\n { resolve: (result: ElicitResult) => void; reject: (err: Error) => void }\n >();\n props?: Props;\n\n // MCP WebSocket connections are transport bridges — they use their own\n // protocol and don't need agent identity, state sync, or other protocol\n // messages. Regular WebSocket connections are left untouched.\n override shouldSendProtocolMessages(\n _connection: Connection,\n ctx: ConnectionContext\n ): boolean {\n return !ctx.request.headers.get(MCP_HTTP_METHOD_HEADER);\n }\n\n abstract server: MaybePromise<McpServer | Server>;\n abstract init(): Promise<void>;\n\n /*\n * Helpers\n */\n\n async setInitializeRequest(initializeRequest: JSONRPCMessage) {\n await this.ctx.storage.put(\"initializeRequest\", initializeRequest);\n }\n\n async getInitializeRequest() {\n return this.ctx.storage.get<JSONRPCMessage>(\"initializeRequest\");\n }\n\n /**\n * Storage key prefix for the `streamId -> requestIds` mapping used\n * to support POST stream resumption across WebSocket reconnects.\n *\n * @internal\n */\n private static readonly STREAM_REQS_KEY_PREFIX = \"__mcp_stream_reqs__:\";\n\n /** Persist the `requestIds` for a POST stream. @internal */\n async setStreamRequestIds(\n streamId: string,\n requestIds: RequestId[]\n ): Promise<void> {\n await this.ctx.storage.put<RequestId[]>(\n `${McpAgent.STREAM_REQS_KEY_PREFIX}${streamId}`,\n requestIds\n );\n }\n\n /** Read the persisted `requestIds` for a POST stream. @internal */\n async getStreamRequestIds(\n streamId: string\n ): Promise<RequestId[] | undefined> {\n return this.ctx.storage.get<RequestId[]>(\n `${McpAgent.STREAM_REQS_KEY_PREFIX}${streamId}`\n );\n }\n\n /** Drop the persisted `requestIds` for a POST stream. @internal */\n async deleteStreamRequestIds(streamId: string): Promise<void> {\n await this.ctx.storage.delete(\n `${McpAgent.STREAM_REQS_KEY_PREFIX}${streamId}`\n );\n }\n\n /**\n * Reverse lookup: find which POST stream a given `requestId` belongs\n * to, and return the stream's full `requestIds` list in the same\n * pass. Used by the transport when the originating WS has dropped,\n * so `send()` can still record events for replay and decide whether\n * the stream is fully responded — mirrors the SDK's\n * `_requestToStreamMapping` which outlives connection loss.\n *\n * Returning `requestIds` alongside `streamId` lets `send()` skip a\n * second `getStreamRequestIds` read on the same key.\n *\n * O(n) in the number of in-flight POST streams — single-digit in\n * practice since each stream is cleaned up on its final response.\n * The `limit` is a defensive ceiling so an abandoned-POST leak can't\n * unbounded-load this scan; if you hit it, something else has gone\n * wrong and `send()` will throw `No active stream found`.\n *\n * @internal\n */\n async getStreamForRequestId(\n requestId: RequestId\n ): Promise<{ streamId: string; requestIds: RequestId[] } | undefined> {\n const STREAM_REQS_SCAN_LIMIT = 1000;\n const rows = await this.ctx.storage.list<RequestId[]>({\n prefix: McpAgent.STREAM_REQS_KEY_PREFIX,\n limit: STREAM_REQS_SCAN_LIMIT\n });\n if (rows.size === STREAM_REQS_SCAN_LIMIT) {\n console.warn(\n `McpAgent: getStreamForRequestId hit the ${STREAM_REQS_SCAN_LIMIT}-key scan cap; ` +\n `stale __mcp_stream_reqs__ entries may be accumulating from abandoned POSTs`\n );\n }\n for (const [key, requestIds] of rows) {\n if (requestIds?.includes(requestId)) {\n return {\n streamId: key.slice(McpAgent.STREAM_REQS_KEY_PREFIX.length),\n requestIds\n };\n }\n }\n return undefined;\n }\n\n /** Read the transport type for this agent.\n * This relies on the naming scheme being `sse:${sessionId}`,\n * `streamable-http:${sessionId}`, or `rpc:${sessionId}`.\n */\n getTransportType(): BaseTransportType {\n const [t, ..._] = this.name.split(\":\");\n switch (t) {\n case \"sse\":\n return \"sse\";\n case \"streamable-http\":\n return \"streamable-http\";\n case \"rpc\":\n return \"rpc\";\n default:\n throw new Error(\n \"Invalid transport type. McpAgent must be addressed with a valid protocol.\"\n );\n }\n }\n\n /** Read the sessionId for this agent.\n * This relies on the naming scheme being `sse:${sessionId}`\n * or `streamable-http:${sessionId}`.\n */\n getSessionId(): string {\n const [_, sessionId] = this.name.split(\":\");\n if (!sessionId) {\n throw new Error(\n \"Invalid session id. McpAgent must be addressed with a valid session id.\"\n );\n }\n return sessionId;\n }\n\n /** Get the unique WebSocket. SSE transport only. */\n getWebSocket() {\n const websockets = Array.from(this.getConnections());\n if (websockets.length === 0) {\n return null;\n }\n return websockets[0];\n }\n\n /**\n * Returns options for configuring the RPC server transport.\n * Override this method to customize RPC transport behavior (e.g., timeout).\n *\n * @example\n * ```typescript\n * class MyMCP extends McpAgent {\n * protected getRpcTransportOptions() {\n * return { timeout: 120000 }; // 2 minutes\n * }\n * }\n * ```\n */\n protected getRpcTransportOptions(): RPCServerTransportOptions {\n return {};\n }\n\n /**\n * Returns the {@link EventStore} for SSE resumability. Defaults to a\n * {@link DurableObjectEventStore} backed by this agent's storage,\n * letting clients reconnect with `Last-Event-ID` after the Cloudflare\n * edge closes an idle SSE stream (~5 minute watchdog) instead of\n * relying on a server-side keepalive that would block hibernation.\n *\n * Per-stream events are cleared by the transport immediately after\n * the final response is written to the wire, so there's no\n * background cleanup — storage cost is bounded by the in-flight\n * streams alone.\n *\n * Override to disable (`return undefined`) or swap implementations.\n */\n protected getEventStore(): EventStore | undefined {\n return new DurableObjectEventStore(this.ctx.storage);\n }\n\n /** Returns a new transport matching the type of the Agent. */\n private initTransport() {\n switch (this.getTransportType()) {\n case \"sse\": {\n return new McpSSETransport();\n }\n case \"streamable-http\": {\n const transport = new StreamableHTTPServerTransport({\n eventStore: this.getEventStore()\n });\n transport.messageInterceptor = (message) => {\n return Promise.resolve(this._handleElicitationResponse(message));\n };\n return transport;\n }\n case \"rpc\": {\n return new RPCServerTransport(this.getRpcTransportOptions());\n }\n }\n }\n\n /** Update and store the props */\n async updateProps(props?: Props) {\n await this.ctx.storage.put(\"props\", props ?? {});\n this.props = props;\n }\n\n async reinitializeServer() {\n // If the agent was previously initialized, we have to populate\n // the server again by sending the initialize request to make\n // client information available to the server.\n const initializeRequest = await this.getInitializeRequest();\n if (initializeRequest) {\n this._transport?.onmessage?.(initializeRequest);\n }\n }\n\n /*\n * Base Agent / Partykit Server overrides\n */\n\n /** Sets up the MCP transport and server every time the Agent is started.*/\n async onStart(props?: Props) {\n if (props) {\n // Fresh start with props — save to storage (also sets this.props)\n await this.updateProps(props);\n } else {\n // Hibernation recovery — restore props from storage\n this.props = await this.ctx.storage.get(\"props\");\n }\n\n await this.init();\n const server = await this.server;\n // Connect to the MCP server\n this._transport = this.initTransport();\n\n if (!this._transport) {\n throw new Error(\"Failed to initialize transport\");\n }\n await server.connect(this._transport);\n\n await this.reinitializeServer();\n }\n\n /** Validates new WebSocket connections. */\n async onConnect(\n conn: Connection,\n { request: req }: ConnectionContext\n ): Promise<void> {\n switch (this.getTransportType()) {\n case \"sse\": {\n // For SSE connections, we can only have one open connection per session\n // If we get an upgrade while already connected, we should error\n const websockets = Array.from(this.getConnections());\n if (websockets.length > 1) {\n conn.close(1008, \"Websocket already connected\");\n return;\n }\n break;\n }\n case \"streamable-http\":\n if (this._transport instanceof StreamableHTTPServerTransport) {\n switch (req.headers.get(MCP_HTTP_METHOD_HEADER)) {\n case \"POST\": {\n // This returns the response directly to the client\n const payloadHeader = req.headers.get(MCP_MESSAGE_HEADER);\n let rawPayload: string;\n\n if (!payloadHeader) {\n rawPayload = \"{}\";\n } else {\n try {\n rawPayload = Buffer.from(payloadHeader, \"base64\").toString(\n \"utf-8\"\n );\n } catch (_error) {\n throw new Error(\n \"Internal Server Error: Failed to decode MCP message header\"\n );\n }\n }\n\n const parsedBody = JSON.parse(rawPayload);\n this._transport?.handlePostRequest(req, parsedBody);\n break;\n }\n case \"GET\":\n this._transport?.handleGetRequest(req);\n break;\n }\n }\n }\n }\n\n /*\n * Transport ingress and routing\n */\n\n /** Handles MCP Messages for the legacy SSE transport. */\n async onSSEMcpMessage(\n _sessionId: string,\n messageBody: unknown,\n extraInfo?: MessageExtraInfo\n ): Promise<Error | null> {\n // Since we address the DO via both the protocol and the session id,\n // this should never happen, but let's enforce it just in case\n if (this.getTransportType() !== \"sse\") {\n return new Error(\"Internal Server Error: Expected SSE transport\");\n }\n\n try {\n let parsedMessage: JSONRPCMessage;\n try {\n parsedMessage = JSONRPCMessageSchema.parse(messageBody);\n } catch (error) {\n this._transport?.onerror?.(error as Error);\n throw error;\n }\n\n // Check if this is an elicitation response before passing to transport\n if (this._handleElicitationResponse(parsedMessage)) {\n return null; // Message was handled by elicitation system\n }\n\n this._transport?.onmessage?.(parsedMessage, extraInfo);\n return null;\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n this._transport?.onerror?.(error as Error);\n return error as Error;\n }\n }\n\n /** Elicit user input with a message and schema */\n async elicitInput(\n params: {\n message: string;\n requestedSchema: unknown;\n },\n options?: { relatedRequestId?: RequestId }\n ): Promise<ElicitResult> {\n const requestId = `elicit_${Math.random().toString(36).substring(2, 11)}`;\n\n const elicitRequest = {\n jsonrpc: \"2.0\" as const,\n id: requestId,\n method: \"elicitation/create\",\n params: {\n message: params.message,\n requestedSchema: params.requestedSchema\n }\n };\n\n // Create a Promise that will be resolved when the response arrives.\n // timeoutId is hoisted so error paths below can clear it and avoid\n // an unhandled rejection on the orphaned responsePromise.\n let timeoutId: ReturnType<typeof setTimeout>;\n const responsePromise = new Promise<ElicitResult>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n this._pendingElicitations.delete(requestId);\n reject(new Error(\"Elicitation request timed out\"));\n }, 60000);\n\n this._pendingElicitations.set(requestId, {\n resolve: (result: ElicitResult) => {\n clearTimeout(timeoutId);\n this._pendingElicitations.delete(requestId);\n resolve(result);\n },\n reject: (err: Error) => {\n clearTimeout(timeoutId);\n this._pendingElicitations.delete(requestId);\n reject(err);\n }\n });\n });\n\n const cleanup = () => {\n clearTimeout(timeoutId);\n this._pendingElicitations.delete(requestId);\n };\n\n // Keep the DO alive while we wait for the user's elicitation response.\n // An unresolved Promise alone isn't enough to prevent hibernation.\n return this.keepAliveWhile(async () => {\n // Send through MCP transport\n if (this._transport) {\n try {\n await this._transport.send(elicitRequest, options);\n } catch (error) {\n cleanup();\n throw error;\n }\n } else {\n const connections = this.getConnections();\n if (!connections || Array.from(connections).length === 0) {\n cleanup();\n throw new Error(\"No active connections available for elicitation\");\n }\n\n const connectionList = Array.from(connections);\n for (const connection of connectionList) {\n try {\n connection.send(JSON.stringify(elicitRequest));\n } catch (error) {\n console.error(\"Failed to send elicitation request:\", error);\n }\n }\n }\n\n return responsePromise;\n });\n }\n\n /** Handle elicitation responses via in-memory resolver */\n private _handleElicitationResponse(message: JSONRPCMessage): boolean {\n if (isJSONRPCResultResponse(message) && message.result) {\n const requestId = message.id?.toString();\n if (!requestId || !requestId.startsWith(\"elicit_\")) return false;\n\n const pending = this._pendingElicitations.get(requestId);\n if (!pending) return false;\n\n pending.resolve(message.result as ElicitResult);\n return true;\n }\n\n if (isJSONRPCErrorResponse(message)) {\n const requestId = message.id?.toString();\n if (!requestId || !requestId.startsWith(\"elicit_\")) return false;\n\n const pending = this._pendingElicitations.get(requestId);\n if (!pending) return false;\n\n pending.resolve({\n action: \"cancel\",\n content: {\n error: message.error.message || \"Elicitation request failed\"\n }\n });\n return true;\n }\n\n return false;\n }\n\n /**\n * Handle an RPC message for MCP\n * This method is called by the RPC stub to process MCP messages\n * @param message The JSON-RPC message(s) to handle\n * @returns The response message(s) or undefined\n */\n async handleMcpMessage(\n message: JSONRPCMessage | JSONRPCMessage[]\n ): Promise<JSONRPCMessage | JSONRPCMessage[] | undefined> {\n await this.__unsafe_ensureInitialized();\n\n if (!(this._transport instanceof RPCServerTransport)) {\n throw new Error(\"Expected RPC transport\");\n }\n\n const transport = this._transport;\n\n // RPC waits are intentionally in-memory. While a request/continuation is\n // pending, keep the object alive so hibernation does not drop the resolver\n // maps or the suspended tool stack. Making this sleep/resume across\n // hibernation would require a durable continuation model instead.\n return await this.keepAliveWhile(async () => {\n // Intercept elicitation responses before they reach the transport.\n // Mirrors what onSSEMcpMessage() and StreamableHTTPServerTransport's\n // messageInterceptor already do for their respective transports.\n if (!Array.isArray(message)) {\n const parseResult = JSONRPCMessageSchema.safeParse(message);\n if (\n parseResult.success &&\n this._handleElicitationResponse(parseResult.data)\n ) {\n // Resolved a pending elicitation — now wait for the tool handler\n // to send its next message (another elicitation request or the\n // final tool result).\n return await transport._awaitPendingResponse();\n }\n }\n\n return await transport.handle(message);\n });\n }\n\n /** Return a handler for the given path for this MCP.\n * Defaults to Streamable HTTP transport.\n */\n static serve(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n transport = \"streamable-http\",\n jurisdiction\n }: ServeOptions = {}\n ) {\n return {\n async fetch<Env>(\n this: void,\n request: Request,\n env: Env,\n ctx: ExecutionContext\n ): Promise<Response> {\n // Handle CORS preflight\n const corsResponse = handleCORS(request, corsOptions);\n if (corsResponse) {\n return corsResponse;\n }\n\n const bindingValue = env[binding as keyof typeof env] as unknown;\n\n // Ensure we have a binding of some sort\n if (bindingValue == null || typeof bindingValue !== \"object\") {\n throw new Error(\n `Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`\n );\n }\n\n // Ensure that the binding is to a DurableObject\n if (!isDurableObjectNamespace(bindingValue)) {\n throw new Error(\n `Invalid McpAgent binding for ${binding}. Make sure it's a Durable Object binding.`\n );\n }\n\n const namespace =\n bindingValue satisfies DurableObjectNamespace<McpAgent>;\n\n switch (transport) {\n case \"streamable-http\": {\n const handleStreamableHttp = createStreamingHttpHandler(\n path,\n namespace,\n { corsOptions, jurisdiction }\n );\n return handleStreamableHttp(request, ctx);\n }\n case \"sse\": {\n const handleLegacySse = createLegacySseHandler(path, namespace, {\n corsOptions,\n jurisdiction\n });\n return handleLegacySse(request, ctx);\n }\n case \"auto\": {\n const handleAuto = createAutoHandler(path, namespace, {\n corsOptions,\n jurisdiction\n });\n return handleAuto(request, ctx);\n }\n default:\n return new Response(\n \"Invalid MCP transport mode. Only `streamable-http`, `sse`, or `auto` are allowed.\",\n { status: 500 }\n );\n }\n }\n };\n }\n /**\n * Legacy api\n **/\n static mount(path: string, opts: Omit<ServeOptions, \"transport\"> = {}) {\n return McpAgent.serveSSE(path, opts);\n }\n\n static serveSSE(path: string, opts: Omit<ServeOptions, \"transport\"> = {}) {\n return McpAgent.serve(path, { ...opts, transport: \"sse\" });\n }\n}\n\nexport {\n SSEEdgeClientTransport,\n StreamableHTTPEdgeClientTransport\n} from \"./client-transports\";\nexport {\n RPC_DO_PREFIX,\n RPCClientTransport,\n RPCServerTransport,\n type RPCClientTransportOptions,\n type RPCServerTransportOptions\n} from \"./rpc\";\n\nexport {\n ElicitRequestSchema,\n type ElicitRequest,\n type ElicitResult\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type {\n MCPClientOAuthResult,\n MCPClientOAuthCallbackConfig,\n MCPServerOptions,\n MCPConnectionResult,\n MCPDiscoverResult\n} from \"./client\";\n\nexport { normalizeServerId, MCP_SERVER_ID_MAX_LENGTH } from \"./client\";\n\nexport type { McpClientOptions } from \"./types\";\n\nexport {\n createMcpHandler,\n experimental_createMcpHandler,\n type CreateMcpHandlerOptions\n} from \"./handler\";\n\nexport { getMcpAuthContext, type McpAuthContext } from \"./auth-context\";\n\nexport { DurableObjectEventStore } from \"./event-store\";\nexport type { ClearableEventStore } from \"./transport\";\n\nexport {\n WorkerTransport,\n type WorkerTransportOptions,\n type TransportState\n} from \"./worker-transport\";\n"],"mappings":"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"}