fastmcp 4.16.7 → 4.16.8
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.
- package/dist/edge/index.cjs +40 -24
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.d.cts +16 -0
- package/dist/edge/index.d.ts +16 -0
- package/dist/edge/index.js +34 -18
- package/dist/edge/index.js.map +1 -1
- package/package.json +1 -1
package/dist/edge/index.cjs
CHANGED
|
@@ -48,9 +48,18 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
48
48
|
*/
|
|
49
49
|
__init7() {this._standaloneStreamOpened = false}
|
|
50
50
|
__init8() {this._started = false}
|
|
51
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Bumped by every teardown. A replay runs detached from the request that
|
|
53
|
+
* started it, so its session can be gone by the time it settles: the
|
|
54
|
+
* teardown already cleared `_streamMapping`, and registering the writer
|
|
55
|
+
* afterwards would resurrect a stream nothing will ever close and re-latch
|
|
56
|
+
* `_standaloneStreamOpened`, leaving the next session on this instance
|
|
57
|
+
* writing its standalone events to the previous session's client.
|
|
58
|
+
*/
|
|
59
|
+
__init9() {this._streamGeneration = 0}
|
|
60
|
+
__init10() {this._streamMapping = /* @__PURE__ */ new Map()}
|
|
52
61
|
|
|
53
|
-
constructor(options) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);
|
|
62
|
+
constructor(options) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);
|
|
54
63
|
this.sessionIdGenerator = options.sessionIdGenerator;
|
|
55
64
|
this._enableJsonResponse = _nullishCoalesce(options.enableJsonResponse, () => ( false));
|
|
56
65
|
this._eventStore = options.eventStore;
|
|
@@ -61,15 +70,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
61
70
|
* Close the transport
|
|
62
71
|
*/
|
|
63
72
|
async close() {
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
await writer.close();
|
|
67
|
-
} catch (e) {
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
this._streamMapping.clear();
|
|
71
|
-
this._standaloneStreamOpened = false;
|
|
72
|
-
this.releasePendingRequests();
|
|
73
|
+
await this.teardownStreams();
|
|
73
74
|
this._started = false;
|
|
74
75
|
_optionalChain([this, 'access', _ => _.onclose, 'optionalCall', _2 => _2()]);
|
|
75
76
|
}
|
|
@@ -163,7 +164,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
163
164
|
async closeQuietly(writer) {
|
|
164
165
|
try {
|
|
165
166
|
await writer.close();
|
|
166
|
-
} catch (
|
|
167
|
+
} catch (e) {
|
|
167
168
|
}
|
|
168
169
|
}
|
|
169
170
|
/**
|
|
@@ -212,15 +213,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
212
213
|
return this.createErrorResponse(404, -32001, "Session not found");
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
await writer.close();
|
|
218
|
-
} catch (e3) {
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
this._streamMapping.clear();
|
|
222
|
-
this._standaloneStreamOpened = false;
|
|
223
|
-
this.releasePendingRequests();
|
|
216
|
+
await this.teardownStreams();
|
|
224
217
|
await _optionalChain([this, 'access', _8 => _8._onsessionclosed, 'optionalCall', _9 => _9(_nullishCoalesce(this.sessionId, () => ( "")))]);
|
|
225
218
|
this.sessionId = void 0;
|
|
226
219
|
return new Response(null, {
|
|
@@ -311,7 +304,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
311
304
|
let rawMessage;
|
|
312
305
|
try {
|
|
313
306
|
rawMessage = await _asyncNullishCoalesce(parsedBody, async () => ( await request.json()));
|
|
314
|
-
} catch (
|
|
307
|
+
} catch (e2) {
|
|
315
308
|
return this.createErrorResponse(400, -32700, "Parse error: Invalid JSON");
|
|
316
309
|
}
|
|
317
310
|
const isBatch = Array.isArray(rawMessage);
|
|
@@ -453,6 +446,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
453
446
|
}
|
|
454
447
|
}
|
|
455
448
|
const eventStore = this._eventStore;
|
|
449
|
+
const generation = this._streamGeneration;
|
|
456
450
|
const { readable, writable } = new TransformStream();
|
|
457
451
|
const writer = writable.getWriter();
|
|
458
452
|
this._replaysInFlight += 1;
|
|
@@ -463,6 +457,10 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
463
457
|
await this.writeSSEEventWithId(writer, eventId, message);
|
|
464
458
|
}
|
|
465
459
|
});
|
|
460
|
+
if (this._streamGeneration !== generation) {
|
|
461
|
+
await this.closeQuietly(writer);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
466
464
|
if (this._streamMapping.has(streamId)) {
|
|
467
465
|
_optionalChain([this, 'access', _24 => _24.onerror, 'optionalCall', _25 => _25(
|
|
468
466
|
new Error(
|
|
@@ -605,6 +603,24 @@ var WebStreamableHTTPServerTransport = (_class = class {
|
|
|
605
603
|
// without `trackStream` from producing an SSE event with no `id:`.
|
|
606
604
|
writer !== void 0 || this._replaysInFlight > 0;
|
|
607
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Close and forget every stream of the current session and release whatever
|
|
608
|
+
* was waiting on one. Shared by `close()` and DELETE so that a new teardown
|
|
609
|
+
* path cannot forget to bump the generation detached replays check before
|
|
610
|
+
* registering themselves.
|
|
611
|
+
*/
|
|
612
|
+
async teardownStreams() {
|
|
613
|
+
this._streamGeneration += 1;
|
|
614
|
+
for (const writer of this._streamMapping.values()) {
|
|
615
|
+
try {
|
|
616
|
+
await writer.close();
|
|
617
|
+
} catch (e3) {
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
this._streamMapping.clear();
|
|
621
|
+
this._standaloneStreamOpened = false;
|
|
622
|
+
this.releasePendingRequests();
|
|
623
|
+
}
|
|
608
624
|
trackStream(streamId, writer) {
|
|
609
625
|
if (streamId === this._standaloneSseStreamId) {
|
|
610
626
|
this._standaloneStreamOpened = true;
|
|
@@ -757,7 +773,7 @@ var EdgeFastMCP = class {
|
|
|
757
773
|
let body;
|
|
758
774
|
try {
|
|
759
775
|
body = await request.json();
|
|
760
|
-
} catch (
|
|
776
|
+
} catch (e4) {
|
|
761
777
|
return this.#errorResponse(400, -32700, "Parse error: Invalid JSON");
|
|
762
778
|
}
|
|
763
779
|
const isBatch = Array.isArray(body);
|
|
@@ -1045,7 +1061,7 @@ var EdgeFastMCP = class {
|
|
|
1045
1061
|
);
|
|
1046
1062
|
}
|
|
1047
1063
|
return { type: "object" };
|
|
1048
|
-
} catch (
|
|
1064
|
+
} catch (e5) {
|
|
1049
1065
|
return { type: "object" };
|
|
1050
1066
|
}
|
|
1051
1067
|
}
|
package/dist/edge/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","../../src/edge/index.ts","../../src/edge/WebStreamableHTTPServerTransport.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","sourcesContent":[null,"/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CancelledNotificationSchema,\n ErrorCode,\n isInitializeRequest,\n isJSONRPCError,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCMessage,\n JSONRPCMessageSchema,\n MessageExtraInfo,\n RequestId,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type EventId = string;\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;\n replayEventsAfter(\n lastEventId: EventId,\n options: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n },\n ): Promise<StreamId>;\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n}\n\nexport type StreamId = string;\n\n/**\n * Configuration options for WebStreamableHTTPServerTransport\n */\nexport interface WebStreamableHTTPServerTransportOptions {\n /**\n * If true, return JSON responses instead of SSE streams\n */\n enableJsonResponse?: boolean;\n\n /**\n * Event store for resumability support\n */\n eventStore?: EventStore;\n\n /**\n * Callback for session close events\n */\n onsessionclosed?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Callback for session initialization events\n */\n onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Function that generates a session ID for the transport.\n * Return undefined to disable session management (stateless mode).\n */\n sessionIdGenerator: (() => string) | undefined;\n}\n\n/**\n * Collects the responses to every request that arrived on a single POST, so\n * that JSON mode can answer once all of them are in.\n */\ninterface PendingJsonResponse {\n expectedIds: RequestId[];\n resolve: (responses: JSONRPCMessage[]) => void;\n responses: Map<RequestId, JSONRPCMessage>;\n}\n\nconst MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB\n\n/**\n * Web-standard Server transport for Streamable HTTP.\n * Uses web APIs (Request, Response, TransformStream) for edge runtime compatibility.\n */\nexport class WebStreamableHTTPServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n sessionId?: string;\n private _enableJsonResponse = false;\n private _encoder = new TextEncoder();\n private _eventStore?: EventStore;\n private _jsonResponseCollectors = new Map<StreamId, PendingJsonResponse>();\n private _onsessionclosed?: (sessionId: string) => Promise<void> | void;\n private _onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n /**\n * Replays whose stream id is still being resolved. `replayEventsAfter` only\n * reveals which stream it was replaying once it settles, so a standalone\n * send during that window has nothing to test against; persist rather than\n * drop, since over-storing for the length of a replay beats losing an event.\n */\n private _replaysInFlight = 0;\n\n private _requestToStreamMapping = new Map<RequestId, StreamId>();\n\n private _standaloneSseStreamId = \"_GET_stream\";\n /**\n * Whether a client has held the standalone GET stream during this session.\n * Latched rather than read from `_streamMapping`, so persistence survives\n * the disconnect window the store exists to cover while still telling a\n * dropped stream apart from one that was never opened. Reset with the rest\n * of the per-session state, since the next session starts with no stream.\n */\n private _standaloneStreamOpened = false;\n private _started = false;\n private _streamMapping = new Map<\n StreamId,\n WritableStreamDefaultWriter<Uint8Array>\n >();\n private sessionIdGenerator: (() => string) | undefined;\n\n constructor(options: WebStreamableHTTPServerTransportOptions) {\n this.sessionIdGenerator = options.sessionIdGenerator;\n this._enableJsonResponse = options.enableJsonResponse ?? false;\n this._eventStore = options.eventStore;\n this._onsessioninitialized = options.onsessioninitialized;\n this._onsessionclosed = options.onsessionclosed;\n }\n\n /**\n * Close the transport\n */\n async close(): Promise<void> {\n for (const writer of this._streamMapping.values()) {\n try {\n await writer.close();\n } catch {\n // Ignore close errors\n }\n }\n this._streamMapping.clear();\n this._standaloneStreamOpened = false;\n this.releasePendingRequests();\n this._started = false;\n this.onclose?.();\n }\n\n /**\n * Handles an incoming web Request and returns a Response\n */\n async handleRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n const method = request.method;\n\n if (method === \"POST\") {\n return this.handlePostRequest(request, parsedBody);\n } else if (method === \"GET\") {\n return this.handleGetRequest(request);\n } else if (method === \"DELETE\") {\n return this.handleDeleteRequest(request);\n } else {\n return this.handleUnsupportedRequest();\n }\n }\n\n /**\n * Send a message to connected clients\n */\n async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId },\n ): Promise<void> {\n let requestId = options?.relatedRequestId;\n const isResponse = isJSONRPCResponse(message) || isJSONRPCError(message);\n if (isResponse) {\n // Responses are routed by the id of the request they answer\n requestId = message.id;\n }\n\n const streamId =\n requestId === undefined\n ? this._standaloneSseStreamId\n : this._requestToStreamMapping.get(requestId);\n\n if (streamId) {\n // JSON mode has no stream to write to: collect the responses instead and\n // let handlePostRequest answer once every request on this POST is done.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n if (isResponse && requestId !== undefined) {\n collector.responses.set(requestId, message);\n this.settleJsonResponse(streamId, collector);\n }\n return;\n }\n\n const writer = this._streamMapping.get(streamId);\n // With an event store the message must be persisted even if the client\n // has already disconnected, so a reconnect with Last-Event-Id can replay\n // it. The live write to the SSE stream is best-effort on top of that.\n const store = this.shouldPersist(streamId, writer)\n ? this._eventStore\n : undefined;\n\n if (writer || store) {\n try {\n let eventId: string | undefined;\n if (store) {\n eventId = await store.storeEvent(streamId, message);\n }\n if (writer) {\n if (eventId === undefined) {\n await this.writeSSEEvent(writer, message);\n } else {\n await this.writeSSEEventWithId(writer, eventId, message);\n }\n }\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n\n // Close the POST stream once all of its requests are answered. Drained\n // whether or not the store and the socket cooperated: with an event\n // store configured `trackStream` deliberately leaves routing entries\n // alone on disconnect, so this is the only thing that reclaims them,\n // and giving up on a failed write strands the entry until the session\n // ends.\n if (requestId !== undefined && isResponse) {\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (!streamInUse) {\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n }\n }\n }\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n /**\n * Close a writer we are giving up on. The stream is already being discarded,\n * and closing one the client cancelled — or one a failed write already\n * errored — rejects; on the detached replay path that would surface as an\n * unhandled rejection rather than anything actionable.\n */\n private async closeQuietly(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): Promise<void> {\n try {\n await writer.close();\n } catch {\n // Already closed, errored, or cancelled by the client.\n }\n }\n\n /**\n * Create an error response\n */\n private createErrorResponse(\n status: number,\n code: number,\n message: string,\n ): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status,\n },\n );\n }\n\n /**\n * Get common response headers\n */\n private getResponseHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n return headers;\n }\n\n /**\n * Handles DELETE requests to terminate sessions\n */\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionId = request.headers.get(\"mcp-session-id\");\n\n if (this.sessionIdGenerator) {\n if (!sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n // Close all streams\n for (const writer of this._streamMapping.values()) {\n try {\n await writer.close();\n } catch {\n // Ignore close errors\n }\n }\n this._streamMapping.clear();\n // Per-session, like the session id below: this instance stays usable, and\n // the next session starts having opened no standalone stream of its own.\n this._standaloneStreamOpened = false;\n this.releasePendingRequests();\n\n await this._onsessionclosed?.(this.sessionId ?? \"\");\n this.sessionId = undefined;\n\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 204,\n });\n }\n\n /**\n * Handles GET requests for SSE stream\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 this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // Validate session\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (this.sessionIdGenerator && !sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionIdGenerator && this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n\n // Check for existing standalone stream\n if (this._streamMapping.has(this._standaloneSseStreamId)) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this session\",\n );\n }\n\n // Handle resumability\n if (this._eventStore) {\n const lastEventId = request.headers.get(\"last-event-id\");\n if (lastEventId) {\n return this.handleReplayEvents(lastEventId);\n }\n }\n\n // Create SSE stream\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n this.trackStream(this._standaloneSseStreamId, writer);\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles POST requests containing JSON-RPC messages\n */\n private async handlePostRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n // Validate Accept header\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n // Validate Content-Type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.createErrorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Validate Content-Length\n const contentLength = parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10,\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE) {\n return this.createErrorResponse(\n 413,\n -32000,\n `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE} bytes`,\n );\n }\n\n // Parse body\n let rawMessage: unknown;\n try {\n rawMessage = parsedBody ?? (await request.json());\n } catch {\n return this.createErrorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle batch or single message. The original shape decides the response\n // envelope: a batch always answers with an array, even when only one\n // response survives.\n const isBatch = Array.isArray(rawMessage);\n const arrayMessage: unknown[] = Array.isArray(rawMessage)\n ? rawMessage\n : [rawMessage];\n\n if (isBatch && arrayMessage.length === 0) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n // Validate messages\n const messages: JSONRPCMessage[] = [];\n for (const msg of arrayMessage) {\n const result = JSONRPCMessageSchema.safeParse(msg);\n if (!result.success) {\n return this.createErrorResponse(\n 400,\n -32700,\n \"Parse error: Invalid JSON-RPC message\",\n );\n }\n messages.push(result.data);\n }\n\n // Handle session ID\n const requestSessionId = request.headers.get(\"mcp-session-id\");\n const hasInitRequest = messages.some((msg) => isInitializeRequest(msg));\n\n // Validate session requirements\n if (hasInitRequest && requestSessionId) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Initialization requests must not include a sessionId\",\n );\n }\n\n if (hasInitRequest && messages.length > 1) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Only one initialization request is allowed\",\n );\n }\n\n if (!hasInitRequest && !requestSessionId && this.sessionIdGenerator) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n // Generate or validate session ID\n if (hasInitRequest && this.sessionIdGenerator) {\n this.sessionId = this.sessionIdGenerator();\n await this._onsessioninitialized?.(this.sessionId);\n } else if (requestSessionId) {\n if (this.sessionIdGenerator && this.sessionId !== requestSessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n const requestIds = messages\n .filter((msg) => isJSONRPCRequest(msg))\n .map((msg) => msg.id);\n const useJsonResponse =\n this._enableJsonResponse &&\n Boolean(acceptHeader?.includes(\"application/json\"));\n\n // Register the response sink before dispatching: the SDK produces\n // responses asynchronously and send() routes them back by request id.\n let jsonResponses: Promise<JSONRPCMessage[]> | undefined;\n let sseReadable: ReadableStream<Uint8Array> | undefined;\n if (requestIds.length > 0) {\n // Must be unique: a wall-clock id collides between two POSTs issued in\n // the same millisecond, which would cross-deliver their responses.\n const streamId = crypto.randomUUID();\n for (const id of requestIds) {\n this._requestToStreamMapping.set(id, streamId);\n }\n\n if (useJsonResponse) {\n jsonResponses = new Promise((resolve) => {\n this._jsonResponseCollectors.set(streamId, {\n expectedIds: requestIds,\n resolve,\n responses: new Map(),\n });\n });\n } else {\n const { readable, writable } = new TransformStream<Uint8Array>();\n this.trackStream(streamId, writable.getWriter());\n sseReadable = readable;\n }\n }\n\n // A cancelled request is never answered — the SDK suppresses the response\n // of a request whose abort signal fired — so send() never runs for its id\n // and nothing else would ever drop its routing entry. Release it here.\n for (const message of messages) {\n const cancelled = CancelledNotificationSchema.safeParse(message);\n if (cancelled.success) {\n await this.releaseCancelledRequest(cancelled.data.params.requestId);\n }\n }\n\n // Process messages through the transport\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: undefined });\n }\n\n // Nothing to answer: the batch was only notifications and/or responses\n if (requestIds.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n // Return JSON response if enabled and client accepts it\n if (jsonResponses) {\n // Wait for the handlers to actually answer, however long they take\n const responses = await jsonResponses;\n\n // Every request this POST carried was cancelled, so there is nothing to\n // put in the body — and an empty body is not a JSON-RPC message. Answer\n // the way a POST that carried no requests at all does.\n if (responses.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n // Return SSE stream\n return new Response(sseReadable ?? null, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Replay events for resumability\n */\n private async handleReplayEvents(lastEventId: string): Promise<Response> {\n if (!this._eventStore) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Resumability not supported\",\n );\n }\n\n // `getStreamIdForEventId` is optional, so this only asks stores that can\n // answer which stream the reconnect would land on before any work is done.\n // Unlike the SDK's Node transport, an event id the store does not\n // recognise is not rejected outright here: that store may still resolve it\n // in `replayEventsAfter`, and answering 400 for it would turn reconnects\n // that work today into errors.\n if (this._eventStore.getStreamIdForEventId) {\n const existingStreamId =\n await this._eventStore.getStreamIdForEventId(lastEventId);\n if (\n existingStreamId !== undefined &&\n this._streamMapping.has(existingStreamId)\n ) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this replay\",\n );\n }\n }\n\n const eventStore = this._eventStore;\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n // The replay deliberately runs detached. Nothing reads `readable` until\n // this Response is handed back to the runtime, and a TransformStream's\n // readable side has a high-water mark of 0, so the very first\n // `writer.write()` a replay performs parks forever waiting for a reader\n // that cannot exist yet — awaiting the replay here would hang every\n // reconnect that actually has events to catch up on. The SDK's Node\n // transport has the same ordering for the same reason: it flushes the 200\n // headers before replaying. The cost is that once the headers are out,\n // nothing below can be reported as a status code.\n this._replaysInFlight += 1;\n void (async () => {\n try {\n const streamId = await eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n\n // The pre-check above runs against the id the store predicts, and only\n // for stores implementing the optional lookup. This one runs against\n // the id the writer would actually be registered under, with no await\n // between it and the `set` inside `trackStream` — so it also covers\n // stores without `getStreamIdForEventId` (the common case), a store\n // whose two methods disagree, and a second reconnect that raced past\n // the pre-check while this one was replaying. Too late for a 409, but\n // ending this stream still beats orphaning the live one by overwriting\n // its writer: the client has its replayed events and can reconnect.\n if (this._streamMapping.has(streamId)) {\n this.onerror?.(\n new Error(\n `Conflict: SSE stream already exists for replayed stream ${streamId}`,\n ),\n );\n await this.closeQuietly(writer);\n return;\n }\n\n this.trackStream(streamId, writer);\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n await this.closeQuietly(writer);\n } finally {\n this._replaysInFlight -= 1;\n }\n })().catch(() => {\n // Only reachable if `onerror` itself threw, so there is nowhere left to\n // report it. Swallow rather than let a detached task take the process\n // down as an unhandled rejection.\n });\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles unsupported HTTP methods\n */\n private handleUnsupportedRequest(): Response {\n return this.createErrorResponse(405, -32000, \"Method not allowed\");\n }\n\n /**\n * Settle the routing state of a request the client cancelled, which will\n * therefore never produce a response: the same drain `send()` performs once\n * a response has been written, minus the response. Idempotent, so it is a\n * no-op if the response won the race against the cancellation.\n */\n private async releaseCancelledRequest(requestId: RequestId): Promise<void> {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (streamId === undefined) {\n return;\n }\n\n // A JSON-mode POST has no stream to close: it is parked on its collector,\n // which would keep waiting for a response that is never coming. Stop\n // expecting that one and answer with whatever the POST's other requests\n // produce.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n collector.expectedIds = collector.expectedIds.filter(\n (id) => id !== requestId,\n );\n this._requestToStreamMapping.delete(requestId);\n this.settleJsonResponse(streamId, collector);\n return;\n }\n\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (streamInUse) {\n return;\n }\n\n // Nothing will ever be written to this stream again; close it rather than\n // leaving the client reading a stream that can only hang.\n const writer = this._streamMapping.get(streamId);\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Drop the routing state left over once every stream is gone, answering any\n * POST still waiting on a JSON response with whatever arrived rather than\n * leaving the request hanging.\n */\n private releasePendingRequests(): void {\n for (const collector of this._jsonResponseCollectors.values()) {\n collector.resolve(\n collector.expectedIds.map(\n (id) =>\n collector.responses.get(id) ??\n // Nobody can answer this one now. Dropping it silently would leave\n // the POST with an empty body for a single request and an empty\n // array for a batch, neither of which a client can read as a\n // result.\n ({\n error: {\n code: ErrorCode.ConnectionClosed,\n message:\n \"Connection closed: the session ended before this request was answered\",\n },\n id,\n jsonrpc: \"2.0\",\n } satisfies JSONRPCMessage),\n ),\n );\n }\n this._jsonResponseCollectors.clear();\n this._requestToStreamMapping.clear();\n }\n\n /**\n * Answer a JSON-mode POST once every request it carried has a response\n */\n private settleJsonResponse(\n streamId: StreamId,\n collector: PendingJsonResponse,\n ): void {\n const responses: JSONRPCMessage[] = [];\n for (const id of collector.expectedIds) {\n const response = collector.responses.get(id);\n if (!response) {\n // Still waiting on at least one of this POST's requests\n return;\n }\n responses.push(response);\n }\n\n this._jsonResponseCollectors.delete(streamId);\n for (const id of collector.expectedIds) {\n this._requestToStreamMapping.delete(id);\n }\n collector.resolve(responses);\n }\n\n /**\n * Whether an event addressed to `streamId` should go to the event store.\n *\n * Everything but the standalone stream is persisted whenever a store is\n * configured: those ids exist only because their stream did. The standalone\n * id is a constant, so it resolves whether or not a client ever opened that\n * stream, and storing before the first GET writes events nothing can reach —\n * replay is keyed off Last-Event-Id, and a client that never held the stream\n * was never handed an id to resume from.\n */\n private shouldPersist(\n streamId: StreamId,\n writer: undefined | WritableStreamDefaultWriter<Uint8Array>,\n ): boolean {\n if (this._eventStore === undefined) {\n return false;\n }\n\n if (streamId !== this._standaloneSseStreamId) {\n return true;\n }\n\n return (\n this._standaloneStreamOpened ||\n // A live writer means the stream is open now, which is stronger evidence\n // than the latch. Belt and braces: it keeps a writer reaching this point\n // without `trackStream` from producing an SSE event with no `id:`.\n writer !== undefined ||\n this._replaysInFlight > 0\n );\n }\n\n private trackStream(\n streamId: StreamId,\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): void {\n // Latched here rather than at each call site so a new way of opening the\n // standalone stream cannot forget to record it.\n if (streamId === this._standaloneSseStreamId) {\n this._standaloneStreamOpened = true;\n }\n this._streamMapping.set(streamId, writer);\n const removeStreamIfCurrent = () => {\n if (this._streamMapping.get(streamId) !== writer) {\n return;\n }\n this._streamMapping.delete(streamId);\n // With an event store, a response can still arrive after the client gave\n // up, and it must be persisted for replay. Keep the routing entry so\n // send() can resolve the stream id and store under it; send() drops the\n // entry once the response has been stored.\n if (this._eventStore) {\n return;\n }\n // No event store: nothing will be persisted for this stream, so drop the\n // routing entries now rather than leaking them. No-op for the standalone\n // GET stream, which is never a request target.\n for (const [requestId, mappedStreamId] of this._requestToStreamMapping) {\n if (mappedStreamId === streamId) {\n this._requestToStreamMapping.delete(requestId);\n }\n }\n };\n void writer.closed.then(removeStreamIfCurrent, removeStreamIfCurrent);\n }\n\n /**\n * Write an SSE event to the stream\n */\n private async writeSSEEvent(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `data: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n\n /**\n * Write an SSE event with ID to the stream\n */\n private async writeSSEEventWithId(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n eventId: string,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `id: ${eventId}\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","../../src/edge/index.ts","../../src/edge/WebStreamableHTTPServerTransport.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","sourcesContent":[null,"/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CancelledNotificationSchema,\n ErrorCode,\n isInitializeRequest,\n isJSONRPCError,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCMessage,\n JSONRPCMessageSchema,\n MessageExtraInfo,\n RequestId,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type EventId = string;\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;\n replayEventsAfter(\n lastEventId: EventId,\n options: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n },\n ): Promise<StreamId>;\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n}\n\nexport type StreamId = string;\n\n/**\n * Configuration options for WebStreamableHTTPServerTransport\n */\nexport interface WebStreamableHTTPServerTransportOptions {\n /**\n * If true, return JSON responses instead of SSE streams\n */\n enableJsonResponse?: boolean;\n\n /**\n * Event store for resumability support\n */\n eventStore?: EventStore;\n\n /**\n * Callback for session close events\n */\n onsessionclosed?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Callback for session initialization events\n */\n onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Function that generates a session ID for the transport.\n * Return undefined to disable session management (stateless mode).\n */\n sessionIdGenerator: (() => string) | undefined;\n}\n\n/**\n * Collects the responses to every request that arrived on a single POST, so\n * that JSON mode can answer once all of them are in.\n */\ninterface PendingJsonResponse {\n expectedIds: RequestId[];\n resolve: (responses: JSONRPCMessage[]) => void;\n responses: Map<RequestId, JSONRPCMessage>;\n}\n\nconst MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB\n\n/**\n * Web-standard Server transport for Streamable HTTP.\n * Uses web APIs (Request, Response, TransformStream) for edge runtime compatibility.\n */\nexport class WebStreamableHTTPServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n sessionId?: string;\n private _enableJsonResponse = false;\n private _encoder = new TextEncoder();\n private _eventStore?: EventStore;\n private _jsonResponseCollectors = new Map<StreamId, PendingJsonResponse>();\n private _onsessionclosed?: (sessionId: string) => Promise<void> | void;\n private _onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n /**\n * Replays whose stream id is still being resolved. `replayEventsAfter` only\n * reveals which stream it was replaying once it settles, so a standalone\n * send during that window has nothing to test against; persist rather than\n * drop, since over-storing for the length of a replay beats losing an event.\n */\n private _replaysInFlight = 0;\n\n private _requestToStreamMapping = new Map<RequestId, StreamId>();\n\n private _standaloneSseStreamId = \"_GET_stream\";\n /**\n * Whether a client has held the standalone GET stream during this session.\n * Latched rather than read from `_streamMapping`, so persistence survives\n * the disconnect window the store exists to cover while still telling a\n * dropped stream apart from one that was never opened. Reset with the rest\n * of the per-session state, since the next session starts with no stream.\n */\n private _standaloneStreamOpened = false;\n private _started = false;\n /**\n * Bumped by every teardown. A replay runs detached from the request that\n * started it, so its session can be gone by the time it settles: the\n * teardown already cleared `_streamMapping`, and registering the writer\n * afterwards would resurrect a stream nothing will ever close and re-latch\n * `_standaloneStreamOpened`, leaving the next session on this instance\n * writing its standalone events to the previous session's client.\n */\n private _streamGeneration = 0;\n\n private _streamMapping = new Map<\n StreamId,\n WritableStreamDefaultWriter<Uint8Array>\n >();\n private sessionIdGenerator: (() => string) | undefined;\n\n constructor(options: WebStreamableHTTPServerTransportOptions) {\n this.sessionIdGenerator = options.sessionIdGenerator;\n this._enableJsonResponse = options.enableJsonResponse ?? false;\n this._eventStore = options.eventStore;\n this._onsessioninitialized = options.onsessioninitialized;\n this._onsessionclosed = options.onsessionclosed;\n }\n\n /**\n * Close the transport\n */\n async close(): Promise<void> {\n await this.teardownStreams();\n this._started = false;\n this.onclose?.();\n }\n\n /**\n * Handles an incoming web Request and returns a Response\n */\n async handleRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n const method = request.method;\n\n if (method === \"POST\") {\n return this.handlePostRequest(request, parsedBody);\n } else if (method === \"GET\") {\n return this.handleGetRequest(request);\n } else if (method === \"DELETE\") {\n return this.handleDeleteRequest(request);\n } else {\n return this.handleUnsupportedRequest();\n }\n }\n\n /**\n * Send a message to connected clients\n */\n async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId },\n ): Promise<void> {\n let requestId = options?.relatedRequestId;\n const isResponse = isJSONRPCResponse(message) || isJSONRPCError(message);\n if (isResponse) {\n // Responses are routed by the id of the request they answer\n requestId = message.id;\n }\n\n const streamId =\n requestId === undefined\n ? this._standaloneSseStreamId\n : this._requestToStreamMapping.get(requestId);\n\n if (streamId) {\n // JSON mode has no stream to write to: collect the responses instead and\n // let handlePostRequest answer once every request on this POST is done.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n if (isResponse && requestId !== undefined) {\n collector.responses.set(requestId, message);\n this.settleJsonResponse(streamId, collector);\n }\n return;\n }\n\n const writer = this._streamMapping.get(streamId);\n // With an event store the message must be persisted even if the client\n // has already disconnected, so a reconnect with Last-Event-Id can replay\n // it. The live write to the SSE stream is best-effort on top of that.\n const store = this.shouldPersist(streamId, writer)\n ? this._eventStore\n : undefined;\n\n if (writer || store) {\n try {\n let eventId: string | undefined;\n if (store) {\n eventId = await store.storeEvent(streamId, message);\n }\n if (writer) {\n if (eventId === undefined) {\n await this.writeSSEEvent(writer, message);\n } else {\n await this.writeSSEEventWithId(writer, eventId, message);\n }\n }\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n\n // Close the POST stream once all of its requests are answered. Drained\n // whether or not the store and the socket cooperated: with an event\n // store configured `trackStream` deliberately leaves routing entries\n // alone on disconnect, so this is the only thing that reclaims them,\n // and giving up on a failed write strands the entry until the session\n // ends.\n if (requestId !== undefined && isResponse) {\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (!streamInUse) {\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n }\n }\n }\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n /**\n * Close a writer we are giving up on. The stream is already being discarded,\n * and closing one the client cancelled — or one a failed write already\n * errored — rejects; on the detached replay path that would surface as an\n * unhandled rejection rather than anything actionable.\n */\n private async closeQuietly(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): Promise<void> {\n try {\n await writer.close();\n } catch {\n // Already closed, errored, or cancelled by the client.\n }\n }\n\n /**\n * Create an error response\n */\n private createErrorResponse(\n status: number,\n code: number,\n message: string,\n ): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status,\n },\n );\n }\n\n /**\n * Get common response headers\n */\n private getResponseHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n return headers;\n }\n\n /**\n * Handles DELETE requests to terminate sessions\n */\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionId = request.headers.get(\"mcp-session-id\");\n\n if (this.sessionIdGenerator) {\n if (!sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n await this.teardownStreams();\n\n await this._onsessionclosed?.(this.sessionId ?? \"\");\n this.sessionId = undefined;\n\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 204,\n });\n }\n\n /**\n * Handles GET requests for SSE stream\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 this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // Validate session\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (this.sessionIdGenerator && !sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionIdGenerator && this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n\n // Check for existing standalone stream\n if (this._streamMapping.has(this._standaloneSseStreamId)) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this session\",\n );\n }\n\n // Handle resumability\n if (this._eventStore) {\n const lastEventId = request.headers.get(\"last-event-id\");\n if (lastEventId) {\n return this.handleReplayEvents(lastEventId);\n }\n }\n\n // Create SSE stream\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n this.trackStream(this._standaloneSseStreamId, writer);\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles POST requests containing JSON-RPC messages\n */\n private async handlePostRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n // Validate Accept header\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n // Validate Content-Type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.createErrorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Validate Content-Length\n const contentLength = parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10,\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE) {\n return this.createErrorResponse(\n 413,\n -32000,\n `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE} bytes`,\n );\n }\n\n // Parse body\n let rawMessage: unknown;\n try {\n rawMessage = parsedBody ?? (await request.json());\n } catch {\n return this.createErrorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle batch or single message. The original shape decides the response\n // envelope: a batch always answers with an array, even when only one\n // response survives.\n const isBatch = Array.isArray(rawMessage);\n const arrayMessage: unknown[] = Array.isArray(rawMessage)\n ? rawMessage\n : [rawMessage];\n\n if (isBatch && arrayMessage.length === 0) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n // Validate messages\n const messages: JSONRPCMessage[] = [];\n for (const msg of arrayMessage) {\n const result = JSONRPCMessageSchema.safeParse(msg);\n if (!result.success) {\n return this.createErrorResponse(\n 400,\n -32700,\n \"Parse error: Invalid JSON-RPC message\",\n );\n }\n messages.push(result.data);\n }\n\n // Handle session ID\n const requestSessionId = request.headers.get(\"mcp-session-id\");\n const hasInitRequest = messages.some((msg) => isInitializeRequest(msg));\n\n // Validate session requirements\n if (hasInitRequest && requestSessionId) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Initialization requests must not include a sessionId\",\n );\n }\n\n if (hasInitRequest && messages.length > 1) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Only one initialization request is allowed\",\n );\n }\n\n if (!hasInitRequest && !requestSessionId && this.sessionIdGenerator) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n // Generate or validate session ID\n if (hasInitRequest && this.sessionIdGenerator) {\n this.sessionId = this.sessionIdGenerator();\n await this._onsessioninitialized?.(this.sessionId);\n } else if (requestSessionId) {\n if (this.sessionIdGenerator && this.sessionId !== requestSessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n const requestIds = messages\n .filter((msg) => isJSONRPCRequest(msg))\n .map((msg) => msg.id);\n const useJsonResponse =\n this._enableJsonResponse &&\n Boolean(acceptHeader?.includes(\"application/json\"));\n\n // Register the response sink before dispatching: the SDK produces\n // responses asynchronously and send() routes them back by request id.\n let jsonResponses: Promise<JSONRPCMessage[]> | undefined;\n let sseReadable: ReadableStream<Uint8Array> | undefined;\n if (requestIds.length > 0) {\n // Must be unique: a wall-clock id collides between two POSTs issued in\n // the same millisecond, which would cross-deliver their responses.\n const streamId = crypto.randomUUID();\n for (const id of requestIds) {\n this._requestToStreamMapping.set(id, streamId);\n }\n\n if (useJsonResponse) {\n jsonResponses = new Promise((resolve) => {\n this._jsonResponseCollectors.set(streamId, {\n expectedIds: requestIds,\n resolve,\n responses: new Map(),\n });\n });\n } else {\n const { readable, writable } = new TransformStream<Uint8Array>();\n this.trackStream(streamId, writable.getWriter());\n sseReadable = readable;\n }\n }\n\n // A cancelled request is never answered — the SDK suppresses the response\n // of a request whose abort signal fired — so send() never runs for its id\n // and nothing else would ever drop its routing entry. Release it here.\n for (const message of messages) {\n const cancelled = CancelledNotificationSchema.safeParse(message);\n if (cancelled.success) {\n await this.releaseCancelledRequest(cancelled.data.params.requestId);\n }\n }\n\n // Process messages through the transport\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: undefined });\n }\n\n // Nothing to answer: the batch was only notifications and/or responses\n if (requestIds.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n // Return JSON response if enabled and client accepts it\n if (jsonResponses) {\n // Wait for the handlers to actually answer, however long they take\n const responses = await jsonResponses;\n\n // Every request this POST carried was cancelled, so there is nothing to\n // put in the body — and an empty body is not a JSON-RPC message. Answer\n // the way a POST that carried no requests at all does.\n if (responses.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n // Return SSE stream\n return new Response(sseReadable ?? null, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Replay events for resumability\n */\n private async handleReplayEvents(lastEventId: string): Promise<Response> {\n if (!this._eventStore) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Resumability not supported\",\n );\n }\n\n // `getStreamIdForEventId` is optional, so this only asks stores that can\n // answer which stream the reconnect would land on before any work is done.\n // Unlike the SDK's Node transport, an event id the store does not\n // recognise is not rejected outright here: that store may still resolve it\n // in `replayEventsAfter`, and answering 400 for it would turn reconnects\n // that work today into errors.\n if (this._eventStore.getStreamIdForEventId) {\n const existingStreamId =\n await this._eventStore.getStreamIdForEventId(lastEventId);\n if (\n existingStreamId !== undefined &&\n this._streamMapping.has(existingStreamId)\n ) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this replay\",\n );\n }\n }\n\n const eventStore = this._eventStore;\n const generation = this._streamGeneration;\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n // The replay deliberately runs detached. Nothing reads `readable` until\n // this Response is handed back to the runtime, and a TransformStream's\n // readable side has a high-water mark of 0, so the very first\n // `writer.write()` a replay performs parks forever waiting for a reader\n // that cannot exist yet — awaiting the replay here would hang every\n // reconnect that actually has events to catch up on. The SDK's Node\n // transport has the same ordering for the same reason: it flushes the 200\n // headers before replaying. The cost is that once the headers are out,\n // nothing below can be reported as a status code.\n this._replaysInFlight += 1;\n void (async () => {\n try {\n const streamId = await eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n\n // `close()` or a DELETE may have ended the session while the replay\n // was running. That teardown could not close this writer — it was not\n // in `_streamMapping` yet — so end it here rather than registering it\n // into a session that no longer exists.\n if (this._streamGeneration !== generation) {\n await this.closeQuietly(writer);\n return;\n }\n\n // The pre-check above runs against the id the store predicts, and only\n // for stores implementing the optional lookup. This one runs against\n // the id the writer would actually be registered under, with no await\n // between it and the `set` inside `trackStream` — so it also covers\n // stores without `getStreamIdForEventId` (the common case), a store\n // whose two methods disagree, and a second reconnect that raced past\n // the pre-check while this one was replaying. Too late for a 409, but\n // ending this stream still beats orphaning the live one by overwriting\n // its writer: the client has its replayed events and can reconnect.\n if (this._streamMapping.has(streamId)) {\n this.onerror?.(\n new Error(\n `Conflict: SSE stream already exists for replayed stream ${streamId}`,\n ),\n );\n await this.closeQuietly(writer);\n return;\n }\n\n this.trackStream(streamId, writer);\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n await this.closeQuietly(writer);\n } finally {\n this._replaysInFlight -= 1;\n }\n })().catch(() => {\n // Only reachable if `onerror` itself threw, so there is nowhere left to\n // report it. Swallow rather than let a detached task take the process\n // down as an unhandled rejection.\n });\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles unsupported HTTP methods\n */\n private handleUnsupportedRequest(): Response {\n return this.createErrorResponse(405, -32000, \"Method not allowed\");\n }\n\n /**\n * Settle the routing state of a request the client cancelled, which will\n * therefore never produce a response: the same drain `send()` performs once\n * a response has been written, minus the response. Idempotent, so it is a\n * no-op if the response won the race against the cancellation.\n */\n private async releaseCancelledRequest(requestId: RequestId): Promise<void> {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (streamId === undefined) {\n return;\n }\n\n // A JSON-mode POST has no stream to close: it is parked on its collector,\n // which would keep waiting for a response that is never coming. Stop\n // expecting that one and answer with whatever the POST's other requests\n // produce.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n collector.expectedIds = collector.expectedIds.filter(\n (id) => id !== requestId,\n );\n this._requestToStreamMapping.delete(requestId);\n this.settleJsonResponse(streamId, collector);\n return;\n }\n\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (streamInUse) {\n return;\n }\n\n // Nothing will ever be written to this stream again; close it rather than\n // leaving the client reading a stream that can only hang.\n const writer = this._streamMapping.get(streamId);\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Drop the routing state left over once every stream is gone, answering any\n * POST still waiting on a JSON response with whatever arrived rather than\n * leaving the request hanging.\n */\n private releasePendingRequests(): void {\n for (const collector of this._jsonResponseCollectors.values()) {\n collector.resolve(\n collector.expectedIds.map(\n (id) =>\n collector.responses.get(id) ??\n // Nobody can answer this one now. Dropping it silently would leave\n // the POST with an empty body for a single request and an empty\n // array for a batch, neither of which a client can read as a\n // result.\n ({\n error: {\n code: ErrorCode.ConnectionClosed,\n message:\n \"Connection closed: the session ended before this request was answered\",\n },\n id,\n jsonrpc: \"2.0\",\n } satisfies JSONRPCMessage),\n ),\n );\n }\n this._jsonResponseCollectors.clear();\n this._requestToStreamMapping.clear();\n }\n\n /**\n * Answer a JSON-mode POST once every request it carried has a response\n */\n private settleJsonResponse(\n streamId: StreamId,\n collector: PendingJsonResponse,\n ): void {\n const responses: JSONRPCMessage[] = [];\n for (const id of collector.expectedIds) {\n const response = collector.responses.get(id);\n if (!response) {\n // Still waiting on at least one of this POST's requests\n return;\n }\n responses.push(response);\n }\n\n this._jsonResponseCollectors.delete(streamId);\n for (const id of collector.expectedIds) {\n this._requestToStreamMapping.delete(id);\n }\n collector.resolve(responses);\n }\n\n /**\n * Whether an event addressed to `streamId` should go to the event store.\n *\n * Everything but the standalone stream is persisted whenever a store is\n * configured: those ids exist only because their stream did. The standalone\n * id is a constant, so it resolves whether or not a client ever opened that\n * stream, and storing before the first GET writes events nothing can reach —\n * replay is keyed off Last-Event-Id, and a client that never held the stream\n * was never handed an id to resume from.\n */\n private shouldPersist(\n streamId: StreamId,\n writer: undefined | WritableStreamDefaultWriter<Uint8Array>,\n ): boolean {\n if (this._eventStore === undefined) {\n return false;\n }\n\n if (streamId !== this._standaloneSseStreamId) {\n return true;\n }\n\n return (\n this._standaloneStreamOpened ||\n // A live writer means the stream is open now, which is stronger evidence\n // than the latch. Belt and braces: it keeps a writer reaching this point\n // without `trackStream` from producing an SSE event with no `id:`.\n writer !== undefined ||\n this._replaysInFlight > 0\n );\n }\n\n /**\n * Close and forget every stream of the current session and release whatever\n * was waiting on one. Shared by `close()` and DELETE so that a new teardown\n * path cannot forget to bump the generation detached replays check before\n * registering themselves.\n */\n private async teardownStreams(): Promise<void> {\n this._streamGeneration += 1;\n for (const writer of this._streamMapping.values()) {\n try {\n await writer.close();\n } catch {\n // Ignore close errors\n }\n }\n this._streamMapping.clear();\n // Per-session, like the session id: this instance stays usable, and the\n // next session starts having opened no standalone stream of its own.\n this._standaloneStreamOpened = false;\n this.releasePendingRequests();\n }\n\n private trackStream(\n streamId: StreamId,\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): void {\n // Latched here rather than at each call site so a new way of opening the\n // standalone stream cannot forget to record it.\n if (streamId === this._standaloneSseStreamId) {\n this._standaloneStreamOpened = true;\n }\n this._streamMapping.set(streamId, writer);\n const removeStreamIfCurrent = () => {\n if (this._streamMapping.get(streamId) !== writer) {\n return;\n }\n this._streamMapping.delete(streamId);\n // With an event store, a response can still arrive after the client gave\n // up, and it must be persisted for replay. Keep the routing entry so\n // send() can resolve the stream id and store under it; send() drops the\n // entry once the response has been stored.\n if (this._eventStore) {\n return;\n }\n // No event store: nothing will be persisted for this stream, so drop the\n // routing entries now rather than leaking them. No-op for the standalone\n // GET stream, which is never a request target.\n for (const [requestId, mappedStreamId] of this._requestToStreamMapping) {\n if (mappedStreamId === streamId) {\n this._requestToStreamMapping.delete(requestId);\n }\n }\n };\n void writer.closed.then(removeStreamIfCurrent, removeStreamIfCurrent);\n }\n\n /**\n * Write an SSE event to the stream\n */\n private async writeSSEEvent(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `data: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n\n /**\n * Write an SSE event with ID to the stream\n */\n private async writeSSEEventWithId(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n eventId: string,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `id: ${eventId}\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n}\n"]}
|
package/dist/edge/index.d.cts
CHANGED
|
@@ -83,6 +83,15 @@ declare class WebStreamableHTTPServerTransport implements Transport {
|
|
|
83
83
|
*/
|
|
84
84
|
private _standaloneStreamOpened;
|
|
85
85
|
private _started;
|
|
86
|
+
/**
|
|
87
|
+
* Bumped by every teardown. A replay runs detached from the request that
|
|
88
|
+
* started it, so its session can be gone by the time it settles: the
|
|
89
|
+
* teardown already cleared `_streamMapping`, and registering the writer
|
|
90
|
+
* afterwards would resurrect a stream nothing will ever close and re-latch
|
|
91
|
+
* `_standaloneStreamOpened`, leaving the next session on this instance
|
|
92
|
+
* writing its standalone events to the previous session's client.
|
|
93
|
+
*/
|
|
94
|
+
private _streamGeneration;
|
|
86
95
|
private _streamMapping;
|
|
87
96
|
private sessionIdGenerator;
|
|
88
97
|
constructor(options: WebStreamableHTTPServerTransportOptions);
|
|
@@ -164,6 +173,13 @@ declare class WebStreamableHTTPServerTransport implements Transport {
|
|
|
164
173
|
* was never handed an id to resume from.
|
|
165
174
|
*/
|
|
166
175
|
private shouldPersist;
|
|
176
|
+
/**
|
|
177
|
+
* Close and forget every stream of the current session and release whatever
|
|
178
|
+
* was waiting on one. Shared by `close()` and DELETE so that a new teardown
|
|
179
|
+
* path cannot forget to bump the generation detached replays check before
|
|
180
|
+
* registering themselves.
|
|
181
|
+
*/
|
|
182
|
+
private teardownStreams;
|
|
167
183
|
private trackStream;
|
|
168
184
|
/**
|
|
169
185
|
* Write an SSE event to the stream
|
package/dist/edge/index.d.ts
CHANGED
|
@@ -83,6 +83,15 @@ declare class WebStreamableHTTPServerTransport implements Transport {
|
|
|
83
83
|
*/
|
|
84
84
|
private _standaloneStreamOpened;
|
|
85
85
|
private _started;
|
|
86
|
+
/**
|
|
87
|
+
* Bumped by every teardown. A replay runs detached from the request that
|
|
88
|
+
* started it, so its session can be gone by the time it settles: the
|
|
89
|
+
* teardown already cleared `_streamMapping`, and registering the writer
|
|
90
|
+
* afterwards would resurrect a stream nothing will ever close and re-latch
|
|
91
|
+
* `_standaloneStreamOpened`, leaving the next session on this instance
|
|
92
|
+
* writing its standalone events to the previous session's client.
|
|
93
|
+
*/
|
|
94
|
+
private _streamGeneration;
|
|
86
95
|
private _streamMapping;
|
|
87
96
|
private sessionIdGenerator;
|
|
88
97
|
constructor(options: WebStreamableHTTPServerTransportOptions);
|
|
@@ -164,6 +173,13 @@ declare class WebStreamableHTTPServerTransport implements Transport {
|
|
|
164
173
|
* was never handed an id to resume from.
|
|
165
174
|
*/
|
|
166
175
|
private shouldPersist;
|
|
176
|
+
/**
|
|
177
|
+
* Close and forget every stream of the current session and release whatever
|
|
178
|
+
* was waiting on one. Shared by `close()` and DELETE so that a new teardown
|
|
179
|
+
* path cannot forget to bump the generation detached replays check before
|
|
180
|
+
* registering themselves.
|
|
181
|
+
*/
|
|
182
|
+
private teardownStreams;
|
|
167
183
|
private trackStream;
|
|
168
184
|
/**
|
|
169
185
|
* Write an SSE event to the stream
|
package/dist/edge/index.js
CHANGED
|
@@ -48,6 +48,15 @@ var WebStreamableHTTPServerTransport = class {
|
|
|
48
48
|
*/
|
|
49
49
|
_standaloneStreamOpened = false;
|
|
50
50
|
_started = false;
|
|
51
|
+
/**
|
|
52
|
+
* Bumped by every teardown. A replay runs detached from the request that
|
|
53
|
+
* started it, so its session can be gone by the time it settles: the
|
|
54
|
+
* teardown already cleared `_streamMapping`, and registering the writer
|
|
55
|
+
* afterwards would resurrect a stream nothing will ever close and re-latch
|
|
56
|
+
* `_standaloneStreamOpened`, leaving the next session on this instance
|
|
57
|
+
* writing its standalone events to the previous session's client.
|
|
58
|
+
*/
|
|
59
|
+
_streamGeneration = 0;
|
|
51
60
|
_streamMapping = /* @__PURE__ */ new Map();
|
|
52
61
|
sessionIdGenerator;
|
|
53
62
|
constructor(options) {
|
|
@@ -61,15 +70,7 @@ var WebStreamableHTTPServerTransport = class {
|
|
|
61
70
|
* Close the transport
|
|
62
71
|
*/
|
|
63
72
|
async close() {
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
await writer.close();
|
|
67
|
-
} catch {
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
this._streamMapping.clear();
|
|
71
|
-
this._standaloneStreamOpened = false;
|
|
72
|
-
this.releasePendingRequests();
|
|
73
|
+
await this.teardownStreams();
|
|
73
74
|
this._started = false;
|
|
74
75
|
this.onclose?.();
|
|
75
76
|
}
|
|
@@ -212,15 +213,7 @@ var WebStreamableHTTPServerTransport = class {
|
|
|
212
213
|
return this.createErrorResponse(404, -32001, "Session not found");
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
await writer.close();
|
|
218
|
-
} catch {
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
this._streamMapping.clear();
|
|
222
|
-
this._standaloneStreamOpened = false;
|
|
223
|
-
this.releasePendingRequests();
|
|
216
|
+
await this.teardownStreams();
|
|
224
217
|
await this._onsessionclosed?.(this.sessionId ?? "");
|
|
225
218
|
this.sessionId = void 0;
|
|
226
219
|
return new Response(null, {
|
|
@@ -453,6 +446,7 @@ var WebStreamableHTTPServerTransport = class {
|
|
|
453
446
|
}
|
|
454
447
|
}
|
|
455
448
|
const eventStore = this._eventStore;
|
|
449
|
+
const generation = this._streamGeneration;
|
|
456
450
|
const { readable, writable } = new TransformStream();
|
|
457
451
|
const writer = writable.getWriter();
|
|
458
452
|
this._replaysInFlight += 1;
|
|
@@ -463,6 +457,10 @@ var WebStreamableHTTPServerTransport = class {
|
|
|
463
457
|
await this.writeSSEEventWithId(writer, eventId, message);
|
|
464
458
|
}
|
|
465
459
|
});
|
|
460
|
+
if (this._streamGeneration !== generation) {
|
|
461
|
+
await this.closeQuietly(writer);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
466
464
|
if (this._streamMapping.has(streamId)) {
|
|
467
465
|
this.onerror?.(
|
|
468
466
|
new Error(
|
|
@@ -605,6 +603,24 @@ var WebStreamableHTTPServerTransport = class {
|
|
|
605
603
|
// without `trackStream` from producing an SSE event with no `id:`.
|
|
606
604
|
writer !== void 0 || this._replaysInFlight > 0;
|
|
607
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Close and forget every stream of the current session and release whatever
|
|
608
|
+
* was waiting on one. Shared by `close()` and DELETE so that a new teardown
|
|
609
|
+
* path cannot forget to bump the generation detached replays check before
|
|
610
|
+
* registering themselves.
|
|
611
|
+
*/
|
|
612
|
+
async teardownStreams() {
|
|
613
|
+
this._streamGeneration += 1;
|
|
614
|
+
for (const writer of this._streamMapping.values()) {
|
|
615
|
+
try {
|
|
616
|
+
await writer.close();
|
|
617
|
+
} catch {
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
this._streamMapping.clear();
|
|
621
|
+
this._standaloneStreamOpened = false;
|
|
622
|
+
this.releasePendingRequests();
|
|
623
|
+
}
|
|
608
624
|
trackStream(streamId, writer) {
|
|
609
625
|
if (streamId === this._standaloneSseStreamId) {
|
|
610
626
|
this._standaloneStreamOpened = true;
|
package/dist/edge/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/edge/index.ts","../../src/edge/WebStreamableHTTPServerTransport.ts"],"sourcesContent":["/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CancelledNotificationSchema,\n ErrorCode,\n isInitializeRequest,\n isJSONRPCError,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCMessage,\n JSONRPCMessageSchema,\n MessageExtraInfo,\n RequestId,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type EventId = string;\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;\n replayEventsAfter(\n lastEventId: EventId,\n options: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n },\n ): Promise<StreamId>;\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n}\n\nexport type StreamId = string;\n\n/**\n * Configuration options for WebStreamableHTTPServerTransport\n */\nexport interface WebStreamableHTTPServerTransportOptions {\n /**\n * If true, return JSON responses instead of SSE streams\n */\n enableJsonResponse?: boolean;\n\n /**\n * Event store for resumability support\n */\n eventStore?: EventStore;\n\n /**\n * Callback for session close events\n */\n onsessionclosed?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Callback for session initialization events\n */\n onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Function that generates a session ID for the transport.\n * Return undefined to disable session management (stateless mode).\n */\n sessionIdGenerator: (() => string) | undefined;\n}\n\n/**\n * Collects the responses to every request that arrived on a single POST, so\n * that JSON mode can answer once all of them are in.\n */\ninterface PendingJsonResponse {\n expectedIds: RequestId[];\n resolve: (responses: JSONRPCMessage[]) => void;\n responses: Map<RequestId, JSONRPCMessage>;\n}\n\nconst MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB\n\n/**\n * Web-standard Server transport for Streamable HTTP.\n * Uses web APIs (Request, Response, TransformStream) for edge runtime compatibility.\n */\nexport class WebStreamableHTTPServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n sessionId?: string;\n private _enableJsonResponse = false;\n private _encoder = new TextEncoder();\n private _eventStore?: EventStore;\n private _jsonResponseCollectors = new Map<StreamId, PendingJsonResponse>();\n private _onsessionclosed?: (sessionId: string) => Promise<void> | void;\n private _onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n /**\n * Replays whose stream id is still being resolved. `replayEventsAfter` only\n * reveals which stream it was replaying once it settles, so a standalone\n * send during that window has nothing to test against; persist rather than\n * drop, since over-storing for the length of a replay beats losing an event.\n */\n private _replaysInFlight = 0;\n\n private _requestToStreamMapping = new Map<RequestId, StreamId>();\n\n private _standaloneSseStreamId = \"_GET_stream\";\n /**\n * Whether a client has held the standalone GET stream during this session.\n * Latched rather than read from `_streamMapping`, so persistence survives\n * the disconnect window the store exists to cover while still telling a\n * dropped stream apart from one that was never opened. Reset with the rest\n * of the per-session state, since the next session starts with no stream.\n */\n private _standaloneStreamOpened = false;\n private _started = false;\n private _streamMapping = new Map<\n StreamId,\n WritableStreamDefaultWriter<Uint8Array>\n >();\n private sessionIdGenerator: (() => string) | undefined;\n\n constructor(options: WebStreamableHTTPServerTransportOptions) {\n this.sessionIdGenerator = options.sessionIdGenerator;\n this._enableJsonResponse = options.enableJsonResponse ?? false;\n this._eventStore = options.eventStore;\n this._onsessioninitialized = options.onsessioninitialized;\n this._onsessionclosed = options.onsessionclosed;\n }\n\n /**\n * Close the transport\n */\n async close(): Promise<void> {\n for (const writer of this._streamMapping.values()) {\n try {\n await writer.close();\n } catch {\n // Ignore close errors\n }\n }\n this._streamMapping.clear();\n this._standaloneStreamOpened = false;\n this.releasePendingRequests();\n this._started = false;\n this.onclose?.();\n }\n\n /**\n * Handles an incoming web Request and returns a Response\n */\n async handleRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n const method = request.method;\n\n if (method === \"POST\") {\n return this.handlePostRequest(request, parsedBody);\n } else if (method === \"GET\") {\n return this.handleGetRequest(request);\n } else if (method === \"DELETE\") {\n return this.handleDeleteRequest(request);\n } else {\n return this.handleUnsupportedRequest();\n }\n }\n\n /**\n * Send a message to connected clients\n */\n async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId },\n ): Promise<void> {\n let requestId = options?.relatedRequestId;\n const isResponse = isJSONRPCResponse(message) || isJSONRPCError(message);\n if (isResponse) {\n // Responses are routed by the id of the request they answer\n requestId = message.id;\n }\n\n const streamId =\n requestId === undefined\n ? this._standaloneSseStreamId\n : this._requestToStreamMapping.get(requestId);\n\n if (streamId) {\n // JSON mode has no stream to write to: collect the responses instead and\n // let handlePostRequest answer once every request on this POST is done.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n if (isResponse && requestId !== undefined) {\n collector.responses.set(requestId, message);\n this.settleJsonResponse(streamId, collector);\n }\n return;\n }\n\n const writer = this._streamMapping.get(streamId);\n // With an event store the message must be persisted even if the client\n // has already disconnected, so a reconnect with Last-Event-Id can replay\n // it. The live write to the SSE stream is best-effort on top of that.\n const store = this.shouldPersist(streamId, writer)\n ? this._eventStore\n : undefined;\n\n if (writer || store) {\n try {\n let eventId: string | undefined;\n if (store) {\n eventId = await store.storeEvent(streamId, message);\n }\n if (writer) {\n if (eventId === undefined) {\n await this.writeSSEEvent(writer, message);\n } else {\n await this.writeSSEEventWithId(writer, eventId, message);\n }\n }\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n\n // Close the POST stream once all of its requests are answered. Drained\n // whether or not the store and the socket cooperated: with an event\n // store configured `trackStream` deliberately leaves routing entries\n // alone on disconnect, so this is the only thing that reclaims them,\n // and giving up on a failed write strands the entry until the session\n // ends.\n if (requestId !== undefined && isResponse) {\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (!streamInUse) {\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n }\n }\n }\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n /**\n * Close a writer we are giving up on. The stream is already being discarded,\n * and closing one the client cancelled — or one a failed write already\n * errored — rejects; on the detached replay path that would surface as an\n * unhandled rejection rather than anything actionable.\n */\n private async closeQuietly(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): Promise<void> {\n try {\n await writer.close();\n } catch {\n // Already closed, errored, or cancelled by the client.\n }\n }\n\n /**\n * Create an error response\n */\n private createErrorResponse(\n status: number,\n code: number,\n message: string,\n ): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status,\n },\n );\n }\n\n /**\n * Get common response headers\n */\n private getResponseHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n return headers;\n }\n\n /**\n * Handles DELETE requests to terminate sessions\n */\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionId = request.headers.get(\"mcp-session-id\");\n\n if (this.sessionIdGenerator) {\n if (!sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n // Close all streams\n for (const writer of this._streamMapping.values()) {\n try {\n await writer.close();\n } catch {\n // Ignore close errors\n }\n }\n this._streamMapping.clear();\n // Per-session, like the session id below: this instance stays usable, and\n // the next session starts having opened no standalone stream of its own.\n this._standaloneStreamOpened = false;\n this.releasePendingRequests();\n\n await this._onsessionclosed?.(this.sessionId ?? \"\");\n this.sessionId = undefined;\n\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 204,\n });\n }\n\n /**\n * Handles GET requests for SSE stream\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 this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // Validate session\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (this.sessionIdGenerator && !sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionIdGenerator && this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n\n // Check for existing standalone stream\n if (this._streamMapping.has(this._standaloneSseStreamId)) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this session\",\n );\n }\n\n // Handle resumability\n if (this._eventStore) {\n const lastEventId = request.headers.get(\"last-event-id\");\n if (lastEventId) {\n return this.handleReplayEvents(lastEventId);\n }\n }\n\n // Create SSE stream\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n this.trackStream(this._standaloneSseStreamId, writer);\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles POST requests containing JSON-RPC messages\n */\n private async handlePostRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n // Validate Accept header\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n // Validate Content-Type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.createErrorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Validate Content-Length\n const contentLength = parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10,\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE) {\n return this.createErrorResponse(\n 413,\n -32000,\n `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE} bytes`,\n );\n }\n\n // Parse body\n let rawMessage: unknown;\n try {\n rawMessage = parsedBody ?? (await request.json());\n } catch {\n return this.createErrorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle batch or single message. The original shape decides the response\n // envelope: a batch always answers with an array, even when only one\n // response survives.\n const isBatch = Array.isArray(rawMessage);\n const arrayMessage: unknown[] = Array.isArray(rawMessage)\n ? rawMessage\n : [rawMessage];\n\n if (isBatch && arrayMessage.length === 0) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n // Validate messages\n const messages: JSONRPCMessage[] = [];\n for (const msg of arrayMessage) {\n const result = JSONRPCMessageSchema.safeParse(msg);\n if (!result.success) {\n return this.createErrorResponse(\n 400,\n -32700,\n \"Parse error: Invalid JSON-RPC message\",\n );\n }\n messages.push(result.data);\n }\n\n // Handle session ID\n const requestSessionId = request.headers.get(\"mcp-session-id\");\n const hasInitRequest = messages.some((msg) => isInitializeRequest(msg));\n\n // Validate session requirements\n if (hasInitRequest && requestSessionId) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Initialization requests must not include a sessionId\",\n );\n }\n\n if (hasInitRequest && messages.length > 1) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Only one initialization request is allowed\",\n );\n }\n\n if (!hasInitRequest && !requestSessionId && this.sessionIdGenerator) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n // Generate or validate session ID\n if (hasInitRequest && this.sessionIdGenerator) {\n this.sessionId = this.sessionIdGenerator();\n await this._onsessioninitialized?.(this.sessionId);\n } else if (requestSessionId) {\n if (this.sessionIdGenerator && this.sessionId !== requestSessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n const requestIds = messages\n .filter((msg) => isJSONRPCRequest(msg))\n .map((msg) => msg.id);\n const useJsonResponse =\n this._enableJsonResponse &&\n Boolean(acceptHeader?.includes(\"application/json\"));\n\n // Register the response sink before dispatching: the SDK produces\n // responses asynchronously and send() routes them back by request id.\n let jsonResponses: Promise<JSONRPCMessage[]> | undefined;\n let sseReadable: ReadableStream<Uint8Array> | undefined;\n if (requestIds.length > 0) {\n // Must be unique: a wall-clock id collides between two POSTs issued in\n // the same millisecond, which would cross-deliver their responses.\n const streamId = crypto.randomUUID();\n for (const id of requestIds) {\n this._requestToStreamMapping.set(id, streamId);\n }\n\n if (useJsonResponse) {\n jsonResponses = new Promise((resolve) => {\n this._jsonResponseCollectors.set(streamId, {\n expectedIds: requestIds,\n resolve,\n responses: new Map(),\n });\n });\n } else {\n const { readable, writable } = new TransformStream<Uint8Array>();\n this.trackStream(streamId, writable.getWriter());\n sseReadable = readable;\n }\n }\n\n // A cancelled request is never answered — the SDK suppresses the response\n // of a request whose abort signal fired — so send() never runs for its id\n // and nothing else would ever drop its routing entry. Release it here.\n for (const message of messages) {\n const cancelled = CancelledNotificationSchema.safeParse(message);\n if (cancelled.success) {\n await this.releaseCancelledRequest(cancelled.data.params.requestId);\n }\n }\n\n // Process messages through the transport\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: undefined });\n }\n\n // Nothing to answer: the batch was only notifications and/or responses\n if (requestIds.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n // Return JSON response if enabled and client accepts it\n if (jsonResponses) {\n // Wait for the handlers to actually answer, however long they take\n const responses = await jsonResponses;\n\n // Every request this POST carried was cancelled, so there is nothing to\n // put in the body — and an empty body is not a JSON-RPC message. Answer\n // the way a POST that carried no requests at all does.\n if (responses.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n // Return SSE stream\n return new Response(sseReadable ?? null, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Replay events for resumability\n */\n private async handleReplayEvents(lastEventId: string): Promise<Response> {\n if (!this._eventStore) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Resumability not supported\",\n );\n }\n\n // `getStreamIdForEventId` is optional, so this only asks stores that can\n // answer which stream the reconnect would land on before any work is done.\n // Unlike the SDK's Node transport, an event id the store does not\n // recognise is not rejected outright here: that store may still resolve it\n // in `replayEventsAfter`, and answering 400 for it would turn reconnects\n // that work today into errors.\n if (this._eventStore.getStreamIdForEventId) {\n const existingStreamId =\n await this._eventStore.getStreamIdForEventId(lastEventId);\n if (\n existingStreamId !== undefined &&\n this._streamMapping.has(existingStreamId)\n ) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this replay\",\n );\n }\n }\n\n const eventStore = this._eventStore;\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n // The replay deliberately runs detached. Nothing reads `readable` until\n // this Response is handed back to the runtime, and a TransformStream's\n // readable side has a high-water mark of 0, so the very first\n // `writer.write()` a replay performs parks forever waiting for a reader\n // that cannot exist yet — awaiting the replay here would hang every\n // reconnect that actually has events to catch up on. The SDK's Node\n // transport has the same ordering for the same reason: it flushes the 200\n // headers before replaying. The cost is that once the headers are out,\n // nothing below can be reported as a status code.\n this._replaysInFlight += 1;\n void (async () => {\n try {\n const streamId = await eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n\n // The pre-check above runs against the id the store predicts, and only\n // for stores implementing the optional lookup. This one runs against\n // the id the writer would actually be registered under, with no await\n // between it and the `set` inside `trackStream` — so it also covers\n // stores without `getStreamIdForEventId` (the common case), a store\n // whose two methods disagree, and a second reconnect that raced past\n // the pre-check while this one was replaying. Too late for a 409, but\n // ending this stream still beats orphaning the live one by overwriting\n // its writer: the client has its replayed events and can reconnect.\n if (this._streamMapping.has(streamId)) {\n this.onerror?.(\n new Error(\n `Conflict: SSE stream already exists for replayed stream ${streamId}`,\n ),\n );\n await this.closeQuietly(writer);\n return;\n }\n\n this.trackStream(streamId, writer);\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n await this.closeQuietly(writer);\n } finally {\n this._replaysInFlight -= 1;\n }\n })().catch(() => {\n // Only reachable if `onerror` itself threw, so there is nowhere left to\n // report it. Swallow rather than let a detached task take the process\n // down as an unhandled rejection.\n });\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles unsupported HTTP methods\n */\n private handleUnsupportedRequest(): Response {\n return this.createErrorResponse(405, -32000, \"Method not allowed\");\n }\n\n /**\n * Settle the routing state of a request the client cancelled, which will\n * therefore never produce a response: the same drain `send()` performs once\n * a response has been written, minus the response. Idempotent, so it is a\n * no-op if the response won the race against the cancellation.\n */\n private async releaseCancelledRequest(requestId: RequestId): Promise<void> {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (streamId === undefined) {\n return;\n }\n\n // A JSON-mode POST has no stream to close: it is parked on its collector,\n // which would keep waiting for a response that is never coming. Stop\n // expecting that one and answer with whatever the POST's other requests\n // produce.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n collector.expectedIds = collector.expectedIds.filter(\n (id) => id !== requestId,\n );\n this._requestToStreamMapping.delete(requestId);\n this.settleJsonResponse(streamId, collector);\n return;\n }\n\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (streamInUse) {\n return;\n }\n\n // Nothing will ever be written to this stream again; close it rather than\n // leaving the client reading a stream that can only hang.\n const writer = this._streamMapping.get(streamId);\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Drop the routing state left over once every stream is gone, answering any\n * POST still waiting on a JSON response with whatever arrived rather than\n * leaving the request hanging.\n */\n private releasePendingRequests(): void {\n for (const collector of this._jsonResponseCollectors.values()) {\n collector.resolve(\n collector.expectedIds.map(\n (id) =>\n collector.responses.get(id) ??\n // Nobody can answer this one now. Dropping it silently would leave\n // the POST with an empty body for a single request and an empty\n // array for a batch, neither of which a client can read as a\n // result.\n ({\n error: {\n code: ErrorCode.ConnectionClosed,\n message:\n \"Connection closed: the session ended before this request was answered\",\n },\n id,\n jsonrpc: \"2.0\",\n } satisfies JSONRPCMessage),\n ),\n );\n }\n this._jsonResponseCollectors.clear();\n this._requestToStreamMapping.clear();\n }\n\n /**\n * Answer a JSON-mode POST once every request it carried has a response\n */\n private settleJsonResponse(\n streamId: StreamId,\n collector: PendingJsonResponse,\n ): void {\n const responses: JSONRPCMessage[] = [];\n for (const id of collector.expectedIds) {\n const response = collector.responses.get(id);\n if (!response) {\n // Still waiting on at least one of this POST's requests\n return;\n }\n responses.push(response);\n }\n\n this._jsonResponseCollectors.delete(streamId);\n for (const id of collector.expectedIds) {\n this._requestToStreamMapping.delete(id);\n }\n collector.resolve(responses);\n }\n\n /**\n * Whether an event addressed to `streamId` should go to the event store.\n *\n * Everything but the standalone stream is persisted whenever a store is\n * configured: those ids exist only because their stream did. The standalone\n * id is a constant, so it resolves whether or not a client ever opened that\n * stream, and storing before the first GET writes events nothing can reach —\n * replay is keyed off Last-Event-Id, and a client that never held the stream\n * was never handed an id to resume from.\n */\n private shouldPersist(\n streamId: StreamId,\n writer: undefined | WritableStreamDefaultWriter<Uint8Array>,\n ): boolean {\n if (this._eventStore === undefined) {\n return false;\n }\n\n if (streamId !== this._standaloneSseStreamId) {\n return true;\n }\n\n return (\n this._standaloneStreamOpened ||\n // A live writer means the stream is open now, which is stronger evidence\n // than the latch. Belt and braces: it keeps a writer reaching this point\n // without `trackStream` from producing an SSE event with no `id:`.\n writer !== undefined ||\n this._replaysInFlight > 0\n );\n }\n\n private trackStream(\n streamId: StreamId,\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): void {\n // Latched here rather than at each call site so a new way of opening the\n // standalone stream cannot forget to record it.\n if (streamId === this._standaloneSseStreamId) {\n this._standaloneStreamOpened = true;\n }\n this._streamMapping.set(streamId, writer);\n const removeStreamIfCurrent = () => {\n if (this._streamMapping.get(streamId) !== writer) {\n return;\n }\n this._streamMapping.delete(streamId);\n // With an event store, a response can still arrive after the client gave\n // up, and it must be persisted for replay. Keep the routing entry so\n // send() can resolve the stream id and store under it; send() drops the\n // entry once the response has been stored.\n if (this._eventStore) {\n return;\n }\n // No event store: nothing will be persisted for this stream, so drop the\n // routing entries now rather than leaking them. No-op for the standalone\n // GET stream, which is never a request target.\n for (const [requestId, mappedStreamId] of this._requestToStreamMapping) {\n if (mappedStreamId === streamId) {\n this._requestToStreamMapping.delete(requestId);\n }\n }\n };\n void writer.closed.then(removeStreamIfCurrent, removeStreamIfCurrent);\n }\n\n /**\n * Write an SSE event to the stream\n */\n private async writeSSEEvent(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `data: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n\n /**\n * Write an SSE event with ID to the stream\n */\n private async writeSSEEventWithId(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n eventId: string,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `id: ${eventId}\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n}\n"],"mappings":"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","names":["ErrorCode","ErrorCode"]}
|
|
1
|
+
{"version":3,"sources":["../../src/edge/index.ts","../../src/edge/WebStreamableHTTPServerTransport.ts"],"sourcesContent":["/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CancelledNotificationSchema,\n ErrorCode,\n isInitializeRequest,\n isJSONRPCError,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCMessage,\n JSONRPCMessageSchema,\n MessageExtraInfo,\n RequestId,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type EventId = string;\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;\n replayEventsAfter(\n lastEventId: EventId,\n options: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n },\n ): Promise<StreamId>;\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n}\n\nexport type StreamId = string;\n\n/**\n * Configuration options for WebStreamableHTTPServerTransport\n */\nexport interface WebStreamableHTTPServerTransportOptions {\n /**\n * If true, return JSON responses instead of SSE streams\n */\n enableJsonResponse?: boolean;\n\n /**\n * Event store for resumability support\n */\n eventStore?: EventStore;\n\n /**\n * Callback for session close events\n */\n onsessionclosed?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Callback for session initialization events\n */\n onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n\n /**\n * Function that generates a session ID for the transport.\n * Return undefined to disable session management (stateless mode).\n */\n sessionIdGenerator: (() => string) | undefined;\n}\n\n/**\n * Collects the responses to every request that arrived on a single POST, so\n * that JSON mode can answer once all of them are in.\n */\ninterface PendingJsonResponse {\n expectedIds: RequestId[];\n resolve: (responses: JSONRPCMessage[]) => void;\n responses: Map<RequestId, JSONRPCMessage>;\n}\n\nconst MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB\n\n/**\n * Web-standard Server transport for Streamable HTTP.\n * Uses web APIs (Request, Response, TransformStream) for edge runtime compatibility.\n */\nexport class WebStreamableHTTPServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n sessionId?: string;\n private _enableJsonResponse = false;\n private _encoder = new TextEncoder();\n private _eventStore?: EventStore;\n private _jsonResponseCollectors = new Map<StreamId, PendingJsonResponse>();\n private _onsessionclosed?: (sessionId: string) => Promise<void> | void;\n private _onsessioninitialized?: (sessionId: string) => Promise<void> | void;\n /**\n * Replays whose stream id is still being resolved. `replayEventsAfter` only\n * reveals which stream it was replaying once it settles, so a standalone\n * send during that window has nothing to test against; persist rather than\n * drop, since over-storing for the length of a replay beats losing an event.\n */\n private _replaysInFlight = 0;\n\n private _requestToStreamMapping = new Map<RequestId, StreamId>();\n\n private _standaloneSseStreamId = \"_GET_stream\";\n /**\n * Whether a client has held the standalone GET stream during this session.\n * Latched rather than read from `_streamMapping`, so persistence survives\n * the disconnect window the store exists to cover while still telling a\n * dropped stream apart from one that was never opened. Reset with the rest\n * of the per-session state, since the next session starts with no stream.\n */\n private _standaloneStreamOpened = false;\n private _started = false;\n /**\n * Bumped by every teardown. A replay runs detached from the request that\n * started it, so its session can be gone by the time it settles: the\n * teardown already cleared `_streamMapping`, and registering the writer\n * afterwards would resurrect a stream nothing will ever close and re-latch\n * `_standaloneStreamOpened`, leaving the next session on this instance\n * writing its standalone events to the previous session's client.\n */\n private _streamGeneration = 0;\n\n private _streamMapping = new Map<\n StreamId,\n WritableStreamDefaultWriter<Uint8Array>\n >();\n private sessionIdGenerator: (() => string) | undefined;\n\n constructor(options: WebStreamableHTTPServerTransportOptions) {\n this.sessionIdGenerator = options.sessionIdGenerator;\n this._enableJsonResponse = options.enableJsonResponse ?? false;\n this._eventStore = options.eventStore;\n this._onsessioninitialized = options.onsessioninitialized;\n this._onsessionclosed = options.onsessionclosed;\n }\n\n /**\n * Close the transport\n */\n async close(): Promise<void> {\n await this.teardownStreams();\n this._started = false;\n this.onclose?.();\n }\n\n /**\n * Handles an incoming web Request and returns a Response\n */\n async handleRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n const method = request.method;\n\n if (method === \"POST\") {\n return this.handlePostRequest(request, parsedBody);\n } else if (method === \"GET\") {\n return this.handleGetRequest(request);\n } else if (method === \"DELETE\") {\n return this.handleDeleteRequest(request);\n } else {\n return this.handleUnsupportedRequest();\n }\n }\n\n /**\n * Send a message to connected clients\n */\n async send(\n message: JSONRPCMessage,\n options?: { relatedRequestId?: RequestId },\n ): Promise<void> {\n let requestId = options?.relatedRequestId;\n const isResponse = isJSONRPCResponse(message) || isJSONRPCError(message);\n if (isResponse) {\n // Responses are routed by the id of the request they answer\n requestId = message.id;\n }\n\n const streamId =\n requestId === undefined\n ? this._standaloneSseStreamId\n : this._requestToStreamMapping.get(requestId);\n\n if (streamId) {\n // JSON mode has no stream to write to: collect the responses instead and\n // let handlePostRequest answer once every request on this POST is done.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n if (isResponse && requestId !== undefined) {\n collector.responses.set(requestId, message);\n this.settleJsonResponse(streamId, collector);\n }\n return;\n }\n\n const writer = this._streamMapping.get(streamId);\n // With an event store the message must be persisted even if the client\n // has already disconnected, so a reconnect with Last-Event-Id can replay\n // it. The live write to the SSE stream is best-effort on top of that.\n const store = this.shouldPersist(streamId, writer)\n ? this._eventStore\n : undefined;\n\n if (writer || store) {\n try {\n let eventId: string | undefined;\n if (store) {\n eventId = await store.storeEvent(streamId, message);\n }\n if (writer) {\n if (eventId === undefined) {\n await this.writeSSEEvent(writer, message);\n } else {\n await this.writeSSEEventWithId(writer, eventId, message);\n }\n }\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n\n // Close the POST stream once all of its requests are answered. Drained\n // whether or not the store and the socket cooperated: with an event\n // store configured `trackStream` deliberately leaves routing entries\n // alone on disconnect, so this is the only thing that reclaims them,\n // and giving up on a failed write strands the entry until the session\n // ends.\n if (requestId !== undefined && isResponse) {\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (!streamInUse) {\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n }\n }\n }\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n /**\n * Close a writer we are giving up on. The stream is already being discarded,\n * and closing one the client cancelled — or one a failed write already\n * errored — rejects; on the detached replay path that would surface as an\n * unhandled rejection rather than anything actionable.\n */\n private async closeQuietly(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): Promise<void> {\n try {\n await writer.close();\n } catch {\n // Already closed, errored, or cancelled by the client.\n }\n }\n\n /**\n * Create an error response\n */\n private createErrorResponse(\n status: number,\n code: number,\n message: string,\n ): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status,\n },\n );\n }\n\n /**\n * Get common response headers\n */\n private getResponseHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n return headers;\n }\n\n /**\n * Handles DELETE requests to terminate sessions\n */\n private async handleDeleteRequest(request: Request): Promise<Response> {\n const sessionId = request.headers.get(\"mcp-session-id\");\n\n if (this.sessionIdGenerator) {\n if (!sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n await this.teardownStreams();\n\n await this._onsessionclosed?.(this.sessionId ?? \"\");\n this.sessionId = undefined;\n\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 204,\n });\n }\n\n /**\n * Handles GET requests for SSE stream\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 this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // Validate session\n const sessionId = request.headers.get(\"mcp-session-id\");\n if (this.sessionIdGenerator && !sessionId) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n if (this.sessionIdGenerator && this.sessionId !== sessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n\n // Check for existing standalone stream\n if (this._streamMapping.has(this._standaloneSseStreamId)) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this session\",\n );\n }\n\n // Handle resumability\n if (this._eventStore) {\n const lastEventId = request.headers.get(\"last-event-id\");\n if (lastEventId) {\n return this.handleReplayEvents(lastEventId);\n }\n }\n\n // Create SSE stream\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n this.trackStream(this._standaloneSseStreamId, writer);\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles POST requests containing JSON-RPC messages\n */\n private async handlePostRequest(\n request: Request,\n parsedBody?: unknown,\n ): Promise<Response> {\n // Validate Accept header\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.createErrorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n // Validate Content-Type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.createErrorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Validate Content-Length\n const contentLength = parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10,\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE) {\n return this.createErrorResponse(\n 413,\n -32000,\n `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE} bytes`,\n );\n }\n\n // Parse body\n let rawMessage: unknown;\n try {\n rawMessage = parsedBody ?? (await request.json());\n } catch {\n return this.createErrorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle batch or single message. The original shape decides the response\n // envelope: a batch always answers with an array, even when only one\n // response survives.\n const isBatch = Array.isArray(rawMessage);\n const arrayMessage: unknown[] = Array.isArray(rawMessage)\n ? rawMessage\n : [rawMessage];\n\n if (isBatch && arrayMessage.length === 0) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n // Validate messages\n const messages: JSONRPCMessage[] = [];\n for (const msg of arrayMessage) {\n const result = JSONRPCMessageSchema.safeParse(msg);\n if (!result.success) {\n return this.createErrorResponse(\n 400,\n -32700,\n \"Parse error: Invalid JSON-RPC message\",\n );\n }\n messages.push(result.data);\n }\n\n // Handle session ID\n const requestSessionId = request.headers.get(\"mcp-session-id\");\n const hasInitRequest = messages.some((msg) => isInitializeRequest(msg));\n\n // Validate session requirements\n if (hasInitRequest && requestSessionId) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Initialization requests must not include a sessionId\",\n );\n }\n\n if (hasInitRequest && messages.length > 1) {\n return this.createErrorResponse(\n 400,\n -32600,\n \"Invalid Request: Only one initialization request is allowed\",\n );\n }\n\n if (!hasInitRequest && !requestSessionId && this.sessionIdGenerator) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Bad Request: Mcp-Session-Id header is required\",\n );\n }\n\n // Generate or validate session ID\n if (hasInitRequest && this.sessionIdGenerator) {\n this.sessionId = this.sessionIdGenerator();\n await this._onsessioninitialized?.(this.sessionId);\n } else if (requestSessionId) {\n if (this.sessionIdGenerator && this.sessionId !== requestSessionId) {\n return this.createErrorResponse(404, -32001, \"Session not found\");\n }\n }\n\n const requestIds = messages\n .filter((msg) => isJSONRPCRequest(msg))\n .map((msg) => msg.id);\n const useJsonResponse =\n this._enableJsonResponse &&\n Boolean(acceptHeader?.includes(\"application/json\"));\n\n // Register the response sink before dispatching: the SDK produces\n // responses asynchronously and send() routes them back by request id.\n let jsonResponses: Promise<JSONRPCMessage[]> | undefined;\n let sseReadable: ReadableStream<Uint8Array> | undefined;\n if (requestIds.length > 0) {\n // Must be unique: a wall-clock id collides between two POSTs issued in\n // the same millisecond, which would cross-deliver their responses.\n const streamId = crypto.randomUUID();\n for (const id of requestIds) {\n this._requestToStreamMapping.set(id, streamId);\n }\n\n if (useJsonResponse) {\n jsonResponses = new Promise((resolve) => {\n this._jsonResponseCollectors.set(streamId, {\n expectedIds: requestIds,\n resolve,\n responses: new Map(),\n });\n });\n } else {\n const { readable, writable } = new TransformStream<Uint8Array>();\n this.trackStream(streamId, writable.getWriter());\n sseReadable = readable;\n }\n }\n\n // A cancelled request is never answered — the SDK suppresses the response\n // of a request whose abort signal fired — so send() never runs for its id\n // and nothing else would ever drop its routing entry. Release it here.\n for (const message of messages) {\n const cancelled = CancelledNotificationSchema.safeParse(message);\n if (cancelled.success) {\n await this.releaseCancelledRequest(cancelled.data.params.requestId);\n }\n }\n\n // Process messages through the transport\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: undefined });\n }\n\n // Nothing to answer: the batch was only notifications and/or responses\n if (requestIds.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n // Return JSON response if enabled and client accepts it\n if (jsonResponses) {\n // Wait for the handlers to actually answer, however long they take\n const responses = await jsonResponses;\n\n // Every request this POST carried was cancelled, so there is nothing to\n // put in the body — and an empty body is not a JSON-RPC message. Answer\n // the way a POST that carried no requests at all does.\n if (responses.length === 0) {\n return new Response(null, {\n headers: this.getResponseHeaders(),\n status: 202,\n });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n ...this.getResponseHeaders(),\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n // Return SSE stream\n return new Response(sseReadable ?? null, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Replay events for resumability\n */\n private async handleReplayEvents(lastEventId: string): Promise<Response> {\n if (!this._eventStore) {\n return this.createErrorResponse(\n 400,\n -32000,\n \"Resumability not supported\",\n );\n }\n\n // `getStreamIdForEventId` is optional, so this only asks stores that can\n // answer which stream the reconnect would land on before any work is done.\n // Unlike the SDK's Node transport, an event id the store does not\n // recognise is not rejected outright here: that store may still resolve it\n // in `replayEventsAfter`, and answering 400 for it would turn reconnects\n // that work today into errors.\n if (this._eventStore.getStreamIdForEventId) {\n const existingStreamId =\n await this._eventStore.getStreamIdForEventId(lastEventId);\n if (\n existingStreamId !== undefined &&\n this._streamMapping.has(existingStreamId)\n ) {\n return this.createErrorResponse(\n 409,\n -32000,\n \"Conflict: SSE stream already exists for this replay\",\n );\n }\n }\n\n const eventStore = this._eventStore;\n const generation = this._streamGeneration;\n const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n // The replay deliberately runs detached. Nothing reads `readable` until\n // this Response is handed back to the runtime, and a TransformStream's\n // readable side has a high-water mark of 0, so the very first\n // `writer.write()` a replay performs parks forever waiting for a reader\n // that cannot exist yet — awaiting the replay here would hang every\n // reconnect that actually has events to catch up on. The SDK's Node\n // transport has the same ordering for the same reason: it flushes the 200\n // headers before replaying. The cost is that once the headers are out,\n // nothing below can be reported as a status code.\n this._replaysInFlight += 1;\n void (async () => {\n try {\n const streamId = await eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n\n // `close()` or a DELETE may have ended the session while the replay\n // was running. That teardown could not close this writer — it was not\n // in `_streamMapping` yet — so end it here rather than registering it\n // into a session that no longer exists.\n if (this._streamGeneration !== generation) {\n await this.closeQuietly(writer);\n return;\n }\n\n // The pre-check above runs against the id the store predicts, and only\n // for stores implementing the optional lookup. This one runs against\n // the id the writer would actually be registered under, with no await\n // between it and the `set` inside `trackStream` — so it also covers\n // stores without `getStreamIdForEventId` (the common case), a store\n // whose two methods disagree, and a second reconnect that raced past\n // the pre-check while this one was replaying. Too late for a 409, but\n // ending this stream still beats orphaning the live one by overwriting\n // its writer: the client has its replayed events and can reconnect.\n if (this._streamMapping.has(streamId)) {\n this.onerror?.(\n new Error(\n `Conflict: SSE stream already exists for replayed stream ${streamId}`,\n ),\n );\n await this.closeQuietly(writer);\n return;\n }\n\n this.trackStream(streamId, writer);\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n await this.closeQuietly(writer);\n } finally {\n this._replaysInFlight -= 1;\n }\n })().catch(() => {\n // Only reachable if `onerror` itself threw, so there is nowhere left to\n // report it. Swallow rather than let a detached task take the process\n // down as an unhandled rejection.\n });\n\n return new Response(readable, {\n headers: {\n ...this.getResponseHeaders(),\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n status: 200,\n });\n }\n\n /**\n * Handles unsupported HTTP methods\n */\n private handleUnsupportedRequest(): Response {\n return this.createErrorResponse(405, -32000, \"Method not allowed\");\n }\n\n /**\n * Settle the routing state of a request the client cancelled, which will\n * therefore never produce a response: the same drain `send()` performs once\n * a response has been written, minus the response. Idempotent, so it is a\n * no-op if the response won the race against the cancellation.\n */\n private async releaseCancelledRequest(requestId: RequestId): Promise<void> {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (streamId === undefined) {\n return;\n }\n\n // A JSON-mode POST has no stream to close: it is parked on its collector,\n // which would keep waiting for a response that is never coming. Stop\n // expecting that one and answer with whatever the POST's other requests\n // produce.\n const collector = this._jsonResponseCollectors.get(streamId);\n if (collector) {\n collector.expectedIds = collector.expectedIds.filter(\n (id) => id !== requestId,\n );\n this._requestToStreamMapping.delete(requestId);\n this.settleJsonResponse(streamId, collector);\n return;\n }\n\n this._requestToStreamMapping.delete(requestId);\n const streamInUse = Array.from(\n this._requestToStreamMapping.values(),\n ).includes(streamId);\n if (streamInUse) {\n return;\n }\n\n // Nothing will ever be written to this stream again; close it rather than\n // leaving the client reading a stream that can only hang.\n const writer = this._streamMapping.get(streamId);\n this._streamMapping.delete(streamId);\n if (writer) {\n try {\n await writer.close();\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Drop the routing state left over once every stream is gone, answering any\n * POST still waiting on a JSON response with whatever arrived rather than\n * leaving the request hanging.\n */\n private releasePendingRequests(): void {\n for (const collector of this._jsonResponseCollectors.values()) {\n collector.resolve(\n collector.expectedIds.map(\n (id) =>\n collector.responses.get(id) ??\n // Nobody can answer this one now. Dropping it silently would leave\n // the POST with an empty body for a single request and an empty\n // array for a batch, neither of which a client can read as a\n // result.\n ({\n error: {\n code: ErrorCode.ConnectionClosed,\n message:\n \"Connection closed: the session ended before this request was answered\",\n },\n id,\n jsonrpc: \"2.0\",\n } satisfies JSONRPCMessage),\n ),\n );\n }\n this._jsonResponseCollectors.clear();\n this._requestToStreamMapping.clear();\n }\n\n /**\n * Answer a JSON-mode POST once every request it carried has a response\n */\n private settleJsonResponse(\n streamId: StreamId,\n collector: PendingJsonResponse,\n ): void {\n const responses: JSONRPCMessage[] = [];\n for (const id of collector.expectedIds) {\n const response = collector.responses.get(id);\n if (!response) {\n // Still waiting on at least one of this POST's requests\n return;\n }\n responses.push(response);\n }\n\n this._jsonResponseCollectors.delete(streamId);\n for (const id of collector.expectedIds) {\n this._requestToStreamMapping.delete(id);\n }\n collector.resolve(responses);\n }\n\n /**\n * Whether an event addressed to `streamId` should go to the event store.\n *\n * Everything but the standalone stream is persisted whenever a store is\n * configured: those ids exist only because their stream did. The standalone\n * id is a constant, so it resolves whether or not a client ever opened that\n * stream, and storing before the first GET writes events nothing can reach —\n * replay is keyed off Last-Event-Id, and a client that never held the stream\n * was never handed an id to resume from.\n */\n private shouldPersist(\n streamId: StreamId,\n writer: undefined | WritableStreamDefaultWriter<Uint8Array>,\n ): boolean {\n if (this._eventStore === undefined) {\n return false;\n }\n\n if (streamId !== this._standaloneSseStreamId) {\n return true;\n }\n\n return (\n this._standaloneStreamOpened ||\n // A live writer means the stream is open now, which is stronger evidence\n // than the latch. Belt and braces: it keeps a writer reaching this point\n // without `trackStream` from producing an SSE event with no `id:`.\n writer !== undefined ||\n this._replaysInFlight > 0\n );\n }\n\n /**\n * Close and forget every stream of the current session and release whatever\n * was waiting on one. Shared by `close()` and DELETE so that a new teardown\n * path cannot forget to bump the generation detached replays check before\n * registering themselves.\n */\n private async teardownStreams(): Promise<void> {\n this._streamGeneration += 1;\n for (const writer of this._streamMapping.values()) {\n try {\n await writer.close();\n } catch {\n // Ignore close errors\n }\n }\n this._streamMapping.clear();\n // Per-session, like the session id: this instance stays usable, and the\n // next session starts having opened no standalone stream of its own.\n this._standaloneStreamOpened = false;\n this.releasePendingRequests();\n }\n\n private trackStream(\n streamId: StreamId,\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): void {\n // Latched here rather than at each call site so a new way of opening the\n // standalone stream cannot forget to record it.\n if (streamId === this._standaloneSseStreamId) {\n this._standaloneStreamOpened = true;\n }\n this._streamMapping.set(streamId, writer);\n const removeStreamIfCurrent = () => {\n if (this._streamMapping.get(streamId) !== writer) {\n return;\n }\n this._streamMapping.delete(streamId);\n // With an event store, a response can still arrive after the client gave\n // up, and it must be persisted for replay. Keep the routing entry so\n // send() can resolve the stream id and store under it; send() drops the\n // entry once the response has been stored.\n if (this._eventStore) {\n return;\n }\n // No event store: nothing will be persisted for this stream, so drop the\n // routing entries now rather than leaking them. No-op for the standalone\n // GET stream, which is never a request target.\n for (const [requestId, mappedStreamId] of this._requestToStreamMapping) {\n if (mappedStreamId === streamId) {\n this._requestToStreamMapping.delete(requestId);\n }\n }\n };\n void writer.closed.then(removeStreamIfCurrent, removeStreamIfCurrent);\n }\n\n /**\n * Write an SSE event to the stream\n */\n private async writeSSEEvent(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `data: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n\n /**\n * Write an SSE event with ID to the stream\n */\n private async writeSSEEventWithId(\n writer: WritableStreamDefaultWriter<Uint8Array>,\n eventId: string,\n message: JSONRPCMessage,\n ): Promise<void> {\n const data = `id: ${eventId}\\ndata: ${JSON.stringify(message)}\\n\\n`;\n await writer.write(this._encoder.encode(data));\n }\n}\n"],"mappings":"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","names":["ErrorCode","ErrorCode"]}
|