agents 0.2.15 → 0.2.17

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 (48) hide show
  1. package/dist/ai-chat-agent.d.ts +10 -10
  2. package/dist/ai-chat-agent.js +6 -6
  3. package/dist/{ai-chat-v5-migration-gdyLiTd8.js → ai-chat-v5-migration-DBHGW4Hv.js} +2 -2
  4. package/dist/{ai-chat-v5-migration-gdyLiTd8.js.map → ai-chat-v5-migration-DBHGW4Hv.js.map} +1 -1
  5. package/dist/ai-chat-v5-migration.js +1 -1
  6. package/dist/ai-react.d.ts +9 -9
  7. package/dist/ai-react.js +1 -1
  8. package/dist/{ai-types-UZlfLOYP.js → ai-types-B3aQaFv3.js} +2 -2
  9. package/dist/{ai-types-UZlfLOYP.js.map → ai-types-B3aQaFv3.js.map} +1 -1
  10. package/dist/{ai-types-BWW4umHY.d.ts → ai-types-D5YoPrBZ.d.ts} +2 -2
  11. package/dist/ai-types.d.ts +4 -4
  12. package/dist/ai-types.js +1 -1
  13. package/dist/{client-CZBVDDoO.js → client-9Ld2_lnt.js} +2 -2
  14. package/dist/{client-CZBVDDoO.js.map → client-9Ld2_lnt.js.map} +1 -1
  15. package/dist/{client-C-nwz-3N.d.ts → client-B17XUTV7.d.ts} +20 -20
  16. package/dist/{client-DjR-lC16.js → client-BfiZ3HQd.js} +3 -3
  17. package/dist/{client-DjR-lC16.js.map → client-BfiZ3HQd.js.map} +1 -1
  18. package/dist/{client-CmMi85Sj.d.ts → client-CbWe9FBd.d.ts} +10 -10
  19. package/dist/client.d.ts +8 -8
  20. package/dist/client.js +2 -2
  21. package/dist/codemode/ai.js +5 -5
  22. package/dist/{do-oauth-client-provider-B2jr6UNq.js → do-oauth-client-provider-CswoD5Lu.js} +2 -2
  23. package/dist/{do-oauth-client-provider-B2jr6UNq.js.map → do-oauth-client-provider-CswoD5Lu.js.map} +1 -1
  24. package/dist/{do-oauth-client-provider-CCwGwnrA.d.ts → do-oauth-client-provider-DGc5pP0l.d.ts} +2 -2
  25. package/dist/{index-DWJSBMbz.d.ts → index-B6MjW6n-.d.ts} +49 -225
  26. package/dist/{index-W4JUkafc.d.ts → index-DhJCaDWd.d.ts} +7 -3
  27. package/dist/index.d.ts +36 -50
  28. package/dist/index.js +6 -6
  29. package/dist/mcp/client.d.ts +3 -3
  30. package/dist/mcp/client.js +1 -1
  31. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  32. package/dist/mcp/do-oauth-client-provider.js +1 -1
  33. package/dist/mcp/index.d.ts +129 -7
  34. package/dist/mcp/index.js +1234 -6
  35. package/dist/mcp/index.js.map +1 -0
  36. package/dist/{mcp-BEwaCsxO.d.ts → mcp-Dw5vDrY8.d.ts} +2 -2
  37. package/dist/observability/index.d.ts +2 -2
  38. package/dist/observability/index.js +5 -5
  39. package/dist/{react-GnTP-a01.d.ts → react-CRBsIQ1z.d.ts} +28 -26
  40. package/dist/react.d.ts +9 -9
  41. package/dist/react.js +1 -1
  42. package/dist/{serializable-gtr9YMhp.d.ts → serializable-CymX8ovI.d.ts} +8 -3
  43. package/dist/serializable.d.ts +5 -5
  44. package/dist/src-Dz0H9hSU.js +1200 -0
  45. package/dist/src-Dz0H9hSU.js.map +1 -0
  46. package/package.json +5 -5
  47. package/dist/src-tpG9NtHy.js +0 -2457
  48. package/dist/src-tpG9NtHy.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"src-tpG9NtHy.js","names":["genericObservability: Observability","body","rawMessage: unknown","arrayMessage: unknown[]","messages: JSONRPCMessage[]","existingHeaders: Record<string, string>","event","authInfo: AuthInfo | undefined","requestInfo: RequestInfo","messages: JSONRPCMessage[]","standaloneConnection: Connection | undefined","eventId: string | undefined","eventId","messages: JSONRPCMessage[]","requestId: RequestId | undefined","authContext: McpAuthContext | undefined","response: Response","rawPayload: string","parsedMessage: JSONRPCMessage","errorResult: ElicitResult","parsed: unknown","response: RPCResponse","ctx","proto","theError: unknown","schedule: Schedule<T>","parsedOptions:\n | {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n }\n | undefined","transportType: TransportType","headerTransportOpts: SSEClientTransportOptions","url","mcpState: MCPServersState","corsHeaders","agentId","map: Record<string, unknown>","serialisableEmail: AgentEmail","chunks: Uint8Array[]","options"],"sources":["../src/observability/index.ts","../src/mcp/utils.ts","../src/mcp/transport.ts","../src/mcp/worker-transport.ts","../src/mcp/auth-context.ts","../src/mcp/handler.ts","../src/mcp/index.ts","../src/index.ts"],"sourcesContent":["import { getCurrentAgent } from \"../index\";\nimport type { AgentObservabilityEvent } from \"./agent\";\nimport type { MCPObservabilityEvent } from \"./mcp\";\n\n/**\n * Union of all observability event types from different domains\n */\nexport type ObservabilityEvent =\n | AgentObservabilityEvent\n | MCPObservabilityEvent;\n\nexport interface Observability {\n /**\n * Emit an event for the Agent's observability implementation to handle.\n * @param event - The event to emit\n * @param ctx - The execution context of the invocation (optional)\n */\n emit(event: ObservabilityEvent, ctx?: DurableObjectState): void;\n}\n\n/**\n * A generic observability implementation that logs events to the console.\n */\nexport const genericObservability: Observability = {\n emit(event) {\n // In local mode, we display a pretty-print version of the event for easier debugging.\n if (isLocalMode()) {\n console.log(event.displayMessage);\n return;\n }\n\n console.log(event);\n }\n};\n\nlet localMode = false;\n\nfunction isLocalMode() {\n if (localMode) {\n return true;\n }\n const { request } = getCurrentAgent();\n if (!request) {\n return false;\n }\n\n const url = new URL(request.url);\n localMode = url.hostname === \"localhost\";\n return localMode;\n}\n","import {\n JSONRPCMessageSchema,\n type JSONRPCMessage,\n InitializeRequestSchema,\n isJSONRPCResponse,\n isJSONRPCNotification\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { McpAgent } from \".\";\nimport { getAgentByName } from \"..\";\nimport type { CORSOptions } from \"./types\";\nimport { MessageType } from \"../ai-types\";\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 corsOptions?: CORSOptions\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 { props: ctx.props as Record<string, unknown> | undefined }\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 if (ctx.props) agent.updateProps(ctx.props as Record<string, unknown>);\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 // 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 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 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 await writer.close().catch(() => {});\n }\n onClose().catch(console.error);\n });\n\n // If there are no requests, we send the messages to the agent and acknowledge the request with a 202\n // since we don't expect any responses back through this connection\n const hasOnlyNotificationsOrResponses = messages.every(\n (msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(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, corsOptions),\n status: 202\n });\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, 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 { props: ctx.props as Record<string, unknown> | undefined }\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 if (ctx.props) agent.updateProps(ctx.props as Record<string, unknown>);\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, 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, corsOptions) }\n );\n }\n const agent = await getAgentByName(\n namespace,\n `streamable-http:${sessionId}`\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, 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, 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 corsOptions?: CORSOptions\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 });\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 if (ctx.props) agent.updateProps(ctx.props as Record<string, unknown>);\n const response = await agent.fetch(\n new Request(request.url, {\n headers: {\n ...existingHeaders,\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, 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 });\n\n const messageBody = await request.json();\n const error = await agent.onSSEMcpMessage(sessionId, messageBody);\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, 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, corsOptions)\n },\n status: 202\n });\n }\n\n return new Response(\"Not Found\", { status: 404 });\n };\n};\n\n// CORS helper functions\nfunction corsHeaders(_request: Request, corsOptions: CORSOptions = {}) {\n const origin = \"*\";\n return {\n \"Access-Control-Allow-Headers\":\n corsOptions.headers ||\n \"Content-Type, Accept, mcp-session-id, mcp-protocol-version\",\n \"Access-Control-Allow-Methods\":\n corsOptions.methods || \"GET, POST, DELETE, OPTIONS\",\n \"Access-Control-Allow-Origin\": corsOptions.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 isJSONRPCError,\n isJSONRPCRequest,\n isJSONRPCResponse,\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 { getCurrentAgent, type Connection } from \"..\";\nimport type { McpAgent } from \".\";\nimport { MessageType } from \"../ai-types\";\nimport { MCP_HTTP_METHOD_HEADER, MCP_MESSAGE_HEADER } from \"./utils\";\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) => void;\n\n private _getWebSocket: () => WebSocket | null;\n private _started = false;\n constructor(getWebSocket: () => WebSocket | null) {\n this._getWebSocket = 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\nexport type StreamId = string;\nexport type EventId = string;\n\n// TODO: Implement this and make it opt-in?\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n /**\n * Stores an event for later retrieval\n * @param streamId ID of the stream the event belongs to\n * @param message The JSON-RPC message to store\n * @returns The generated event ID for the stored event\n */\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n\n replayEventsAfter(\n lastEventId: EventId,\n {\n send\n }: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n }\n ): Promise<StreamId>;\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 reconnect and resume messages\n */\n eventStore?: EventStore;\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 */\nexport class StreamableHTTPServerTransport implements Transport {\n private _started = false;\n private _eventStore?: EventStore;\n\n // This is to keep track whether all messages from a single POST request have been answered.\n // I's fine that we don't persist this since it's only for backwards compatibility as clients\n // should no longer batch requests, per the spec.\n private _requestResponseMap: Map<RequestId, JSONRPCMessage> = new Map();\n\n sessionId: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\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 async handleGetRequest(req: Request): Promise<void> {\n // Get the WS connection so we can tag it as the standalone stream\n const { connection } = getCurrentAgent();\n if (!connection)\n throw new Error(\"Connection was not found in handleGetRequest\");\n\n // Handle resumability: check for Last-Event-ID header\n if (this._eventStore) {\n const lastEventId = req.headers.get(\"last-event-id\");\n if (lastEventId) {\n await this.replayEvents(lastEventId);\n return;\n }\n }\n\n connection.setState({\n _standaloneSse: true\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 };\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 this.onmessage?.(message, { authInfo, requestInfo });\n }\n } else if (hasRequests) {\n const { connection } = getCurrentAgent();\n if (!connection)\n throw new Error(\"Connection 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 connection.setState({\n requestIds\n });\n\n // handle each message\n for (const message of messages) {\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 async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId }\n ): Promise<void> {\n const { agent } = getCurrentAgent();\n if (!agent) throw new Error(\"Agent was not found in send\");\n\n let requestId = options?.relatedRequestId;\n if (isJSONRPCResponse(message) || isJSONRPCError(message)) {\n // If the message is a response, use the request ID from the message\n requestId = message.id;\n }\n\n // Check if this message should be sent on the standalone SSE stream (no request ID)\n // Ignore notifications from tools (which have relatedRequestId set)\n // Those will be sent via dedicated response SSE streams\n if (requestId === undefined) {\n // For standalone SSE streams, we can only send requests and notifications\n if (isJSONRPCResponse(message) || isJSONRPCError(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 let standaloneConnection: Connection | undefined;\n for (const conn of agent.getConnections<{ _standaloneSse?: boolean }>()) {\n if (conn.state?._standaloneSse) standaloneConnection = conn;\n }\n\n if (standaloneConnection === undefined) {\n // The spec says the server MAY send messages on the stream, so it's ok to discard if no stream\n return;\n }\n\n // Generate and store event ID if event store is provided\n let eventId: string | undefined;\n if (this._eventStore) {\n // Stores the event and gets the generated event ID\n eventId = await this._eventStore.storeEvent(\n standaloneConnection.id,\n message\n );\n }\n\n // Send the message to the standalone SSE stream\n this.writeSSEEvent(standaloneConnection, message, eventId);\n return;\n }\n\n // Get the response for this request\n const connection = Array.from(\n agent.getConnections<{ requestIds?: number[] }>()\n ).find((conn) => conn.state?.requestIds?.includes(requestId as number));\n if (!connection) {\n throw new Error(\n `No connection established for request ID: ${String(requestId)}`\n );\n }\n\n let eventId: string | undefined;\n\n if (this._eventStore) {\n eventId = await this._eventStore.storeEvent(connection.id, message);\n }\n\n let shouldClose = false;\n\n if (isJSONRPCResponse(message) || isJSONRPCError(message)) {\n this._requestResponseMap.set(requestId, message);\n const relatedIds = connection.state?.requestIds ?? [];\n // Check if we have responses for all requests using this connection\n shouldClose = relatedIds.every((id) => this._requestResponseMap.has(id));\n\n if (shouldClose) {\n // Clean up\n for (const id of relatedIds) {\n this._requestResponseMap.delete(id);\n }\n }\n }\n this.writeSSEEvent(connection, message, eventId, shouldClose);\n }\n}\n","/**\n * Based on @hono/mcp transport implementation (https://github.com/honojs/middleware/tree/main/packages/mcp)\n */\n\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n JSONRPCMessage,\n RequestId\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n isInitializeRequest,\n isJSONRPCError,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCMessageSchema\n} from \"@modelcontextprotocol/sdk/types.js\";\n\ninterface StreamMapping {\n writer?: WritableStreamDefaultWriter<Uint8Array>;\n encoder?: TextEncoder;\n resolveJson?: (response: Response) => void;\n cleanup: () => void;\n}\n\nexport interface WorkerTransportOptions {\n sessionIdGenerator?: () => string;\n enableJsonResponse?: boolean;\n onsessioninitialized?: (sessionId: string) => void;\n}\n\nexport class WorkerTransport implements Transport {\n private started = false;\n private initialized = false;\n private sessionIdGenerator?: () => string;\n private enableJsonResponse = false;\n private onsessioninitialized?: (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\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n\n constructor(options?: WorkerTransportOptions) {\n this.sessionIdGenerator = options?.sessionIdGenerator;\n this.enableJsonResponse = options?.enableJsonResponse ?? false;\n this.onsessioninitialized = options?.onsessioninitialized;\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 async handleRequest(\n request: Request,\n parsedBody?: unknown\n ): Promise<Response> {\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 { status: 406, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n\n const sessionValid = this.validateSession(request);\n if (sessionValid !== true) {\n return sessionValid;\n }\n\n const streamId = this.standaloneSseStreamId;\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 { status: 409, headers: { \"Content-Type\": \"application/json\" } }\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 \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Expose-Headers\": \"mcp-session-id\"\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n const keepAlive = setInterval(() => {\n try {\n writer.write(encoder.encode(\"event: ping\\ndata: \\n\\n\"));\n } catch {\n clearInterval(keepAlive);\n }\n }, 30000);\n\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 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 { status: 406, headers: { \"Content-Type\": \"application/json\" } }\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 { status: 415, headers: { \"Content-Type\": \"application/json\" } }\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 { status: 400, headers: { \"Content-Type\": \"application/json\" } }\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 { status: 400, headers: { \"Content-Type\": \"application/json\" } }\n );\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 { status: 400, headers: { \"Content-Type\": \"application/json\" } }\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 { status: 400, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n\n this.sessionId = this.sessionIdGenerator?.();\n this.initialized = true;\n\n if (this.sessionId && this.onsessioninitialized) {\n this.onsessioninitialized(this.sessionId);\n }\n }\n\n if (!isInitializationRequest) {\n const sessionValid = this.validateSession(request);\n if (sessionValid !== true) {\n return sessionValid;\n }\n }\n\n const hasRequests = messages.some(isJSONRPCRequest);\n\n if (!hasRequests) {\n for (const message of messages) {\n this.onmessage?.(message);\n }\n return new Response(null, {\n status: 202,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\"\n }\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);\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 \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Expose-Headers\": \"mcp-session-id\"\n });\n\n if (this.sessionId !== undefined) {\n headers.set(\"mcp-session-id\", this.sessionId);\n }\n\n this.streamMapping.set(streamId, {\n writer,\n encoder,\n cleanup: () => {\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);\n }\n\n return new Response(readable, { headers });\n }\n\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionValid = this.validateSession(request);\n if (sessionValid !== true) {\n return sessionValid;\n }\n\n await this.close();\n return new Response(null, {\n status: 200,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\"\n }\n });\n }\n\n private handleOptionsRequest(_request: Request): Response {\n const headers = new Headers({\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\":\n \"Content-Type, Accept, Authorization, mcp-session-id\",\n \"Access-Control-Max-Age\": \"86400\"\n });\n\n return new Response(null, { status: 204, headers });\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): true | Response {\n if (this.sessionIdGenerator === undefined) {\n return true;\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 { status: 400, headers: { \"Content-Type\": \"application/json\" } }\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 { status: 400, headers: { \"Content-Type\": \"application/json\" } }\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 { status: 404, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n\n return true;\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 async send(message: JSONRPCMessage): Promise<void> {\n let requestId: RequestId | undefined;\n\n if (isJSONRPCResponse(message) || isJSONRPCError(message)) {\n requestId = message.id;\n }\n\n if (requestId === undefined) {\n if (isJSONRPCResponse(message) || isJSONRPCError(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 const data = `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 const data = `event: message\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await response.writer.write(response.encoder.encode(data));\n }\n }\n\n if (isJSONRPCResponse(message) || isJSONRPCError(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 \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Expose-Headers\": \"mcp-session-id\"\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 type { 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\nexport type OAuthExecutionContext = ExecutionContext & {\n props?: Record<string, unknown>;\n};\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 const route = options.route ?? \"/mcp\";\n\n return async (\n request: Request,\n _env: unknown,\n ctx: ExecutionContext\n ): Promise<Response> => {\n // Check if the request path matches the configured route\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 oauthCtx = ctx as OAuthExecutionContext;\n const authContext: McpAuthContext | undefined = oauthCtx.props\n ? { props: oauthCtx.props }\n : undefined;\n\n const transport = new WorkerTransport(options);\n await server.connect(transport);\n\n const handleRequest = async () => {\n return await transport.handleRequest(request);\n };\n\n try {\n let response: Response;\n\n if (authContext) {\n response = await runWithAuthContext(authContext, handleRequest);\n } else {\n response = await handleRequest();\n }\n\n return response;\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","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 { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n JSONRPCMessageSchema,\n isJSONRPCError,\n isJSONRPCResponse,\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 createLegacySseHandler,\n createStreamingHttpHandler,\n handleCORS,\n isDurableObjectNamespace,\n MCP_HTTP_METHOD_HEADER,\n MCP_MESSAGE_HEADER\n} from \"./utils\";\nimport { McpSSETransport, StreamableHTTPServerTransport } from \"./transport\";\n\nexport abstract class McpAgent<\n Env = unknown,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>\n> extends Agent<Env, State, Props> {\n private _transport?: Transport;\n props?: Props;\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 /** Read the transport type for this agent.\n * This relies on the naming scheme being `sse:${sessionId}`\n * or `streamable-http:${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 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 private getWebSocket() {\n const websockets = Array.from(this.getConnections());\n if (websockets.length === 0) {\n return null;\n }\n return websockets[0];\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(() => this.getWebSocket());\n }\n case \"streamable-http\": {\n return new StreamableHTTPServerTransport({});\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 / Parykit 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 onStart was passed props, save them in storage\n if (props) await this.updateProps(props);\n this.props = await this.ctx.storage.get(\"props\");\n\n await this.init();\n const server = await this.server;\n // Connect to the MCP server\n this._transport = this.initTransport();\n await server.connect(this._transport);\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 ): 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 (await this._handleElicitationResponse(parsedMessage)) {\n return null; // Message was handled by elicitation system\n }\n\n this._transport?.onmessage?.(parsedMessage);\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(params: {\n message: string;\n requestedSchema: unknown;\n }): Promise<ElicitResult> {\n const requestId = `elicit_${Math.random().toString(36).substring(2, 11)}`;\n\n // Store pending request in durable storage\n await this.ctx.storage.put(`elicitation:${requestId}`, {\n message: params.message,\n requestedSchema: params.requestedSchema,\n timestamp: Date.now()\n });\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 // Send through MCP transport\n if (this._transport) {\n await this._transport.send(elicitRequest);\n } else {\n const connections = this.getConnections();\n if (!connections || Array.from(connections).length === 0) {\n await this.ctx.storage.delete(`elicitation:${requestId}`);\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 // Wait for response through MCP\n return this._waitForElicitationResponse(requestId);\n }\n\n /** Wait for elicitation response through storage polling */\n private async _waitForElicitationResponse(\n requestId: string\n ): Promise<ElicitResult> {\n const startTime = Date.now();\n const timeout = 60000; // 60 second timeout\n\n try {\n while (Date.now() - startTime < timeout) {\n // Check if response has been stored\n const response = await this.ctx.storage.get<ElicitResult>(\n `elicitation:response:${requestId}`\n );\n if (response) {\n // Immediately clean up both request and response\n await this.ctx.storage.delete(`elicitation:${requestId}`);\n await this.ctx.storage.delete(`elicitation:response:${requestId}`);\n return response;\n }\n\n // Sleep briefly before checking again\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n throw new Error(\"Elicitation request timed out\");\n } finally {\n // Always clean up on timeout or error\n await this.ctx.storage.delete(`elicitation:${requestId}`);\n await this.ctx.storage.delete(`elicitation:response:${requestId}`);\n }\n }\n\n /** Handle elicitation responses */\n private async _handleElicitationResponse(\n message: JSONRPCMessage\n ): Promise<boolean> {\n // Check if this is a response to an elicitation request\n if (isJSONRPCResponse(message) && message.result) {\n const requestId = message.id?.toString();\n if (!requestId || !requestId.startsWith(\"elicit_\")) return false;\n\n // Check if we have a pending request for this ID\n const pendingRequest = await this.ctx.storage.get(\n `elicitation:${requestId}`\n );\n if (!pendingRequest) return false;\n\n // Store the response in durable storage\n await this.ctx.storage.put(\n `elicitation:response:${requestId}`,\n message.result as ElicitResult\n );\n return true;\n }\n\n // Check if this is an error response to an elicitation request\n if (isJSONRPCError(message)) {\n const requestId = message.id?.toString();\n if (!requestId || !requestId.startsWith(\"elicit_\")) return false;\n\n // Check if we have a pending request for this ID\n const pendingRequest = await this.ctx.storage.get(\n `elicitation:${requestId}`\n );\n if (!pendingRequest) return false;\n\n // Store error response\n const errorResult: ElicitResult = {\n action: \"cancel\",\n content: {\n error: message.error.message || \"Elicitation request failed\"\n }\n };\n await this.ctx.storage.put(\n `elicitation:response:${requestId}`,\n errorResult\n );\n return true;\n }\n\n return false;\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 }: 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 // Streamable HTTP transport handling\n const handleStreamableHttp = createStreamingHttpHandler(\n path,\n namespace,\n corsOptions\n );\n return handleStreamableHttp(request, ctx);\n }\n case \"sse\": {\n // Legacy SSE transport handling\n const handleLegacySse = createLegacySseHandler(\n path,\n namespace,\n corsOptions\n );\n return handleLegacySse(request, ctx);\n }\n default:\n return new Response(\n \"Invalid MCP transport mode. Only `streamable-http` or `sse` 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 { SSEEdgeClientTransport } from \"./sse-edge\";\nexport { StreamableHTTPEdgeClientTransport } from \"./streamable-http-edge\";\n\nexport {\n ElicitRequestSchema,\n type ElicitRequest,\n type ElicitResult\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type {\n MCPClientOAuthResult,\n MCPClientOAuthCallbackConfig\n} from \"./client\";\n\nexport {\n experimental_createMcpHandler,\n type CreateMcpHandlerOptions,\n type OAuthExecutionContext\n} from \"./handler\";\n\nexport { getMcpAuthContext, type McpAuthContext } from \"./auth-context\";\n\nexport {\n WorkerTransport,\n type WorkerTransportOptions\n} from \"./worker-transport\";\n","import type { env } from \"cloudflare:workers\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\n\nimport type {\n Prompt,\n Resource,\n ServerCapabilities,\n Tool\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { parseCronExpression } from \"cron-schedule\";\nimport { nanoid } from \"nanoid\";\nimport { EmailMessage } from \"cloudflare:email\";\nimport {\n type Connection,\n type ConnectionContext,\n type PartyServerOptions,\n Server,\n type WSMessage,\n getServerByName,\n routePartykitRequest\n} from \"partyserver\";\nimport { camelCaseToKebabCase } from \"./client\";\nimport { MCPClientManager, type MCPClientOAuthResult } from \"./mcp/client\";\nimport type { MCPConnectionState } from \"./mcp/client-connection\";\nimport { DurableObjectOAuthClientProvider } from \"./mcp/do-oauth-client-provider\";\nimport type { TransportType } from \"./mcp/types\";\nimport { genericObservability, type Observability } from \"./observability\";\nimport { DisposableStore } from \"./core/events\";\nimport { MessageType } from \"./ai-types\";\n\nexport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\n\n/**\n * RPC request message from client\n */\nexport type RPCRequest = {\n type: \"rpc\";\n id: string;\n method: string;\n args: unknown[];\n};\n\n/**\n * State update message from client\n */\nexport type StateUpdateMessage = {\n type: MessageType.CF_AGENT_STATE;\n state: unknown;\n};\n\n/**\n * RPC response message to client\n */\nexport type RPCResponse = {\n type: MessageType.RPC;\n id: string;\n} & (\n | {\n success: true;\n result: unknown;\n done?: false;\n }\n | {\n success: true;\n result: unknown;\n done: true;\n }\n | {\n success: false;\n error: string;\n }\n);\n\n/**\n * Type guard for RPC request messages\n */\nfunction isRPCRequest(msg: unknown): msg is RPCRequest {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === MessageType.RPC &&\n \"id\" in msg &&\n typeof msg.id === \"string\" &&\n \"method\" in msg &&\n typeof msg.method === \"string\" &&\n \"args\" in msg &&\n Array.isArray((msg as RPCRequest).args)\n );\n}\n\n/**\n * Type guard for state update messages\n */\nfunction isStateUpdateMessage(msg: unknown): msg is StateUpdateMessage {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === MessageType.CF_AGENT_STATE &&\n \"state\" in msg\n );\n}\n\n/**\n * Metadata for a callable method\n */\nexport type CallableMetadata = {\n /** Optional description of what the method does */\n description?: string;\n /** Whether the method supports streaming responses */\n streaming?: boolean;\n};\n\nconst callableMetadata = new Map<Function, CallableMetadata>();\n\n/**\n * Decorator that marks a method as callable by clients\n * @param metadata Optional metadata about the callable method\n */\nexport function callable(metadata: CallableMetadata = {}) {\n return function callableDecorator<This, Args extends unknown[], Return>(\n target: (this: This, ...args: Args) => Return,\n // biome-ignore lint/correctness/noUnusedFunctionParameters: later\n context: ClassMethodDecoratorContext\n ) {\n if (!callableMetadata.has(target)) {\n callableMetadata.set(target, metadata);\n }\n\n return target;\n };\n}\n\nlet didWarnAboutUnstableCallable = false;\n\n/**\n * Decorator that marks a method as callable by clients\n * @deprecated this has been renamed to callable, and unstable_callable will be removed in the next major version\n * @param metadata Optional metadata about the callable method\n */\nexport const unstable_callable = (metadata: CallableMetadata = {}) => {\n if (!didWarnAboutUnstableCallable) {\n didWarnAboutUnstableCallable = true;\n console.warn(\n \"unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version.\"\n );\n }\n callable(metadata);\n};\n\nexport type QueueItem<T = string> = {\n id: string;\n payload: T;\n callback: keyof Agent<unknown>;\n created_at: number;\n};\n\n/**\n * Represents a scheduled task within an Agent\n * @template T Type of the payload data\n */\nexport type Schedule<T = string> = {\n /** Unique identifier for the schedule */\n id: string;\n /** Name of the method to be called */\n callback: string;\n /** Data to be passed to the callback */\n payload: T;\n} & (\n | {\n /** Type of schedule for one-time execution at a specific time */\n type: \"scheduled\";\n /** Timestamp when the task should execute */\n time: number;\n }\n | {\n /** Type of schedule for delayed execution */\n type: \"delayed\";\n /** Timestamp when the task should execute */\n time: number;\n /** Number of seconds to delay execution */\n delayInSeconds: number;\n }\n | {\n /** Type of schedule for recurring execution based on cron expression */\n type: \"cron\";\n /** Timestamp for the next execution */\n time: number;\n /** Cron expression defining the schedule */\n cron: string;\n }\n);\n\nfunction getNextCronTime(cron: string) {\n const interval = parseCronExpression(cron);\n return interval.getNextDate();\n}\n\nexport type { TransportType } from \"./mcp/types\";\n\n// Export stateless MCP handler for simple fetch exports\nexport {\n experimental_createMcpHandler,\n getMcpAuthContext,\n WorkerTransport,\n type CreateMcpHandlerOptions,\n type OAuthExecutionContext,\n type McpAuthContext,\n type WorkerTransportOptions\n} from \"./mcp\";\n\n/**\n * MCP Server state update message from server -> Client\n */\nexport type MCPServerMessage = {\n type: MessageType.CF_AGENT_MCP_SERVERS;\n mcp: MCPServersState;\n};\n\nexport type MCPServersState = {\n servers: {\n [id: string]: MCPServer;\n };\n tools: Tool[];\n prompts: Prompt[];\n resources: Resource[];\n};\n\nexport type MCPServer = {\n name: string;\n server_url: string;\n auth_url: string | null;\n // This state is specifically about the temporary process of getting a token (if needed).\n // Scope outside of that can't be relied upon because when the DO sleeps, there's no way\n // to communicate a change to a non-ready state.\n state: MCPConnectionState;\n instructions: string | null;\n capabilities: ServerCapabilities | null;\n};\n\n/**\n * MCP Server data stored in DO SQL for resuming MCP Server connections\n */\ntype MCPServerRow = {\n id: string;\n name: string;\n server_url: string;\n client_id: string | null;\n auth_url: string | null;\n callback_url: string;\n server_options: string;\n};\n\nconst STATE_ROW_ID = \"cf_state_row_id\";\nconst STATE_WAS_CHANGED = \"cf_state_was_changed\";\n\nconst DEFAULT_STATE = {} as unknown;\n\nconst agentContext = new AsyncLocalStorage<{\n agent: Agent<unknown, unknown>;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n}>();\n\nexport function getCurrentAgent<\n T extends Agent<unknown, unknown> = Agent<unknown, unknown>\n>(): {\n agent: T | undefined;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n} {\n const store = agentContext.getStore() as\n | {\n agent: T;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n }\n | undefined;\n if (!store) {\n return {\n agent: undefined,\n connection: undefined,\n request: undefined,\n email: undefined\n };\n }\n return store;\n}\n\n/**\n * Wraps a method to run within the agent context, ensuring getCurrentAgent() works properly\n * @param agent The agent instance\n * @param method The method to wrap\n * @returns A wrapped method that runs within the agent context\n */\n\n// biome-ignore lint/suspicious/noExplicitAny: I can't typescript\nfunction withAgentContext<T extends (...args: any[]) => any>(\n method: T\n): (this: Agent<unknown, unknown>, ...args: Parameters<T>) => ReturnType<T> {\n return function (...args: Parameters<T>): ReturnType<T> {\n const { connection, request, email, agent } = getCurrentAgent();\n\n if (agent === this) {\n // already wrapped, so we can just call the method\n return method.apply(this, args);\n }\n // not wrapped, so we need to wrap it\n return agentContext.run({ agent: this, connection, request, email }, () => {\n return method.apply(this, args);\n });\n };\n}\n\n/**\n * Base class for creating Agent implementations\n * @template Env Environment type containing bindings\n * @template State State type to store within the Agent\n */\nexport class Agent<\n Env = typeof env,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>\n> extends Server<Env, Props> {\n private _state = DEFAULT_STATE as State;\n private _disposables = new DisposableStore();\n\n private _ParentClass: typeof Agent<Env, State> =\n Object.getPrototypeOf(this).constructor;\n\n readonly mcp: MCPClientManager = new MCPClientManager(\n this._ParentClass.name,\n \"0.0.1\"\n );\n\n /**\n * Initial state for the Agent\n * Override to provide default state values\n */\n initialState: State = DEFAULT_STATE as State;\n\n /**\n * Current state of the Agent\n */\n get state(): State {\n if (this._state !== DEFAULT_STATE) {\n // state was previously set, and populated internal state\n return this._state;\n }\n // looks like this is the first time the state is being accessed\n // check if the state was set in a previous life\n const wasChanged = this.sql<{ state: \"true\" | undefined }>`\n SELECT state FROM cf_agents_state WHERE id = ${STATE_WAS_CHANGED}\n `;\n\n // ok, let's pick up the actual state from the db\n const result = this.sql<{ state: State | undefined }>`\n SELECT state FROM cf_agents_state WHERE id = ${STATE_ROW_ID}\n `;\n\n if (\n wasChanged[0]?.state === \"true\" ||\n // we do this check for people who updated their code before we shipped wasChanged\n result[0]?.state\n ) {\n const state = result[0]?.state as string; // could be null?\n\n this._state = JSON.parse(state);\n return this._state;\n }\n\n // ok, this is the first time the state is being accessed\n // and the state was not set in a previous life\n // so we need to set the initial state (if provided)\n if (this.initialState === DEFAULT_STATE) {\n // no initial state provided, so we return undefined\n return undefined as State;\n }\n // initial state provided, so we set the state,\n // update db and return the initial state\n this.setState(this.initialState);\n return this.initialState;\n }\n\n /**\n * Agent configuration options\n */\n static options = {\n /** Whether the Agent should hibernate when inactive */\n hibernate: true // default to hibernate\n };\n\n /**\n * The observability implementation to use for the Agent\n */\n observability?: Observability = genericObservability;\n\n /**\n * Execute SQL queries against the Agent's database\n * @template T Type of the returned rows\n * @param strings SQL query template strings\n * @param values Values to be inserted into the query\n * @returns Array of query results\n */\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ) {\n let query = \"\";\n try {\n // Construct the SQL query with placeholders\n query = strings.reduce(\n (acc, str, i) => acc + str + (i < values.length ? \"?\" : \"\"),\n \"\"\n );\n\n // Execute the SQL query with the provided values\n return [...this.ctx.storage.sql.exec(query, ...values)] as T[];\n } catch (e) {\n console.error(`failed to execute sql query: ${query}`, e);\n throw this.onError(e);\n }\n }\n constructor(ctx: AgentContext, env: Env) {\n super(ctx, env);\n\n if (!wrappedClasses.has(this.constructor)) {\n // Auto-wrap custom methods with agent context\n this._autoWrapCustomMethods();\n wrappedClasses.add(this.constructor);\n }\n\n // Broadcast server state after background connects (for OAuth servers)\n this._disposables.add(\n this.mcp.onConnected(async () => {\n this.broadcastMcpServers();\n })\n );\n\n // Emit MCP observability events\n this._disposables.add(\n this.mcp.onObservabilityEvent((event) => {\n this.observability?.emit(event);\n })\n );\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_state (\n id TEXT PRIMARY KEY NOT NULL,\n state TEXT\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_queues (\n id TEXT PRIMARY KEY NOT NULL,\n payload TEXT,\n callback TEXT,\n created_at INTEGER DEFAULT (unixepoch())\n )\n `;\n\n void this.ctx.blockConcurrencyWhile(async () => {\n return this._tryCatch(async () => {\n // Create alarms table if it doesn't exist\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_schedules (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n created_at INTEGER DEFAULT (unixepoch())\n )\n `;\n\n // execute any pending alarms and schedule the next alarm\n await this.alarm();\n });\n });\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_mcp_servers (\n id TEXT PRIMARY KEY NOT NULL,\n name TEXT NOT NULL,\n server_url TEXT NOT NULL,\n callback_url TEXT NOT NULL,\n client_id TEXT,\n auth_url TEXT,\n server_options TEXT\n )\n `;\n\n const _onRequest = this.onRequest.bind(this);\n this.onRequest = (request: Request) => {\n return agentContext.run(\n { agent: this, connection: undefined, request, email: undefined },\n async () => {\n // Check if this is an OAuth callback and restore state if needed\n const callbackResult =\n await this._handlePotentialOAuthCallback(request);\n if (callbackResult) {\n return callbackResult;\n }\n\n return this._tryCatch(() => _onRequest(request));\n }\n );\n };\n\n const _onMessage = this.onMessage.bind(this);\n this.onMessage = async (connection: Connection, message: WSMessage) => {\n return agentContext.run(\n { agent: this, connection, request: undefined, email: undefined },\n async () => {\n if (typeof message !== \"string\") {\n return this._tryCatch(() => _onMessage(connection, message));\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(message);\n } catch (_e) {\n // silently fail and let the onMessage handler handle it\n return this._tryCatch(() => _onMessage(connection, message));\n }\n\n if (isStateUpdateMessage(parsed)) {\n this._setStateInternal(parsed.state as State, connection);\n return;\n }\n\n if (isRPCRequest(parsed)) {\n try {\n const { id, method, args } = parsed;\n\n // Check if method exists and is callable\n const methodFn = this[method as keyof this];\n if (typeof methodFn !== \"function\") {\n throw new Error(`Method ${method} does not exist`);\n }\n\n if (!this._isCallable(method)) {\n throw new Error(`Method ${method} is not callable`);\n }\n\n const metadata = callableMetadata.get(methodFn as Function);\n\n // For streaming methods, pass a StreamingResponse object\n if (metadata?.streaming) {\n const stream = new StreamingResponse(connection, id);\n await methodFn.apply(this, [stream, ...args]);\n return;\n }\n\n // For regular methods, execute and send response\n const result = await methodFn.apply(this, args);\n\n this.observability?.emit(\n {\n displayMessage: `RPC call to ${method}`,\n id: nanoid(),\n payload: {\n method,\n streaming: metadata?.streaming\n },\n timestamp: Date.now(),\n type: \"rpc\"\n },\n this.ctx\n );\n\n const response: RPCResponse = {\n done: true,\n id,\n result,\n success: true,\n type: MessageType.RPC\n };\n connection.send(JSON.stringify(response));\n } catch (e) {\n // Send error response\n const response: RPCResponse = {\n error:\n e instanceof Error ? e.message : \"Unknown error occurred\",\n id: parsed.id,\n success: false,\n type: MessageType.RPC\n };\n connection.send(JSON.stringify(response));\n console.error(\"RPC error:\", e);\n }\n return;\n }\n\n return this._tryCatch(() => _onMessage(connection, message));\n }\n );\n };\n\n const _onConnect = this.onConnect.bind(this);\n this.onConnect = (connection: Connection, ctx: ConnectionContext) => {\n // TODO: This is a hack to ensure the state is sent after the connection is established\n // must fix this\n return agentContext.run(\n { agent: this, connection, request: ctx.request, email: undefined },\n () => {\n if (this.state) {\n connection.send(\n JSON.stringify({\n state: this.state,\n type: MessageType.CF_AGENT_STATE\n })\n );\n }\n\n connection.send(\n JSON.stringify({\n mcp: this.getMcpServers(),\n type: MessageType.CF_AGENT_MCP_SERVERS\n })\n );\n\n this.observability?.emit(\n {\n displayMessage: \"Connection established\",\n id: nanoid(),\n payload: {\n connectionId: connection.id\n },\n timestamp: Date.now(),\n type: \"connect\"\n },\n this.ctx\n );\n return this._tryCatch(() => _onConnect(connection, ctx));\n }\n );\n };\n\n const _onStart = this.onStart.bind(this);\n this.onStart = async (props?: Props) => {\n return agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n await this._tryCatch(() => {\n const servers = this.sql<MCPServerRow>`\n SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;\n `;\n\n this.broadcastMcpServers();\n\n // from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information\n if (servers && Array.isArray(servers) && servers.length > 0) {\n // Restore callback URLs for OAuth-enabled servers\n servers.forEach((server) => {\n if (server.callback_url) {\n // Register the full redirect URL including serverId to avoid ambiguous matches\n this.mcp.registerCallbackUrl(\n `${server.callback_url}/${server.id}`\n );\n }\n });\n\n servers.forEach((server) => {\n this._connectToMcpServerInternal(\n server.name,\n server.server_url,\n server.callback_url,\n server.server_options\n ? JSON.parse(server.server_options)\n : undefined,\n {\n id: server.id,\n oauthClientId: server.client_id ?? undefined\n }\n )\n .then(() => {\n // Broadcast updated MCP servers state after each server connects\n this.broadcastMcpServers();\n })\n .catch((error) => {\n console.error(\n `Error connecting to MCP server: ${server.name} (${server.server_url})`,\n error\n );\n // Still broadcast even if connection fails, so clients know about the failure\n this.broadcastMcpServers();\n });\n });\n }\n return _onStart(props);\n });\n }\n );\n };\n }\n\n private _setStateInternal(\n state: State,\n source: Connection | \"server\" = \"server\"\n ) {\n this._state = state;\n this.sql`\n INSERT OR REPLACE INTO cf_agents_state (id, state)\n VALUES (${STATE_ROW_ID}, ${JSON.stringify(state)})\n `;\n this.sql`\n INSERT OR REPLACE INTO cf_agents_state (id, state)\n VALUES (${STATE_WAS_CHANGED}, ${JSON.stringify(true)})\n `;\n this.broadcast(\n JSON.stringify({\n state: state,\n type: MessageType.CF_AGENT_STATE\n }),\n source !== \"server\" ? [source.id] : []\n );\n return this._tryCatch(() => {\n const { connection, request, email } = agentContext.getStore() || {};\n return agentContext.run(\n { agent: this, connection, request, email },\n async () => {\n this.observability?.emit(\n {\n displayMessage: \"State updated\",\n id: nanoid(),\n payload: {},\n timestamp: Date.now(),\n type: \"state:update\"\n },\n this.ctx\n );\n return this.onStateUpdate(state, source);\n }\n );\n });\n }\n\n /**\n * Update the Agent's state\n * @param state New state to set\n */\n setState(state: State) {\n this._setStateInternal(state, \"server\");\n }\n\n /**\n * Called when the Agent's state is updated\n * @param state Updated state\n * @param source Source of the state update (\"server\" or a client connection)\n */\n // biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates\n }\n\n /**\n * Called when the Agent receives an email via routeAgentEmail()\n * Override this method to handle incoming emails\n * @param email Email message to process\n */\n async _onEmail(email: AgentEmail) {\n // nb: we use this roundabout way of getting to onEmail\n // because of https://github.com/cloudflare/workerd/issues/4499\n return agentContext.run(\n { agent: this, connection: undefined, request: undefined, email: email },\n async () => {\n if (\"onEmail\" in this && typeof this.onEmail === \"function\") {\n return this._tryCatch(() =>\n (this.onEmail as (email: AgentEmail) => Promise<void>)(email)\n );\n } else {\n console.log(\"Received email from:\", email.from, \"to:\", email.to);\n console.log(\"Subject:\", email.headers.get(\"subject\"));\n console.log(\n \"Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails\"\n );\n }\n }\n );\n }\n\n /**\n * Reply to an email\n * @param email The email to reply to\n * @param options Options for the reply\n * @returns void\n */\n async replyToEmail(\n email: AgentEmail,\n options: {\n fromName: string;\n subject?: string | undefined;\n body: string;\n contentType?: string;\n headers?: Record<string, string>;\n }\n ): Promise<void> {\n return this._tryCatch(async () => {\n const agentName = camelCaseToKebabCase(this._ParentClass.name);\n const agentId = this.name;\n\n const { createMimeMessage } = await import(\"mimetext\");\n const msg = createMimeMessage();\n msg.setSender({ addr: email.to, name: options.fromName });\n msg.setRecipient(email.from);\n msg.setSubject(\n options.subject || `Re: ${email.headers.get(\"subject\")}` || \"No subject\"\n );\n msg.addMessage({\n contentType: options.contentType || \"text/plain\",\n data: options.body\n });\n\n const domain = email.from.split(\"@\")[1];\n const messageId = `<${agentId}@${domain}>`;\n msg.setHeader(\"In-Reply-To\", email.headers.get(\"Message-ID\")!);\n msg.setHeader(\"Message-ID\", messageId);\n msg.setHeader(\"X-Agent-Name\", agentName);\n msg.setHeader(\"X-Agent-ID\", agentId);\n\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n msg.setHeader(key, value);\n }\n }\n await email.reply({\n from: email.to,\n raw: msg.asRaw(),\n to: email.from\n });\n });\n }\n\n private async _tryCatch<T>(fn: () => T | Promise<T>) {\n try {\n return await fn();\n } catch (e) {\n throw this.onError(e);\n }\n }\n\n /**\n * Automatically wrap custom methods with agent context\n * This ensures getCurrentAgent() works in all custom methods without decorators\n */\n private _autoWrapCustomMethods() {\n // Collect all methods from base prototypes (Agent and Server)\n const basePrototypes = [Agent.prototype, Server.prototype];\n const baseMethods = new Set<string>();\n for (const baseProto of basePrototypes) {\n let proto = baseProto;\n while (proto && proto !== Object.prototype) {\n const methodNames = Object.getOwnPropertyNames(proto);\n for (const methodName of methodNames) {\n baseMethods.add(methodName);\n }\n proto = Object.getPrototypeOf(proto);\n }\n }\n // Get all methods from the current instance's prototype chain\n let proto = Object.getPrototypeOf(this);\n let depth = 0;\n while (proto && proto !== Object.prototype && depth < 10) {\n const methodNames = Object.getOwnPropertyNames(proto);\n for (const methodName of methodNames) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);\n\n // Skip if it's a private method, a base method, a getter, or not a function,\n if (\n baseMethods.has(methodName) ||\n methodName.startsWith(\"_\") ||\n !descriptor ||\n !!descriptor.get ||\n typeof descriptor.value !== \"function\"\n ) {\n continue;\n }\n\n // Now, methodName is confirmed to be a custom method/function\n // Wrap the custom method with context\n const wrappedFunction = withAgentContext(\n // biome-ignore lint/suspicious/noExplicitAny: I can't typescript\n this[methodName as keyof this] as (...args: any[]) => any\n // biome-ignore lint/suspicious/noExplicitAny: I can't typescript\n ) as any;\n\n // if the method is callable, copy the metadata from the original method\n if (this._isCallable(methodName)) {\n callableMetadata.set(\n wrappedFunction,\n callableMetadata.get(this[methodName as keyof this] as Function)!\n );\n }\n\n // set the wrapped function on the prototype\n this.constructor.prototype[methodName as keyof this] = wrappedFunction;\n }\n\n proto = Object.getPrototypeOf(proto);\n depth++;\n }\n }\n\n override onError(\n connection: Connection,\n error: unknown\n ): void | Promise<void>;\n override onError(error: unknown): void | Promise<void>;\n override onError(connectionOrError: Connection | unknown, error?: unknown) {\n let theError: unknown;\n if (connectionOrError && error) {\n theError = error;\n // this is a websocket connection error\n console.error(\n \"Error on websocket connection:\",\n (connectionOrError as Connection).id,\n theError\n );\n console.error(\n \"Override onError(connection, error) to handle websocket connection errors\"\n );\n } else {\n theError = connectionOrError;\n // this is a server error\n console.error(\"Error on server:\", theError);\n console.error(\"Override onError(error) to handle server errors\");\n }\n throw theError;\n }\n\n /**\n * Render content (not implemented in base class)\n */\n render() {\n throw new Error(\"Not implemented\");\n }\n\n /**\n * Queue a task to be executed in the future\n * @param payload Payload to pass to the callback\n * @param callback Name of the method to call\n * @returns The ID of the queued task\n */\n async queue<T = unknown>(callback: keyof this, payload: T): Promise<string> {\n const id = nanoid(9);\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback)\n VALUES (${id}, ${JSON.stringify(payload)}, ${callback})\n `;\n\n void this._flushQueue().catch((e) => {\n console.error(\"Error flushing queue:\", e);\n });\n\n return id;\n }\n\n private _flushingQueue = false;\n\n private async _flushQueue() {\n if (this._flushingQueue) {\n return;\n }\n this._flushingQueue = true;\n while (true) {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues\n ORDER BY created_at ASC\n `;\n\n if (!result || result.length === 0) {\n break;\n }\n\n for (const row of result || []) {\n const callback = this[row.callback as keyof Agent<Env>];\n if (!callback) {\n console.error(`callback ${row.callback} not found`);\n continue;\n }\n const { connection, request, email } = agentContext.getStore() || {};\n await agentContext.run(\n {\n agent: this,\n connection,\n request,\n email\n },\n async () => {\n // TODO: add retries and backoff\n await (\n callback as (\n payload: unknown,\n queueItem: QueueItem<string>\n ) => Promise<void>\n ).bind(this)(JSON.parse(row.payload as string), row);\n await this.dequeue(row.id);\n }\n );\n }\n }\n this._flushingQueue = false;\n }\n\n /**\n * Dequeue a task by ID\n * @param id ID of the task to dequeue\n */\n async dequeue(id: string) {\n this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;\n }\n\n /**\n * Dequeue all tasks\n */\n async dequeueAll() {\n this.sql`DELETE FROM cf_agents_queues`;\n }\n\n /**\n * Dequeue all tasks by callback\n * @param callback Name of the callback to dequeue\n */\n async dequeueAllByCallback(callback: string) {\n this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;\n }\n\n /**\n * Get a queued task by ID\n * @param id ID of the task to get\n * @returns The task or undefined if not found\n */\n async getQueue(id: string): Promise<QueueItem<string> | undefined> {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues WHERE id = ${id}\n `;\n return result\n ? { ...result[0], payload: JSON.parse(result[0].payload) }\n : undefined;\n }\n\n /**\n * Get all queues by key and value\n * @param key Key to filter by\n * @param value Value to filter by\n * @returns Array of matching QueueItem objects\n */\n async getQueues(key: string, value: string): Promise<QueueItem<string>[]> {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues\n `;\n return result.filter((row) => JSON.parse(row.payload)[key] === value);\n }\n\n /**\n * Schedule a task to be executed in the future\n * @template T Type of the payload data\n * @param when When to execute the task (Date, seconds delay, or cron expression)\n * @param callback Name of the method to call\n * @param payload Data to pass to the callback\n * @returns Schedule object representing the scheduled task\n */\n async schedule<T = string>(\n when: Date | string | number,\n callback: keyof this,\n payload?: T\n ): Promise<Schedule<T>> {\n const id = nanoid(9);\n\n const emitScheduleCreate = (schedule: Schedule<T>) =>\n this.observability?.emit(\n {\n displayMessage: `Schedule ${schedule.id} created`,\n id: nanoid(),\n payload: {\n callback: callback as string,\n id: id\n },\n timestamp: Date.now(),\n type: \"schedule:create\"\n },\n this.ctx\n );\n\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (when instanceof Date) {\n const timestamp = Math.floor(when.getTime() / 1000);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules (id, callback, payload, type, time)\n VALUES (${id}, ${callback}, ${JSON.stringify(\n payload\n )}, 'scheduled', ${timestamp})\n `;\n\n await this._scheduleNextAlarm();\n\n const schedule: Schedule<T> = {\n callback: callback,\n id,\n payload: payload as T,\n time: timestamp,\n type: \"scheduled\"\n };\n\n emitScheduleCreate(schedule);\n\n return schedule;\n }\n if (typeof when === \"number\") {\n const time = new Date(Date.now() + when * 1000);\n const timestamp = Math.floor(time.getTime() / 1000);\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules (id, callback, payload, type, delayInSeconds, time)\n VALUES (${id}, ${callback}, ${JSON.stringify(\n payload\n )}, 'delayed', ${when}, ${timestamp})\n `;\n\n await this._scheduleNextAlarm();\n\n const schedule: Schedule<T> = {\n callback: callback,\n delayInSeconds: when,\n id,\n payload: payload as T,\n time: timestamp,\n type: \"delayed\"\n };\n\n emitScheduleCreate(schedule);\n\n return schedule;\n }\n if (typeof when === \"string\") {\n const nextExecutionTime = getNextCronTime(when);\n const timestamp = Math.floor(nextExecutionTime.getTime() / 1000);\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules (id, callback, payload, type, cron, time)\n VALUES (${id}, ${callback}, ${JSON.stringify(\n payload\n )}, 'cron', ${when}, ${timestamp})\n `;\n\n await this._scheduleNextAlarm();\n\n const schedule: Schedule<T> = {\n callback: callback,\n cron: when,\n id,\n payload: payload as T,\n time: timestamp,\n type: \"cron\"\n };\n\n emitScheduleCreate(schedule);\n\n return schedule;\n }\n throw new Error(\"Invalid schedule type\");\n }\n\n /**\n * Get a scheduled task by ID\n * @template T Type of the payload data\n * @param id ID of the scheduled task\n * @returns The Schedule object or undefined if not found\n */\n async getSchedule<T = string>(id: string): Promise<Schedule<T> | undefined> {\n const result = this.sql<Schedule<string>>`\n SELECT * FROM cf_agents_schedules WHERE id = ${id}\n `;\n if (!result) {\n console.error(`schedule ${id} not found`);\n return undefined;\n }\n\n return { ...result[0], payload: JSON.parse(result[0].payload) as T };\n }\n\n /**\n * Get scheduled tasks matching the given criteria\n * @template T Type of the payload data\n * @param criteria Criteria to filter schedules\n * @returns Array of matching Schedule objects\n */\n getSchedules<T = string>(\n criteria: {\n id?: string;\n type?: \"scheduled\" | \"delayed\" | \"cron\";\n timeRange?: { start?: Date; end?: Date };\n } = {}\n ): Schedule<T>[] {\n let query = \"SELECT * FROM cf_agents_schedules WHERE 1=1\";\n const params = [];\n\n if (criteria.id) {\n query += \" AND id = ?\";\n params.push(criteria.id);\n }\n\n if (criteria.type) {\n query += \" AND type = ?\";\n params.push(criteria.type);\n }\n\n if (criteria.timeRange) {\n query += \" AND time >= ? AND time <= ?\";\n const start = criteria.timeRange.start || new Date(0);\n const end = criteria.timeRange.end || new Date(999999999999999);\n params.push(\n Math.floor(start.getTime() / 1000),\n Math.floor(end.getTime() / 1000)\n );\n }\n\n const result = this.ctx.storage.sql\n .exec(query, ...params)\n .toArray()\n .map((row) => ({\n ...row,\n payload: JSON.parse(row.payload as string) as T\n })) as Schedule<T>[];\n\n return result;\n }\n\n /**\n * Cancel a scheduled task\n * @param id ID of the task to cancel\n * @returns true if the task was cancelled, false otherwise\n */\n async cancelSchedule(id: string): Promise<boolean> {\n const schedule = await this.getSchedule(id);\n if (schedule) {\n this.observability?.emit(\n {\n displayMessage: `Schedule ${id} cancelled`,\n id: nanoid(),\n payload: {\n callback: schedule.callback,\n id: schedule.id\n },\n timestamp: Date.now(),\n type: \"schedule:cancel\"\n },\n this.ctx\n );\n }\n this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;\n\n await this._scheduleNextAlarm();\n return true;\n }\n\n private async _scheduleNextAlarm() {\n // Find the next schedule that needs to be executed\n const result = this.sql`\n SELECT time FROM cf_agents_schedules\n WHERE time > ${Math.floor(Date.now() / 1000)}\n ORDER BY time ASC\n LIMIT 1\n `;\n if (!result) return;\n\n if (result.length > 0 && \"time\" in result[0]) {\n const nextTime = (result[0].time as number) * 1000;\n await this.ctx.storage.setAlarm(nextTime);\n }\n }\n\n /**\n * Method called when an alarm fires.\n * Executes any scheduled tasks that are due.\n *\n * @remarks\n * To schedule a task, please use the `this.schedule` method instead.\n * See {@link https://developers.cloudflare.com/agents/api-reference/schedule-tasks/}\n */\n public readonly alarm = async () => {\n const now = Math.floor(Date.now() / 1000);\n\n // Get all schedules that should be executed now\n const result = this.sql<Schedule<string>>`\n SELECT * FROM cf_agents_schedules WHERE time <= ${now}\n `;\n\n if (result && Array.isArray(result)) {\n for (const row of result) {\n const callback = this[row.callback as keyof Agent<Env>];\n if (!callback) {\n console.error(`callback ${row.callback} not found`);\n continue;\n }\n await agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n try {\n this.observability?.emit(\n {\n displayMessage: `Schedule ${row.id} executed`,\n id: nanoid(),\n payload: {\n callback: row.callback,\n id: row.id\n },\n timestamp: Date.now(),\n type: \"schedule:execute\"\n },\n this.ctx\n );\n\n await (\n callback as (\n payload: unknown,\n schedule: Schedule<unknown>\n ) => Promise<void>\n ).bind(this)(JSON.parse(row.payload as string), row);\n } catch (e) {\n console.error(`error executing callback \"${row.callback}\"`, e);\n }\n }\n );\n if (row.type === \"cron\") {\n // Update next execution time for cron schedules\n const nextExecutionTime = getNextCronTime(row.cron);\n const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1000);\n\n this.sql`\n UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}\n `;\n } else {\n // Delete one-time schedules after execution\n this.sql`\n DELETE FROM cf_agents_schedules WHERE id = ${row.id}\n `;\n }\n }\n }\n\n // Schedule the next alarm\n await this._scheduleNextAlarm();\n };\n\n /**\n * Destroy the Agent, removing all state and scheduled tasks\n */\n async destroy() {\n // drop all tables\n this.sql`DROP TABLE IF EXISTS cf_agents_state`;\n this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;\n this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;\n this.sql`DROP TABLE IF EXISTS cf_agents_queues`;\n\n // delete all alarms\n await this.ctx.storage.deleteAlarm();\n await this.ctx.storage.deleteAll();\n this._disposables.dispose();\n await this.mcp.dispose?.();\n this.ctx.abort(\"destroyed\"); // enforce that the agent is evicted\n\n this.observability?.emit(\n {\n displayMessage: \"Agent destroyed\",\n id: nanoid(),\n payload: {},\n timestamp: Date.now(),\n type: \"destroy\"\n },\n this.ctx\n );\n }\n\n /**\n * Get all methods marked as callable on this Agent\n * @returns A map of method names to their metadata\n */\n private _isCallable(method: string): boolean {\n return callableMetadata.has(this[method as keyof this] as Function);\n }\n\n /**\n * Connect to a new MCP Server\n *\n * @param serverName Name of the MCP server\n * @param url MCP Server SSE URL\n * @param callbackHost Base host for the agent, used for the redirect URI. If not provided, will be derived from the current request.\n * @param agentsPrefix agents routing prefix if not using `agents`\n * @param options MCP client and transport options\n * @returns authUrl\n */\n async addMcpServer(\n serverName: string,\n url: string,\n callbackHost?: string,\n agentsPrefix = \"agents\",\n options?: {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n }\n ): Promise<{ id: string; authUrl: string | undefined }> {\n // If callbackHost is not provided, derive it from the current request\n let resolvedCallbackHost = callbackHost;\n if (!resolvedCallbackHost) {\n const { request } = getCurrentAgent();\n if (!request) {\n throw new Error(\n \"callbackHost is required when not called within a request context\"\n );\n }\n\n // Extract the origin from the request\n const requestUrl = new URL(request.url);\n resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;\n }\n\n const callbackUrl = `${resolvedCallbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;\n\n // Generate a serverId upfront\n const serverId = nanoid(8);\n\n // Persist to database BEFORE starting OAuth flow to survive DO hibernation\n this.sql`\n INSERT OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)\n VALUES (\n ${serverId},\n ${serverName},\n ${url},\n ${null},\n ${null},\n ${callbackUrl},\n ${options ? JSON.stringify(options) : null}\n );\n `;\n\n // _connectToMcpServerInternal will call mcp.connect which registers the callback URL\n const result = await this._connectToMcpServerInternal(\n serverName,\n url,\n callbackUrl,\n options,\n { id: serverId }\n );\n\n // Update database with OAuth client info if auth is required\n if (result.clientId || result.authUrl) {\n this.sql`\n UPDATE cf_agents_mcp_servers\n SET client_id = ${result.clientId ?? null}, auth_url = ${result.authUrl ?? null}\n WHERE id = ${serverId}\n `;\n }\n\n this.broadcastMcpServers();\n\n return result;\n }\n\n /**\n * Handle potential OAuth callback requests after DO hibernation.\n * Detects OAuth callbacks, restores state from database, and processes the callback.\n * Returns a Response if this was an OAuth callback, otherwise returns undefined.\n */\n private async _handlePotentialOAuthCallback(\n request: Request\n ): Promise<Response | undefined> {\n // Quick check: must be GET with callback pattern and code parameter\n if (request.method !== \"GET\") {\n return undefined;\n }\n\n const url = new URL(request.url);\n const hasCallbackPattern =\n url.pathname.includes(\"/callback/\") && url.searchParams.has(\"code\");\n\n if (!hasCallbackPattern) {\n return undefined;\n }\n\n // Extract serverId from callback URL\n const pathParts = url.pathname.split(\"/\");\n const callbackIndex = pathParts.indexOf(\"callback\");\n const serverId = callbackIndex !== -1 ? pathParts[callbackIndex + 1] : null;\n\n if (!serverId) {\n return new Response(\"Invalid callback URL: missing serverId\", {\n status: 400\n });\n }\n\n // Check if callback is already registered AND connection exists (not hibernated)\n if (\n this.mcp.isCallbackRequest(request) &&\n this.mcp.mcpConnections[serverId]\n ) {\n // State already restored, handle normally\n return this._processOAuthCallback(request);\n }\n\n // Need to restore from database after hibernation\n try {\n const server = this.sql<MCPServerRow>`\n SELECT id, name, server_url, client_id, auth_url, callback_url, server_options\n FROM cf_agents_mcp_servers\n WHERE id = ${serverId}\n `.find((s) => s.id === serverId);\n\n if (!server) {\n return new Response(\n `OAuth callback failed: Server ${serverId} not found in database`,\n { status: 404 }\n );\n }\n\n // Register callback URL (restores it after hibernation)\n if (!server.callback_url) {\n return new Response(\n `OAuth callback failed: No callback URL stored for server ${serverId}`,\n { status: 500 }\n );\n }\n\n this.mcp.registerCallbackUrl(`${server.callback_url}/${server.id}`);\n\n // Restore connection if not in memory\n if (!this.mcp.mcpConnections[serverId]) {\n let parsedOptions:\n | {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n }\n | undefined;\n try {\n parsedOptions = server.server_options\n ? JSON.parse(server.server_options)\n : undefined;\n } catch {\n return new Response(\n `OAuth callback failed: Invalid server options in database for ${serverId}`,\n { status: 500 }\n );\n }\n\n await this._connectToMcpServerInternal(\n server.name,\n server.server_url,\n server.callback_url,\n parsedOptions,\n {\n id: server.id,\n oauthClientId: server.client_id ?? undefined\n }\n );\n }\n\n // Now process the OAuth callback\n return this._processOAuthCallback(request);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`Failed to restore MCP state for ${serverId}:`, error);\n return new Response(\n `OAuth callback failed during state restoration: ${errorMsg}`,\n { status: 500 }\n );\n }\n }\n\n /**\n * Process an OAuth callback request (assumes state is already restored)\n */\n private async _processOAuthCallback(request: Request): Promise<Response> {\n const result = await this.mcp.handleCallbackRequest(request);\n this.broadcastMcpServers();\n\n if (result.authSuccess) {\n // Start background connection if auth was successful\n this.mcp\n .establishConnection(result.serverId)\n .catch((error) => {\n console.error(\"Background connection failed:\", error);\n })\n .finally(() => {\n // Broadcast after background connection resolves (success/failure)\n this.broadcastMcpServers();\n });\n }\n\n // Handle OAuth callback response using MCPClientManager configuration\n return this.handleOAuthCallbackResponse(result, request);\n }\n\n private async _connectToMcpServerInternal(\n _serverName: string,\n url: string,\n callbackUrl: string,\n // it's important that any options here are serializable because we put them into our sqlite DB for reconnection purposes\n options?: {\n client?: ConstructorParameters<typeof Client>[1];\n /**\n * We don't expose the normal set of transport options because:\n * 1) we can't serialize things like the auth provider or a fetch function into the DB for reconnection purposes\n * 2) We probably want these options to be agnostic to the transport type (SSE vs Streamable)\n *\n * This has the limitation that you can't override fetch, but I think headers should handle nearly all cases needed (i.e. non-standard bearer auth).\n */\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n },\n reconnect?: {\n id: string;\n oauthClientId?: string;\n }\n ): Promise<{\n id: string;\n authUrl: string | undefined;\n clientId: string | undefined;\n }> {\n const authProvider = new DurableObjectOAuthClientProvider(\n this.ctx.storage,\n this.name,\n callbackUrl\n );\n\n if (reconnect) {\n authProvider.serverId = reconnect.id;\n if (reconnect.oauthClientId) {\n authProvider.clientId = reconnect.oauthClientId;\n }\n }\n\n // Use the transport type specified in options, or default to \"auto\"\n const transportType: TransportType = options?.transport?.type ?? \"auto\";\n\n // allows passing through transport headers if necessary\n // this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)\n let headerTransportOpts: SSEClientTransportOptions = {};\n if (options?.transport?.headers) {\n headerTransportOpts = {\n eventSourceInit: {\n fetch: (url, init) =>\n fetch(url, {\n ...init,\n headers: options?.transport?.headers\n })\n },\n requestInit: {\n headers: options?.transport?.headers\n }\n };\n }\n\n const { id, authUrl, clientId } = await this.mcp.connect(url, {\n client: options?.client,\n reconnect,\n transport: {\n ...headerTransportOpts,\n authProvider,\n type: transportType\n }\n });\n\n return {\n authUrl,\n clientId,\n id\n };\n }\n\n async removeMcpServer(id: string) {\n this.mcp.closeConnection(id);\n this.mcp.unregisterCallbackUrl(id);\n this.sql`\n DELETE FROM cf_agents_mcp_servers WHERE id = ${id};\n `;\n this.broadcastMcpServers();\n }\n\n getMcpServers(): MCPServersState {\n const mcpState: MCPServersState = {\n prompts: this.mcp.listPrompts(),\n resources: this.mcp.listResources(),\n servers: {},\n tools: this.mcp.listTools()\n };\n\n const servers = this.sql<MCPServerRow>`\n SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;\n `;\n\n if (servers && Array.isArray(servers) && servers.length > 0) {\n for (const server of servers) {\n const serverConn = this.mcp.mcpConnections[server.id];\n mcpState.servers[server.id] = {\n auth_url: server.auth_url,\n capabilities: serverConn?.serverCapabilities ?? null,\n instructions: serverConn?.instructions ?? null,\n name: server.name,\n server_url: server.server_url,\n // mark as \"authenticating\" because the server isn't automatically connected, so it's pending authenticating\n state: serverConn?.connectionState ?? \"authenticating\"\n };\n }\n }\n\n return mcpState;\n }\n\n private broadcastMcpServers() {\n this.broadcast(\n JSON.stringify({\n mcp: this.getMcpServers(),\n type: MessageType.CF_AGENT_MCP_SERVERS\n })\n );\n }\n\n /**\n * Handle OAuth callback response using MCPClientManager configuration\n * @param result OAuth callback result\n * @param request The original request (needed for base URL)\n * @returns Response for the OAuth callback\n */\n private handleOAuthCallbackResponse(\n result: MCPClientOAuthResult,\n request: Request\n ): Response {\n const config = this.mcp.getOAuthCallbackConfig();\n\n // Use custom handler if configured\n if (config?.customHandler) {\n return config.customHandler(result);\n }\n\n // Use redirect URLs if configured\n if (config?.successRedirect && result.authSuccess) {\n return Response.redirect(config.successRedirect);\n }\n\n if (config?.errorRedirect && !result.authSuccess) {\n return Response.redirect(\n `${config.errorRedirect}?error=${encodeURIComponent(result.authError || \"Unknown error\")}`\n );\n }\n\n // Default behavior - redirect to base URL\n const baseUrl = new URL(request.url).origin;\n return Response.redirect(baseUrl);\n }\n}\n\n// A set of classes that have been wrapped with agent context\nconst wrappedClasses = new Set<typeof Agent.prototype.constructor>();\n\n/**\n * Namespace for creating Agent instances\n * @template Agentic Type of the Agent class\n */\nexport type AgentNamespace<Agentic extends Agent<unknown>> =\n DurableObjectNamespace<Agentic>;\n\n/**\n * Agent's durable context\n */\nexport type AgentContext = DurableObjectState;\n\n/**\n * Configuration options for Agent routing\n */\nexport type AgentOptions<Env> = PartyServerOptions<Env> & {\n /**\n * Whether to enable CORS for the Agent\n */\n cors?: boolean | HeadersInit | undefined;\n};\n\n/**\n * Route a request to the appropriate Agent\n * @param request Request to route\n * @param env Environment containing Agent bindings\n * @param options Routing options\n * @returns Response from the Agent or undefined if no route matched\n */\nexport async function routeAgentRequest<Env>(\n request: Request,\n env: Env,\n options?: AgentOptions<Env>\n) {\n const corsHeaders =\n options?.cors === true\n ? {\n \"Access-Control-Allow-Credentials\": \"true\",\n \"Access-Control-Allow-Methods\": \"GET, POST, HEAD, OPTIONS\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Max-Age\": \"86400\"\n }\n : options?.cors;\n\n if (request.method === \"OPTIONS\") {\n if (corsHeaders) {\n return new Response(null, {\n headers: corsHeaders\n });\n }\n console.warn(\n \"Received an OPTIONS request, but cors was not enabled. Pass `cors: true` or `cors: { ...custom cors headers }` to routeAgentRequest to enable CORS.\"\n );\n }\n\n let response = await routePartykitRequest(\n request,\n env as Record<string, unknown>,\n {\n prefix: \"agents\",\n ...(options as PartyServerOptions<Record<string, unknown>>)\n }\n );\n\n if (\n response &&\n corsHeaders &&\n request.headers.get(\"upgrade\")?.toLowerCase() !== \"websocket\" &&\n request.headers.get(\"Upgrade\")?.toLowerCase() !== \"websocket\"\n ) {\n response = new Response(response.body, {\n headers: {\n ...response.headers,\n ...corsHeaders\n }\n });\n }\n return response;\n}\n\nexport type EmailResolver<Env> = (\n email: ForwardableEmailMessage,\n env: Env\n) => Promise<{\n agentName: string;\n agentId: string;\n} | null>;\n\n/**\n * Create a resolver that uses the message-id header to determine the agent to route the email to\n * @returns A function that resolves the agent to route the email to\n */\nexport function createHeaderBasedEmailResolver<Env>(): EmailResolver<Env> {\n return async (email: ForwardableEmailMessage, _env: Env) => {\n const messageId = email.headers.get(\"message-id\");\n if (messageId) {\n const messageIdMatch = messageId.match(/<([^@]+)@([^>]+)>/);\n if (messageIdMatch) {\n const [, agentId, domain] = messageIdMatch;\n const agentName = domain.split(\".\")[0];\n return { agentName, agentId };\n }\n }\n\n const references = email.headers.get(\"references\");\n if (references) {\n const referencesMatch = references.match(\n /<([A-Za-z0-9+/]{43}=)@([^>]+)>/\n );\n if (referencesMatch) {\n const [, base64Id, domain] = referencesMatch;\n const agentId = Buffer.from(base64Id, \"base64\").toString(\"hex\");\n const agentName = domain.split(\".\")[0];\n return { agentName, agentId };\n }\n }\n\n const agentName = email.headers.get(\"x-agent-name\");\n const agentId = email.headers.get(\"x-agent-id\");\n if (agentName && agentId) {\n return { agentName, agentId };\n }\n\n return null;\n };\n}\n\n/**\n * Create a resolver that uses the email address to determine the agent to route the email to\n * @param defaultAgentName The default agent name to use if the email address does not contain a sub-address\n * @returns A function that resolves the agent to route the email to\n */\nexport function createAddressBasedEmailResolver<Env>(\n defaultAgentName: string\n): EmailResolver<Env> {\n return async (email: ForwardableEmailMessage, _env: Env) => {\n const emailMatch = email.to.match(/^([^+@]+)(?:\\+([^@]+))?@(.+)$/);\n if (!emailMatch) {\n return null;\n }\n\n const [, localPart, subAddress] = emailMatch;\n\n if (subAddress) {\n return {\n agentName: localPart,\n agentId: subAddress\n };\n }\n\n // Option 2: Use defaultAgentName namespace, localPart as agentId\n // Common for catch-all email routing to a single EmailAgent namespace\n return {\n agentName: defaultAgentName,\n agentId: localPart\n };\n };\n}\n\n/**\n * Create a resolver that uses the agentName and agentId to determine the agent to route the email to\n * @param agentName The name of the agent to route the email to\n * @param agentId The id of the agent to route the email to\n * @returns A function that resolves the agent to route the email to\n */\nexport function createCatchAllEmailResolver<Env>(\n agentName: string,\n agentId: string\n): EmailResolver<Env> {\n return async () => ({ agentName, agentId });\n}\n\nexport type EmailRoutingOptions<Env> = AgentOptions<Env> & {\n resolver: EmailResolver<Env>;\n};\n\n// Cache the agent namespace map for email routing\n// This maps both kebab-case and original names to namespaces\nconst agentMapCache = new WeakMap<\n Record<string, unknown>,\n Record<string, unknown>\n>();\n\n/**\n * Route an email to the appropriate Agent\n * @param email The email to route\n * @param env The environment containing the Agent bindings\n * @param options The options for routing the email\n * @returns A promise that resolves when the email has been routed\n */\nexport async function routeAgentEmail<Env>(\n email: ForwardableEmailMessage,\n env: Env,\n options: EmailRoutingOptions<Env>\n): Promise<void> {\n const routingInfo = await options.resolver(email, env);\n\n if (!routingInfo) {\n console.warn(\"No routing information found for email, dropping message\");\n return;\n }\n\n // Build a map that includes both original names and kebab-case versions\n if (!agentMapCache.has(env as Record<string, unknown>)) {\n const map: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(env as Record<string, unknown>)) {\n if (\n value &&\n typeof value === \"object\" &&\n \"idFromName\" in value &&\n typeof value.idFromName === \"function\"\n ) {\n // Add both the original name and kebab-case version\n map[key] = value;\n map[camelCaseToKebabCase(key)] = value;\n }\n }\n agentMapCache.set(env as Record<string, unknown>, map);\n }\n\n const agentMap = agentMapCache.get(env as Record<string, unknown>)!;\n const namespace = agentMap[routingInfo.agentName];\n\n if (!namespace) {\n // Provide helpful error message listing available agents\n const availableAgents = Object.keys(agentMap)\n .filter((key) => !key.includes(\"-\")) // Show only original names, not kebab-case duplicates\n .join(\", \");\n throw new Error(\n `Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`\n );\n }\n\n const agent = await getAgentByName(\n namespace as unknown as AgentNamespace<Agent<Env>>,\n routingInfo.agentId\n );\n\n // let's make a serialisable version of the email\n const serialisableEmail: AgentEmail = {\n getRaw: async () => {\n const reader = email.raw.getReader();\n const chunks: Uint8Array[] = [];\n\n let done = false;\n while (!done) {\n const { value, done: readerDone } = await reader.read();\n done = readerDone;\n if (value) {\n chunks.push(value);\n }\n }\n\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n\n return combined;\n },\n headers: email.headers,\n rawSize: email.rawSize,\n setReject: (reason: string) => {\n email.setReject(reason);\n },\n forward: (rcptTo: string, headers?: Headers) => {\n return email.forward(rcptTo, headers);\n },\n reply: (options: { from: string; to: string; raw: string }) => {\n return email.reply(\n new EmailMessage(options.from, options.to, options.raw)\n );\n },\n from: email.from,\n to: email.to\n };\n\n await agent._onEmail(serialisableEmail);\n}\n\nexport type AgentEmail = {\n from: string;\n to: string;\n getRaw: () => Promise<Uint8Array>;\n headers: Headers;\n rawSize: number;\n setReject: (reason: string) => void;\n forward: (rcptTo: string, headers?: Headers) => Promise<void>;\n reply: (options: { from: string; to: string; raw: string }) => Promise<void>;\n};\n\nexport type EmailSendOptions = {\n to: string;\n subject: string;\n body: string;\n contentType?: string;\n headers?: Record<string, string>;\n includeRoutingHeaders?: boolean;\n agentName?: string;\n agentId?: string;\n domain?: string;\n};\n\n/**\n * Get or create an Agent by name\n * @template Env Environment type containing bindings\n * @template T Type of the Agent class\n * @param namespace Agent namespace\n * @param name Name of the Agent instance\n * @param options Options for Agent creation\n * @returns Promise resolving to an Agent instance stub\n */\nexport async function getAgentByName<\n Env,\n T extends Agent<Env>,\n Props extends Record<string, unknown> = Record<string, unknown>\n>(\n namespace: AgentNamespace<T>,\n name: string,\n options?: {\n jurisdiction?: DurableObjectJurisdiction;\n locationHint?: DurableObjectLocationHint;\n props?: Props;\n }\n) {\n return getServerByName<Env, T>(namespace, name, options);\n}\n\n/**\n * A wrapper for streaming responses in callable methods\n */\nexport class StreamingResponse {\n private _connection: Connection;\n private _id: string;\n private _closed = false;\n\n constructor(connection: Connection, id: string) {\n this._connection = connection;\n this._id = id;\n }\n\n /**\n * Send a chunk of data to the client\n * @param chunk The data to send\n */\n send(chunk: unknown) {\n if (this._closed) {\n throw new Error(\"StreamingResponse is already closed\");\n }\n const response: RPCResponse = {\n done: false,\n id: this._id,\n result: chunk,\n success: true,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n }\n\n /**\n * End the stream and send the final chunk (if any)\n * @param finalChunk Optional final chunk of data to send\n */\n end(finalChunk?: unknown) {\n if (this._closed) {\n throw new Error(\"StreamingResponse is already closed\");\n }\n this._closed = true;\n const response: RPCResponse = {\n done: true,\n id: this._id,\n result: finalChunk,\n success: true,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n }\n}\n"],"mappings":"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"}