fastmcp 4.16.1 → 4.16.3

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.
@@ -16,6 +16,7 @@ var _zodtojsonschema = require('zod-to-json-schema');
16
16
 
17
17
 
18
18
 
19
+
19
20
  var MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024;
20
21
  var WebStreamableHTTPServerTransport = (_class = class {
21
22
 
@@ -28,12 +29,27 @@ var WebStreamableHTTPServerTransport = (_class = class {
28
29
  __init3() {this._jsonResponseCollectors = /* @__PURE__ */ new Map()}
29
30
 
30
31
 
31
- __init4() {this._requestToStreamMapping = /* @__PURE__ */ new Map()}
32
- __init5() {this._standaloneSseStreamId = "_GET_stream"}
33
- __init6() {this._started = false}
34
- __init7() {this._streamMapping = /* @__PURE__ */ new Map()}
32
+ /**
33
+ * Replays whose stream id is still being resolved. `replayEventsAfter` only
34
+ * reveals which stream it was replaying once it settles, so a standalone
35
+ * send during that window has nothing to test against; persist rather than
36
+ * drop, since over-storing for the length of a replay beats losing an event.
37
+ */
38
+ __init4() {this._replaysInFlight = 0}
39
+ __init5() {this._requestToStreamMapping = /* @__PURE__ */ new Map()}
40
+ __init6() {this._standaloneSseStreamId = "_GET_stream"}
41
+ /**
42
+ * Whether a client has held the standalone GET stream during this session.
43
+ * Latched rather than read from `_streamMapping`, so persistence survives
44
+ * the disconnect window the store exists to cover while still telling a
45
+ * dropped stream apart from one that was never opened. Reset with the rest
46
+ * of the per-session state, since the next session starts with no stream.
47
+ */
48
+ __init7() {this._standaloneStreamOpened = false}
49
+ __init8() {this._started = false}
50
+ __init9() {this._streamMapping = /* @__PURE__ */ new Map()}
35
51
 
36
- 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);
52
+ 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);
37
53
  this.sessionIdGenerator = options.sessionIdGenerator;
38
54
  this._enableJsonResponse = _nullishCoalesce(options.enableJsonResponse, () => ( false));
39
55
  this._eventStore = options.eventStore;
@@ -51,6 +67,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
51
67
  }
52
68
  }
53
69
  this._streamMapping.clear();
70
+ this._standaloneStreamOpened = false;
54
71
  this.releasePendingRequests();
55
72
  this._started = false;
56
73
  _optionalChain([this, 'access', _ => _.onclose, 'optionalCall', _2 => _2()]);
@@ -90,25 +107,18 @@ var WebStreamableHTTPServerTransport = (_class = class {
90
107
  return;
91
108
  }
92
109
  const writer = this._streamMapping.get(streamId);
93
- if (writer) {
110
+ const store = this.shouldPersist(streamId, writer) ? this._eventStore : void 0;
111
+ if (writer || store) {
94
112
  try {
95
- if (this._eventStore) {
96
- const eventId = await this._eventStore.storeEvent(
97
- streamId,
98
- message
99
- );
100
- await this.writeSSEEventWithId(writer, eventId, message);
101
- } else {
102
- await this.writeSSEEvent(writer, message);
113
+ let eventId;
114
+ if (store) {
115
+ eventId = await store.storeEvent(streamId, message);
103
116
  }
104
- if (requestId !== void 0 && isResponse) {
105
- this._requestToStreamMapping.delete(requestId);
106
- const streamInUse = Array.from(
107
- this._requestToStreamMapping.values()
108
- ).includes(streamId);
109
- if (!streamInUse) {
110
- this._streamMapping.delete(streamId);
111
- await writer.close();
117
+ if (writer) {
118
+ if (eventId === void 0) {
119
+ await this.writeSSEEvent(writer, message);
120
+ } else {
121
+ await this.writeSSEEventWithId(writer, eventId, message);
112
122
  }
113
123
  }
114
124
  } catch (error) {
@@ -116,6 +126,24 @@ var WebStreamableHTTPServerTransport = (_class = class {
116
126
  error instanceof Error ? error : new Error(String(error))
117
127
  )]);
118
128
  }
129
+ if (requestId !== void 0 && isResponse) {
130
+ this._requestToStreamMapping.delete(requestId);
131
+ const streamInUse = Array.from(
132
+ this._requestToStreamMapping.values()
133
+ ).includes(streamId);
134
+ if (!streamInUse) {
135
+ this._streamMapping.delete(streamId);
136
+ if (writer) {
137
+ try {
138
+ await writer.close();
139
+ } catch (error) {
140
+ _optionalChain([this, 'access', _6 => _6.onerror, 'optionalCall', _7 => _7(
141
+ error instanceof Error ? error : new Error(String(error))
142
+ )]);
143
+ }
144
+ }
145
+ }
146
+ }
119
147
  }
120
148
  }
121
149
  }
@@ -178,8 +206,9 @@ var WebStreamableHTTPServerTransport = (_class = class {
178
206
  }
179
207
  }
180
208
  this._streamMapping.clear();
209
+ this._standaloneStreamOpened = false;
181
210
  this.releasePendingRequests();
182
- await _optionalChain([this, 'access', _6 => _6._onsessionclosed, 'optionalCall', _7 => _7(_nullishCoalesce(this.sessionId, () => ( "")))]);
211
+ await _optionalChain([this, 'access', _8 => _8._onsessionclosed, 'optionalCall', _9 => _9(_nullishCoalesce(this.sessionId, () => ( "")))]);
183
212
  this.sessionId = void 0;
184
213
  return new Response(null, {
185
214
  headers: this.getResponseHeaders(),
@@ -191,7 +220,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
191
220
  */
192
221
  async handleGetRequest(request) {
193
222
  const acceptHeader = request.headers.get("accept");
194
- if (!_optionalChain([acceptHeader, 'optionalAccess', _8 => _8.includes, 'call', _9 => _9("text/event-stream")])) {
223
+ if (!_optionalChain([acceptHeader, 'optionalAccess', _10 => _10.includes, 'call', _11 => _11("text/event-stream")])) {
195
224
  return this.createErrorResponse(
196
225
  406,
197
226
  -32e3,
@@ -240,7 +269,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
240
269
  */
241
270
  async handlePostRequest(request, parsedBody) {
242
271
  const acceptHeader = request.headers.get("accept");
243
- if (!_optionalChain([acceptHeader, 'optionalAccess', _10 => _10.includes, 'call', _11 => _11("application/json")]) && !_optionalChain([acceptHeader, 'optionalAccess', _12 => _12.includes, 'call', _13 => _13("text/event-stream")])) {
272
+ if (!_optionalChain([acceptHeader, 'optionalAccess', _12 => _12.includes, 'call', _13 => _13("application/json")]) && !_optionalChain([acceptHeader, 'optionalAccess', _14 => _14.includes, 'call', _15 => _15("text/event-stream")])) {
244
273
  return this.createErrorResponse(
245
274
  406,
246
275
  -32e3,
@@ -248,7 +277,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
248
277
  );
249
278
  }
250
279
  const contentType = request.headers.get("content-type");
251
- if (!_optionalChain([contentType, 'optionalAccess', _14 => _14.includes, 'call', _15 => _15("application/json")])) {
280
+ if (!_optionalChain([contentType, 'optionalAccess', _16 => _16.includes, 'call', _17 => _17("application/json")])) {
252
281
  return this.createErrorResponse(
253
282
  415,
254
283
  -32e3,
@@ -318,14 +347,14 @@ var WebStreamableHTTPServerTransport = (_class = class {
318
347
  }
319
348
  if (hasInitRequest && this.sessionIdGenerator) {
320
349
  this.sessionId = this.sessionIdGenerator();
321
- await _optionalChain([this, 'access', _16 => _16._onsessioninitialized, 'optionalCall', _17 => _17(this.sessionId)]);
350
+ await _optionalChain([this, 'access', _18 => _18._onsessioninitialized, 'optionalCall', _19 => _19(this.sessionId)]);
322
351
  } else if (requestSessionId) {
323
352
  if (this.sessionIdGenerator && this.sessionId !== requestSessionId) {
324
353
  return this.createErrorResponse(404, -32001, "Session not found");
325
354
  }
326
355
  }
327
356
  const requestIds = messages.filter((msg) => _typesjs.isJSONRPCRequest.call(void 0, msg)).map((msg) => msg.id);
328
- const useJsonResponse = this._enableJsonResponse && Boolean(_optionalChain([acceptHeader, 'optionalAccess', _18 => _18.includes, 'call', _19 => _19("application/json")]));
357
+ const useJsonResponse = this._enableJsonResponse && Boolean(_optionalChain([acceptHeader, 'optionalAccess', _20 => _20.includes, 'call', _21 => _21("application/json")]));
329
358
  let jsonResponses;
330
359
  let sseReadable;
331
360
  if (requestIds.length > 0) {
@@ -348,7 +377,13 @@ var WebStreamableHTTPServerTransport = (_class = class {
348
377
  }
349
378
  }
350
379
  for (const message of messages) {
351
- _optionalChain([this, 'access', _20 => _20.onmessage, 'optionalCall', _21 => _21(message, { authInfo: void 0 })]);
380
+ const cancelled = _typesjs.CancelledNotificationSchema.safeParse(message);
381
+ if (cancelled.success) {
382
+ await this.releaseCancelledRequest(cancelled.data.params.requestId);
383
+ }
384
+ }
385
+ for (const message of messages) {
386
+ _optionalChain([this, 'access', _22 => _22.onmessage, 'optionalCall', _23 => _23(message, { authInfo: void 0 })]);
352
387
  }
353
388
  if (requestIds.length === 0) {
354
389
  return new Response(null, {
@@ -390,6 +425,7 @@ var WebStreamableHTTPServerTransport = (_class = class {
390
425
  }
391
426
  const { readable, writable } = new TransformStream();
392
427
  const writer = writable.getWriter();
428
+ this._replaysInFlight += 1;
393
429
  try {
394
430
  const streamId = await this._eventStore.replayEventsAfter(lastEventId, {
395
431
  send: async (eventId, message) => {
@@ -400,6 +436,8 @@ var WebStreamableHTTPServerTransport = (_class = class {
400
436
  } catch (error) {
401
437
  await writer.close();
402
438
  return this.createErrorResponse(500, -32e3, `Replay failed: ${error}`);
439
+ } finally {
440
+ this._replaysInFlight -= 1;
403
441
  }
404
442
  return new Response(readable, {
405
443
  headers: {
@@ -417,6 +455,39 @@ var WebStreamableHTTPServerTransport = (_class = class {
417
455
  handleUnsupportedRequest() {
418
456
  return this.createErrorResponse(405, -32e3, "Method not allowed");
419
457
  }
458
+ /**
459
+ * Settle the routing state of a request the client cancelled, which will
460
+ * therefore never produce a response: the same drain `send()` performs once
461
+ * a response has been written, minus the response. Idempotent, so it is a
462
+ * no-op if the response won the race against the cancellation.
463
+ *
464
+ * JSON-mode POSTs are left alone: `_jsonResponseCollectors` owns their
465
+ * settlement.
466
+ */
467
+ async releaseCancelledRequest(requestId) {
468
+ const streamId = this._requestToStreamMapping.get(requestId);
469
+ if (streamId === void 0 || this._jsonResponseCollectors.has(streamId)) {
470
+ return;
471
+ }
472
+ this._requestToStreamMapping.delete(requestId);
473
+ const streamInUse = Array.from(
474
+ this._requestToStreamMapping.values()
475
+ ).includes(streamId);
476
+ if (streamInUse) {
477
+ return;
478
+ }
479
+ const writer = this._streamMapping.get(streamId);
480
+ this._streamMapping.delete(streamId);
481
+ if (writer) {
482
+ try {
483
+ await writer.close();
484
+ } catch (error) {
485
+ _optionalChain([this, 'access', _24 => _24.onerror, 'optionalCall', _25 => _25(
486
+ error instanceof Error ? error : new Error(String(error))
487
+ )]);
488
+ }
489
+ }
490
+ }
420
491
  /**
421
492
  * Drop the routing state left over once every stream is gone, answering any
422
493
  * POST still waiting on a JSON response with whatever arrived rather than
@@ -449,13 +520,41 @@ var WebStreamableHTTPServerTransport = (_class = class {
449
520
  }
450
521
  collector.resolve(responses);
451
522
  }
523
+ /**
524
+ * Whether an event addressed to `streamId` should go to the event store.
525
+ *
526
+ * Everything but the standalone stream is persisted whenever a store is
527
+ * configured: those ids exist only because their stream did. The standalone
528
+ * id is a constant, so it resolves whether or not a client ever opened that
529
+ * stream, and storing before the first GET writes events nothing can reach —
530
+ * replay is keyed off Last-Event-Id, and a client that never held the stream
531
+ * was never handed an id to resume from.
532
+ */
533
+ shouldPersist(streamId, writer) {
534
+ if (this._eventStore === void 0) {
535
+ return false;
536
+ }
537
+ if (streamId !== this._standaloneSseStreamId) {
538
+ return true;
539
+ }
540
+ return this._standaloneStreamOpened || // A live writer means the stream is open now, which is stronger evidence
541
+ // than the latch. Belt and braces: it keeps a writer reaching this point
542
+ // without `trackStream` from producing an SSE event with no `id:`.
543
+ writer !== void 0 || this._replaysInFlight > 0;
544
+ }
452
545
  trackStream(streamId, writer) {
546
+ if (streamId === this._standaloneSseStreamId) {
547
+ this._standaloneStreamOpened = true;
548
+ }
453
549
  this._streamMapping.set(streamId, writer);
454
550
  const removeStreamIfCurrent = () => {
455
551
  if (this._streamMapping.get(streamId) !== writer) {
456
552
  return;
457
553
  }
458
554
  this._streamMapping.delete(streamId);
555
+ if (this._eventStore) {
556
+ return;
557
+ }
459
558
  for (const [requestId, mappedStreamId] of this._requestToStreamMapping) {
460
559
  if (mappedStreamId === streamId) {
461
560
  this._requestToStreamMapping.delete(requestId);
@@ -577,7 +676,7 @@ var EdgeFastMCP = class {
577
676
  */
578
677
  async #handleMcpRequest(request) {
579
678
  const acceptHeader = request.headers.get("accept");
580
- if (!_optionalChain([acceptHeader, 'optionalAccess', _22 => _22.includes, 'call', _23 => _23("application/json")]) && !_optionalChain([acceptHeader, 'optionalAccess', _24 => _24.includes, 'call', _25 => _25("text/event-stream")])) {
679
+ if (!_optionalChain([acceptHeader, 'optionalAccess', _26 => _26.includes, 'call', _27 => _27("application/json")]) && !_optionalChain([acceptHeader, 'optionalAccess', _28 => _28.includes, 'call', _29 => _29("text/event-stream")])) {
581
680
  return this.#errorResponse(
582
681
  406,
583
682
  -32e3,
@@ -585,7 +684,7 @@ var EdgeFastMCP = class {
585
684
  );
586
685
  }
587
686
  const contentType = request.headers.get("content-type");
588
- if (!_optionalChain([contentType, 'optionalAccess', _26 => _26.includes, 'call', _27 => _27("application/json")])) {
687
+ if (!_optionalChain([contentType, 'optionalAccess', _30 => _30.includes, 'call', _31 => _31("application/json")])) {
589
688
  return this.#errorResponse(
590
689
  415,
591
690
  -32e3,
@@ -630,7 +729,7 @@ var EdgeFastMCP = class {
630
729
  */
631
730
  async #handleMcpSseRequest(request) {
632
731
  const acceptHeader = request.headers.get("accept");
633
- if (!_optionalChain([acceptHeader, 'optionalAccess', _28 => _28.includes, 'call', _29 => _29("text/event-stream")])) {
732
+ if (!_optionalChain([acceptHeader, 'optionalAccess', _32 => _32.includes, 'call', _33 => _33("text/event-stream")])) {
634
733
  return this.#errorResponse(
635
734
  406,
636
735
  -32e3,
@@ -698,8 +797,8 @@ var EdgeFastMCP = class {
698
797
  * Handle prompts/get request
699
798
  */
700
799
  async #handlePromptsGet(id, params) {
701
- const promptName = _optionalChain([params, 'optionalAccess', _30 => _30.name]);
702
- const promptArgs = _optionalChain([params, 'optionalAccess', _31 => _31.arguments]);
800
+ const promptName = _optionalChain([params, 'optionalAccess', _34 => _34.name]);
801
+ const promptArgs = _optionalChain([params, 'optionalAccess', _35 => _35.arguments]);
703
802
  const prompt = this.#prompts.find((p) => p.name === promptName);
704
803
  if (!prompt) {
705
804
  return this.#rpcError(
@@ -761,7 +860,7 @@ var EdgeFastMCP = class {
761
860
  * Handle resources/read request
762
861
  */
763
862
  async #handleResourcesRead(id, params) {
764
- const uri = _optionalChain([params, 'optionalAccess', _32 => _32.uri]);
863
+ const uri = _optionalChain([params, 'optionalAccess', _36 => _36.uri]);
765
864
  const resource = this.#resources.find((r) => r.uri === uri);
766
865
  if (!resource) {
767
866
  return this.#rpcError(
@@ -790,8 +889,8 @@ var EdgeFastMCP = class {
790
889
  * Handle tools/call request
791
890
  */
792
891
  async #handleToolsCall(id, params) {
793
- const toolName = _optionalChain([params, 'optionalAccess', _33 => _33.name]);
794
- const toolArgs = _optionalChain([params, 'optionalAccess', _34 => _34.arguments]);
892
+ const toolName = _optionalChain([params, 'optionalAccess', _37 => _37.name]);
893
+ const toolArgs = _optionalChain([params, 'optionalAccess', _38 => _38.arguments]);
795
894
  const tool = this.#tools.find((t) => t.name === toolName);
796
895
  if (!tool) {
797
896
  return this.#rpcError(
@@ -814,7 +913,7 @@ var EdgeFastMCP = class {
814
913
  }
815
914
  if (parsed.issues) {
816
915
  const friendlyErrors = parsed.issues.map((issue) => {
817
- const path = _optionalChain([issue, 'access', _35 => _35.path, 'optionalAccess', _36 => _36.join, 'call', _37 => _37(".")]) || "root";
916
+ const path = _optionalChain([issue, 'access', _39 => _39.path, 'optionalAccess', _40 => _40.join, 'call', _41 => _41(".")]) || "root";
818
917
  return `${path}: ${issue.message}`;
819
918
  }).join(", ");
820
919
  return this.#rpcError(
@@ -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 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 private _requestToStreamMapping = new Map<RequestId, StreamId>();\n\n private _standaloneSseStreamId = \"_GET_stream\";\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.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 if (writer) {\n try {\n if (this._eventStore) {\n const eventId = await this._eventStore.storeEvent(\n streamId,\n message,\n );\n await this.writeSSEEventWithId(writer, eventId, message);\n } else {\n await this.writeSSEEvent(writer, message);\n }\n\n // Close the POST stream once all of its requests are answered\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 await writer.close();\n }\n }\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\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 * 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 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 // 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 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 const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n try {\n const streamId = await this._eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n this.trackStream(streamId, writer);\n } catch (error) {\n await writer.close();\n return this.createErrorResponse(500, -32000, `Replay failed: ${error}`);\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 * 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\n .map((id) => collector.responses.get(id))\n .filter((response) => response !== undefined),\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 private trackStream(\n streamId: StreamId,\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): void {\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 // Drop the routing entries that pointed at this stream, so a response\n // arriving after the client gave up is not looked up against a writer\n // that no longer exists. No-op for the standalone GET stream, which is\n // 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":"AAAA;ACyBA;AACE;AAEA;AAAA,6DACK;AAEP,4BAAqB;AACrB,oCAAiC;AACjC,0BAAkB;AAClB,qDAAgC;ADzBhC;AACA;AEDA;AACE;AACA;AACA;AACA;AACA;AAEA;AAAA;AA+DF,IAAM,qBAAA,EAAuB,EAAA,EAAI,KAAA,EAAO,IAAA;AAMjC,IAAM,iCAAA,YAAN,MAA4D;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,iBACQ,oBAAA,EAAsB,MAAA;AAAA,kBACtB,SAAA,EAAW,IAAI,WAAA,CAAY,EAAA;AAAA,EAC3B;AAAA,kBACA,wBAAA,kBAA0B,IAAI,GAAA,CAAmC,EAAA;AAAA,EACjE;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAOA,iBAAA,EAAmB,EAAA;AAAA,kBAEnB,wBAAA,kBAA0B,IAAI,GAAA,CAAyB,EAAA;AAAA,kBAEvD,uBAAA,EAAyB,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAQzB,wBAAA,EAA0B,MAAA;AAAA,kBAC1B,SAAA,EAAW,MAAA;AAAA,kBACX,eAAA,kBAAiB,IAAI,GAAA,CAG3B,EAAA;AAAA,EACM;AAAA,EAER,WAAA,CAAY,OAAA,EAAkD;AAC5D,IAAA,IAAA,CAAK,mBAAA,EAAqB,OAAA,CAAQ,kBAAA;AAClC,IAAA,IAAA,CAAK,oBAAA,mBAAsB,OAAA,CAAQ,kBAAA,UAAsB,OAAA;AACzD,IAAA,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,UAAA;AAC3B,IAAA,IAAA,CAAK,sBAAA,EAAwB,OAAA,CAAQ,oBAAA;AACrC,IAAA,IAAA,CAAK,iBAAA,EAAmB,OAAA,CAAQ,eAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,CAAA,EAAuB;AAC3B,IAAA,IAAA,CAAA,MAAW,OAAA,GAAU,IAAA,CAAK,cAAA,CAAe,MAAA,CAAO,CAAA,EAAG;AACjD,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,CAAO,KAAA,CAAM,CAAA;AAAA,MACrB,EAAA,UAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAA,CAAK,cAAA,CAAe,KAAA,CAAM,CAAA;AAC1B,IAAA,IAAA,CAAK,wBAAA,EAA0B,KAAA;AAC/B,IAAA,IAAA,CAAK,sBAAA,CAAuB,CAAA;AAC5B,IAAA,IAAA,CAAK,SAAA,EAAW,KAAA;AAChB,oBAAA,IAAA,mBAAK,OAAA,0BAAA,CAAU,GAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAA,CACJ,OAAA,EACA,UAAA,EACmB;AACnB,IAAA,MAAM,OAAA,EAAS,OAAA,CAAQ,MAAA;AAEvB,IAAA,GAAA,CAAI,OAAA,IAAW,MAAA,EAAQ;AACrB,MAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,OAAA,EAAS,UAAU,CAAA;AAAA,IACnD,EAAA,KAAA,GAAA,CAAW,OAAA,IAAW,KAAA,EAAO;AAC3B,MAAA,OAAO,IAAA,CAAK,gBAAA,CAAiB,OAAO,CAAA;AAAA,IACtC,EAAA,KAAA,GAAA,CAAW,OAAA,IAAW,QAAA,EAAU;AAC9B,MAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,OAAO,CAAA;AAAA,IACzC,EAAA,KAAO;AACL,MAAA,OAAO,IAAA,CAAK,wBAAA,CAAyB,CAAA;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAA,CACJ,OAAA,EACA,OAAA,EACe;AACf,IAAA,IAAI,UAAA,kBAAY,OAAA,6BAAS,kBAAA;AACzB,IAAA,MAAM,WAAA,EAAa,wCAAA,OAAyB,EAAA,GAAK,qCAAA,OAAsB,CAAA;AACvE,IAAA,GAAA,CAAI,UAAA,EAAY;AAEd,MAAA,UAAA,EAAY,OAAA,CAAQ,EAAA;AAAA,IACtB;AAEA,IAAA,MAAM,SAAA,EACJ,UAAA,IAAc,KAAA,EAAA,EACV,IAAA,CAAK,uBAAA,EACL,IAAA,CAAK,uBAAA,CAAwB,GAAA,CAAI,SAAS,CAAA;AAEhD,IAAA,GAAA,CAAI,QAAA,EAAU;AAGZ,MAAA,MAAM,UAAA,EAAY,IAAA,CAAK,uBAAA,CAAwB,GAAA,CAAI,QAAQ,CAAA;AAC3D,MAAA,GAAA,CAAI,SAAA,EAAW;AACb,QAAA,GAAA,CAAI,WAAA,GAAc,UAAA,IAAc,KAAA,CAAA,EAAW;AACzC,UAAA,SAAA,CAAU,SAAA,CAAU,GAAA,CAAI,SAAA,EAAW,OAAO,CAAA;AAC1C,UAAA,IAAA,CAAK,kBAAA,CAAmB,QAAA,EAAU,SAAS,CAAA;AAAA,QAC7C;AACA,QAAA,MAAA;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,EAAS,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,QAAQ,CAAA;AAI/C,MAAA,MAAM,MAAA,EAAQ,IAAA,CAAK,aAAA,CAAc,QAAA,EAAU,MAAM,EAAA,EAC7C,IAAA,CAAK,YAAA,EACL,KAAA,CAAA;AAEJ,MAAA,GAAA,CAAI,OAAA,GAAU,KAAA,EAAO;AACnB,QAAA,IAAI;AACF,UAAA,IAAI,OAAA;AACJ,UAAA,GAAA,CAAI,KAAA,EAAO;AACT,YAAA,QAAA,EAAU,MAAM,KAAA,CAAM,UAAA,CAAW,QAAA,EAAU,OAAO,CAAA;AAAA,UACpD;AACA,UAAA,GAAA,CAAI,MAAA,EAAQ;AACV,YAAA,GAAA,CAAI,QAAA,IAAY,KAAA,CAAA,EAAW;AACzB,cAAA,MAAM,IAAA,CAAK,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA;AAAA,YAC1C,EAAA,KAAO;AACL,cAAA,MAAM,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAAA,YACzD;AAAA,UACF;AAAA,QACF,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,0BAAA,IAAA,qBAAK,OAAA,0BAAA;AAAA,YACH,MAAA,WAAiB,MAAA,EAAQ,MAAA,EAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC;AAAA,UAC1D,GAAA;AAAA,QACF;AAQA,QAAA,GAAA,CAAI,UAAA,IAAc,KAAA,EAAA,GAAa,UAAA,EAAY;AACzC,UAAA,IAAA,CAAK,uBAAA,CAAwB,MAAA,CAAO,SAAS,CAAA;AAC7C,UAAA,MAAM,YAAA,EAAc,KAAA,CAAM,IAAA;AAAA,YACxB,IAAA,CAAK,uBAAA,CAAwB,MAAA,CAAO;AAAA,UACtC,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA;AACnB,UAAA,GAAA,CAAI,CAAC,WAAA,EAAa;AAChB,YAAA,IAAA,CAAK,cAAA,CAAe,MAAA,CAAO,QAAQ,CAAA;AACnC,YAAA,GAAA,CAAI,MAAA,EAAQ;AACV,cAAA,IAAI;AACF,gBAAA,MAAM,MAAA,CAAO,KAAA,CAAM,CAAA;AAAA,cACrB,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,gCAAA,IAAA,qBAAK,OAAA,0BAAA;AAAA,kBACH,MAAA,WAAiB,MAAA,EAAQ,MAAA,EAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC;AAAA,gBAC1D,GAAA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,CAAA,EAAuB;AAC3B,IAAA,GAAA,CAAI,IAAA,CAAK,QAAA,EAAU;AACjB,MAAA,MAAM,IAAI,KAAA,CAAM,2BAA2B,CAAA;AAAA,IAC7C;AACA,IAAA,IAAA,CAAK,SAAA,EAAW,IAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAA,CACN,MAAA,EACA,IAAA,EACA,OAAA,EACU;AACV,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,IAAA,CAAK,SAAA,CAAU;AAAA,QACb,KAAA,EAAO,EAAE,IAAA,EAAM,QAAQ,CAAA;AAAA,QACvB,EAAA,EAAI,IAAA;AAAA,QACJ,OAAA,EAAS;AAAA,MACX,CAAC,CAAA;AAAA,MACD;AAAA,QACE,OAAA,EAAS;AAAA,UACP,GAAG,IAAA,CAAK,kBAAA,CAAmB,CAAA;AAAA,UAC3B,cAAA,EAAgB;AAAA,QAClB,CAAA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,CAAA,EAA6C;AACnD,IAAA,MAAM,QAAA,EAAkC,CAAC,CAAA;AACzC,IAAA,GAAA,CAAI,IAAA,CAAK,SAAA,EAAW;AAClB,MAAA,OAAA,CAAQ,gBAAgB,EAAA,EAAI,IAAA,CAAK,SAAA;AAAA,IACnC;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAA,CAAoB,OAAA,EAAqC;AACrE,IAAA,MAAM,UAAA,EAAY,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,gBAAgB,CAAA;AAEtD,IAAA,GAAA,CAAI,IAAA,CAAK,kBAAA,EAAoB;AAC3B,MAAA,GAAA,CAAI,CAAC,SAAA,EAAW;AACd,QAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,UACV,GAAA;AAAA,UACA,CAAA,IAAA;AAAA,UACA;AAAA,QACF,CAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,IAAA,CAAK,UAAA,IAAc,SAAA,EAAW;AAChC,QAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,GAAA,EAAK,CAAA,KAAA,EAAQ,mBAAmB,CAAA;AAAA,MAClE;AAAA,IACF;AAGA,IAAA,IAAA,CAAA,MAAW,OAAA,GAAU,IAAA,CAAK,cAAA,CAAe,MAAA,CAAO,CAAA,EAAG;AACjD,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,CAAO,KAAA,CAAM,CAAA;AAAA,MACrB,EAAA,WAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAA,CAAK,cAAA,CAAe,KAAA,CAAM,CAAA;AAG1B,IAAA,IAAA,CAAK,wBAAA,EAA0B,KAAA;AAC/B,IAAA,IAAA,CAAK,sBAAA,CAAuB,CAAA;AAE5B,IAAA,sBAAM,IAAA,qBAAK,gBAAA,0BAAA,kBAAmB,IAAA,CAAK,SAAA,UAAa,IAAE,GAAA;AAClD,IAAA,IAAA,CAAK,UAAA,EAAY,KAAA,CAAA;AAEjB,IAAA,OAAO,IAAI,QAAA,CAAS,IAAA,EAAM;AAAA,MACxB,OAAA,EAAS,IAAA,CAAK,kBAAA,CAAmB,CAAA;AAAA,MACjC,MAAA,EAAQ;AAAA,IACV,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAA,CAAiB,OAAA,EAAqC;AAClE,IAAA,MAAM,aAAA,EAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AACjD,IAAA,GAAA,CAAI,iBAAC,YAAA,+BAAc,QAAA,qBAAS,mBAAmB,GAAA,EAAG;AAChD,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAGA,IAAA,MAAM,UAAA,EAAY,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,gBAAgB,CAAA;AACtD,IAAA,GAAA,CAAI,IAAA,CAAK,mBAAA,GAAsB,CAAC,SAAA,EAAW;AACzC,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,IAAA,CAAK,mBAAA,GAAsB,IAAA,CAAK,UAAA,IAAc,SAAA,EAAW;AAC3D,MAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,GAAA,EAAK,CAAA,KAAA,EAAQ,mBAAmB,CAAA;AAAA,IAClE;AAGA,IAAA,GAAA,CAAI,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,IAAA,CAAK,sBAAsB,CAAA,EAAG;AACxD,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,IAAA,CAAK,WAAA,EAAa;AACpB,MAAA,MAAM,YAAA,EAAc,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA;AACvD,MAAA,GAAA,CAAI,WAAA,EAAa;AACf,QAAA,OAAO,IAAA,CAAK,kBAAA,CAAmB,WAAW,CAAA;AAAA,MAC5C;AAAA,IACF;AAGA,IAAA,MAAM,EAAE,QAAA,EAAU,SAAS,EAAA,EAAI,IAAI,eAAA,CAA4B,CAAA;AAC/D,IAAA,MAAM,OAAA,EAAS,QAAA,CAAS,SAAA,CAAU,CAAA;AAClC,IAAA,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,sBAAA,EAAwB,MAAM,CAAA;AAEpD,IAAA,OAAO,IAAI,QAAA,CAAS,QAAA,EAAU;AAAA,MAC5B,OAAA,EAAS;AAAA,QACP,GAAG,IAAA,CAAK,kBAAA,CAAmB,CAAA;AAAA,QAC3B,eAAA,EAAiB,wBAAA;AAAA,QACjB,UAAA,EAAY,YAAA;AAAA,QACZ,cAAA,EAAgB;AAAA,MAClB,CAAA;AAAA,MACA,MAAA,EAAQ;AAAA,IACV,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAA,CACZ,OAAA,EACA,UAAA,EACmB;AAEnB,IAAA,MAAM,aAAA,EAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AACjD,IAAA,GAAA,CACE,iBAAC,YAAA,+BAAc,QAAA,qBAAS,kBAAkB,IAAA,GAC1C,iBAAC,YAAA,+BAAc,QAAA,qBAAS,mBAAmB,GAAA,EAC3C;AACA,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,EAAc,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AACtD,IAAA,GAAA,CAAI,iBAAC,WAAA,+BAAa,QAAA,qBAAS,kBAAkB,GAAA,EAAG;AAC9C,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAGA,IAAA,MAAM,cAAA,EAAgB,QAAA;AAAA,uBACpB,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,gBAAgB,CAAA,UAAK,KAAA;AAAA,MACzC;AAAA,IACF,CAAA;AACA,IAAA,GAAA,CAAI,cAAA,EAAgB,oBAAA,EAAsB;AACxC,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA,CAAA,wCAAA,EAA2C,oBAAoB,CAAA,MAAA;AAAA,MACjE,CAAA;AAAA,IACF;AAGA,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI;AACF,MAAA,WAAA,8BAAa,UAAA,gBAAe,MAAM,OAAA,CAAQ,IAAA,CAAK,GAAA;AAAA,IACjD,EAAA,WAAQ;AACN,MAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,GAAA,EAAK,CAAA,KAAA,EAAQ,2BAA2B,CAAA;AAAA,IAC1E;AAKA,IAAA,MAAM,QAAA,EAAU,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA;AACxC,IAAA,MAAM,aAAA,EAA0B,KAAA,CAAM,OAAA,CAAQ,UAAU,EAAA,EACpD,WAAA,EACA,CAAC,UAAU,CAAA;AAEf,IAAA,GAAA,CAAI,QAAA,GAAW,YAAA,CAAa,OAAA,IAAW,CAAA,EAAG;AACxC,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,KAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAGA,IAAA,MAAM,SAAA,EAA6B,CAAC,CAAA;AACpC,IAAA,IAAA,CAAA,MAAW,IAAA,GAAO,YAAA,EAAc;AAC9B,MAAA,MAAM,OAAA,EAAS,6BAAA,CAAqB,SAAA,CAAU,GAAG,CAAA;AACjD,MAAA,GAAA,CAAI,CAAC,MAAA,CAAO,OAAA,EAAS;AACnB,QAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,UACV,GAAA;AAAA,UACA,CAAA,KAAA;AAAA,UACA;AAAA,QACF,CAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA;AAAA,IAC3B;AAGA,IAAA,MAAM,iBAAA,EAAmB,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,gBAAgB,CAAA;AAC7D,IAAA,MAAM,eAAA,EAAiB,QAAA,CAAS,IAAA,CAAK,CAAC,GAAA,EAAA,GAAQ,0CAAA,GAAuB,CAAC,CAAA;AAGtE,IAAA,GAAA,CAAI,eAAA,GAAkB,gBAAA,EAAkB;AACtC,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,KAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,eAAA,GAAkB,QAAA,CAAS,OAAA,EAAS,CAAA,EAAG;AACzC,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,KAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,CAAC,eAAA,GAAkB,CAAC,iBAAA,GAAoB,IAAA,CAAK,kBAAA,EAAoB;AACnE,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,eAAA,GAAkB,IAAA,CAAK,kBAAA,EAAoB;AAC7C,MAAA,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,kBAAA,CAAmB,CAAA;AACzC,MAAA,sBAAM,IAAA,uBAAK,qBAAA,4BAAA,CAAwB,IAAA,CAAK,SAAS,GAAA;AAAA,IACnD,EAAA,KAAA,GAAA,CAAW,gBAAA,EAAkB;AAC3B,MAAA,GAAA,CAAI,IAAA,CAAK,mBAAA,GAAsB,IAAA,CAAK,UAAA,IAAc,gBAAA,EAAkB;AAClE,QAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,GAAA,EAAK,CAAA,KAAA,EAAQ,mBAAmB,CAAA;AAAA,MAClE;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,EAAa,QAAA,CAChB,MAAA,CAAO,CAAC,GAAA,EAAA,GAAQ,uCAAA,GAAoB,CAAC,CAAA,CACrC,GAAA,CAAI,CAAC,GAAA,EAAA,GAAQ,GAAA,CAAI,EAAE,CAAA;AACtB,IAAA,MAAM,gBAAA,EACJ,IAAA,CAAK,oBAAA,GACL,OAAA,iBAAQ,YAAA,+BAAc,QAAA,qBAAS,kBAAkB,GAAC,CAAA;AAIpD,IAAA,IAAI,aAAA;AACJ,IAAA,IAAI,WAAA;AACJ,IAAA,GAAA,CAAI,UAAA,CAAW,OAAA,EAAS,CAAA,EAAG;AAGzB,MAAA,MAAM,SAAA,EAAW,MAAA,CAAO,UAAA,CAAW,CAAA;AACnC,MAAA,IAAA,CAAA,MAAW,GAAA,GAAM,UAAA,EAAY;AAC3B,QAAA,IAAA,CAAK,uBAAA,CAAwB,GAAA,CAAI,EAAA,EAAI,QAAQ,CAAA;AAAA,MAC/C;AAEA,MAAA,GAAA,CAAI,eAAA,EAAiB;AACnB,QAAA,cAAA,EAAgB,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAA,GAAY;AACvC,UAAA,IAAA,CAAK,uBAAA,CAAwB,GAAA,CAAI,QAAA,EAAU;AAAA,YACzC,WAAA,EAAa,UAAA;AAAA,YACb,OAAA;AAAA,YACA,SAAA,kBAAW,IAAI,GAAA,CAAI;AAAA,UACrB,CAAC,CAAA;AAAA,QACH,CAAC,CAAA;AAAA,MACH,EAAA,KAAO;AACL,QAAA,MAAM,EAAE,QAAA,EAAU,SAAS,EAAA,EAAI,IAAI,eAAA,CAA4B,CAAA;AAC/D,QAAA,IAAA,CAAK,WAAA,CAAY,QAAA,EAAU,QAAA,CAAS,SAAA,CAAU,CAAC,CAAA;AAC/C,QAAA,YAAA,EAAc,QAAA;AAAA,MAChB;AAAA,IACF;AAKA,IAAA,IAAA,CAAA,MAAW,QAAA,GAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,UAAA,EAAY,oCAAA,CAA4B,SAAA,CAAU,OAAO,CAAA;AAC/D,MAAA,GAAA,CAAI,SAAA,CAAU,OAAA,EAAS;AACrB,QAAA,MAAM,IAAA,CAAK,uBAAA,CAAwB,SAAA,CAAU,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA;AAAA,MACpE;AAAA,IACF;AAGA,IAAA,IAAA,CAAA,MAAW,QAAA,GAAW,QAAA,EAAU;AAC9B,sBAAA,IAAA,uBAAK,SAAA,4BAAA,CAAY,OAAA,EAAS,EAAE,QAAA,EAAU,KAAA,EAAU,CAAC,GAAA;AAAA,IACnD;AAGA,IAAA,GAAA,CAAI,UAAA,CAAW,OAAA,IAAW,CAAA,EAAG;AAC3B,MAAA,OAAO,IAAI,QAAA,CAAS,IAAA,EAAM;AAAA,QACxB,OAAA,EAAS,IAAA,CAAK,kBAAA,CAAmB,CAAA;AAAA,QACjC,MAAA,EAAQ;AAAA,MACV,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,GAAA,CAAI,aAAA,EAAe;AAEjB,MAAA,MAAM,UAAA,EAAY,MAAM,aAAA;AAExB,MAAA,MAAM,aAAA,EAAe,IAAA,CAAK,SAAA,CAAU,QAAA,EAAU,UAAA,EAAY,SAAA,CAAU,CAAC,CAAC,CAAA;AAEtE,MAAA,OAAO,IAAI,QAAA,CAAS,YAAA,EAAc;AAAA,QAChC,OAAA,EAAS;AAAA,UACP,GAAG,IAAA,CAAK,kBAAA,CAAmB,CAAA;AAAA,UAC3B,cAAA,EAAgB;AAAA,QAClB,CAAA;AAAA,QACA,MAAA,EAAQ;AAAA,MACV,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,OAAO,IAAI,QAAA,kBAAS,WAAA,UAAe,MAAA,EAAM;AAAA,MACvC,OAAA,EAAS;AAAA,QACP,GAAG,IAAA,CAAK,kBAAA,CAAmB,CAAA;AAAA,QAC3B,eAAA,EAAiB,wBAAA;AAAA,QACjB,UAAA,EAAY,YAAA;AAAA,QACZ,cAAA,EAAgB;AAAA,MAClB,CAAA;AAAA,MACA,MAAA,EAAQ;AAAA,IACV,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBAAA,CAAmB,WAAA,EAAwC;AACvE,IAAA,GAAA,CAAI,CAAC,IAAA,CAAK,WAAA,EAAa;AACrB,MAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,QACV,GAAA;AAAA,QACA,CAAA,IAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,QAAA,EAAU,SAAS,EAAA,EAAI,IAAI,eAAA,CAA4B,CAAA;AAC/D,IAAA,MAAM,OAAA,EAAS,QAAA,CAAS,SAAA,CAAU,CAAA;AAElC,IAAA,IAAA,CAAK,iBAAA,GAAoB,CAAA;AACzB,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,EAAW,MAAM,IAAA,CAAK,WAAA,CAAY,iBAAA,CAAkB,WAAA,EAAa;AAAA,QACrE,IAAA,EAAM,MAAA,CAAO,OAAA,EAAS,OAAA,EAAA,GAAY;AAChC,UAAA,MAAM,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAAA,QACzD;AAAA,MACF,CAAC,CAAA;AACD,MAAA,IAAA,CAAK,WAAA,CAAY,QAAA,EAAU,MAAM,CAAA;AAAA,IACnC,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,MAAA,MAAM,MAAA,CAAO,KAAA,CAAM,CAAA;AACnB,MAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,GAAA,EAAK,CAAA,IAAA,EAAQ,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA;AACpE,IAAA;AACyB,MAAA;AAC3B,IAAA;AAE8B,IAAA;AACnB,MAAA;AACoB,QAAA;AACV,QAAA;AACL,QAAA;AACI,QAAA;AAClB,MAAA;AACQ,MAAA;AACT,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAK6C,EAAA;AACsB,IAAA;AACnE,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAW2E,EAAA;AACd,IAAA;AACY,IAAA;AACrE,MAAA;AACF,IAAA;AAE6C,IAAA;AACnB,IAAA;AACY,MAAA;AACnB,IAAA;AACF,IAAA;AACf,MAAA;AACF,IAAA;AAI+C,IAAA;AACZ,IAAA;AACvB,IAAA;AACN,MAAA;AACiB,QAAA;AACL,MAAA;AACT,wBAAA;AACqD,UAAA;AAC1D,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOuC,EAAA;AAC0B,IAAA;AACnD,MAAA;AAGL,QAAA;AACL,MAAA;AACF,IAAA;AACmC,IAAA;AACA,IAAA;AACrC,EAAA;AAAA;AAAA;AAAA;AAQQ,EAAA;AAC+B,IAAA;AACG,IAAA;AACK,MAAA;AAC5B,MAAA;AAEb,QAAA;AACF,MAAA;AACuB,MAAA;AACzB,IAAA;AAE4C,IAAA;AACJ,IAAA;AACA,MAAA;AACxC,IAAA;AAC2B,IAAA;AAC7B,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeW,EAAA;AAC2B,IAAA;AAC3B,MAAA;AACT,IAAA;AAE8C,IAAA;AACrC,MAAA;AACT,IAAA;AAGO,IAAA;AAAA;AAAA;AAKmB,IAAA;AAE5B,EAAA;AAKQ,EAAA;AAGwC,IAAA;AACb,MAAA;AACjC,IAAA;AACwC,IAAA;AACJ,IAAA;AACgB,MAAA;AAChD,QAAA;AACF,MAAA;AACmC,MAAA;AAKb,MAAA;AACpB,QAAA;AACF,MAAA;AAI+C,MAAA;AACZ,QAAA;AACc,UAAA;AAC/C,QAAA;AACF,MAAA;AACF,IAAA;AACoE,IAAA;AACtE,EAAA;AAAA;AAAA;AAAA;AAQiB,EAAA;AAC8B,IAAA;AAAA;AAAA;AACA,IAAA;AAC/C,EAAA;AAAA;AAAA;AAAA;AASiB,EAAA;AACY,IAAA;AAAkC,MAAA;AAAA;AAAA;AAChB,IAAA;AAC/C,EAAA;AACF;AF1O0E;AACA;ACzcjD;AACH,EAAA;AACpB,EAAA;AACA,EAAA;AACA,EAAA;AAC0B,EAAA;AACI,EAAA;AACR,EAAA;AACtB,EAAA;AAEyC,EAAA;AAClB,IAAA;AACG,IAAA;AACS,IAAA;AACE,IAAA;AAEjB,IAAA;AACpB,EAAA;AAAA;AAAA;AAAA;AAKoC,EAAA;AACT,IAAA;AAClB,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAK0C,EAAA;AACX,IAAA;AACtB,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAKgD,EAAA;AACb,IAAA;AAC1B,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAKiD,EAAA;AACb,IAAA;AACpC,EAAA;AAAA;AAAA;AAAA;AAKe,EAAA;AACD,IAAA;AACd,EAAA;AAAA;AAAA;AAAA;AAKwE,EAAA;AAC3D,IAAA;AACM,MAAA;AACU,QAAA;AACnB,QAAA;AACK,QAAA;AACV,MAAA;AACD,MAAA;AACgD,QAAA;AAC9C,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAKuD,EAAA;AAC9C,IAAA;AACL,MAAA;AACS,MAAA;AACD,MAAA;AACQ,QAAA;AAC6B,UAAA;AACI,UAAA;AACR,UAAA;AACvC,QAAA;AACiB,QAAA;AACL,QAAA;AACC,UAAA;AACG,UAAA;AAChB,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAK6D,EAAA;AAEV,IAAA;AAGhC,IAAA;AAEH,MAAA;AACV,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AAEsD,IAAA;AACN,IAAA;AAClC,MAAA;AACV,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AAGI,IAAA;AACA,IAAA;AACwB,MAAA;AACpB,IAAA;AAC6D,MAAA;AACrE,IAAA;AAGkC,IAAA;AACiB,IAAA;AAEb,IAAA;AACxB,MAAA;AACV,QAAA;AACU,QAAA;AACV,QAAA;AACF,MAAA;AACF,IAAA;AAEqC,IAAA;AAEL,IAAA;AACoB,MAAA;AACpC,MAAA;AACW,QAAA;AACzB,MAAA;AACF,IAAA;AAG4B,IAAA;AACe,MAAA;AAC3C,IAAA;AAEsE,IAAA;AAEpC,IAAA;AACvB,MAAA;AACS,QAAA;AAClB,MAAA;AACQ,MAAA;AACT,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAKgE,EAAA;AACb,IAAA;AACC,IAAA;AACpC,MAAA;AACV,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AAGY,IAAA;AACV,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAKuE,EAAA;AACxB,IAAA;AACuB,MAAA;AACpE,IAAA;AAEY,IAAA;AAOe,IAAA;AACb,MAAA;AACA,yBAAA;AACV,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AAG4C,IAAA;AACnC,MAAA;AACT,IAAA;AAEmB,IAAA;AACJ,IAAA;AACI,IAAA;AAEf,IAAA;AACc,MAAA;AACT,QAAA;AAC6B,UAAA;AAE7B,QAAA;AACqC,UAAA;AAErC,QAAA;AACqC,UAAA;AAErC,QAAA;AAC8B,UAAA;AAE9B,QAAA;AACgC,UAAA;AAEhC,QAAA;AACwC,UAAA;AAExC,QAAA;AACoC,UAAA;AAEpC,QAAA;AAC4B,UAAA;AAEjC,QAAA;AACiE,UAAA;AACnE,MAAA;AACc,IAAA;AACuC,MAAA;AACzC,MAAA;AACV,QAAA;AACA,QAAA;AAC4D,QAAA;AAC9D,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAQ2B,EAAA;AACE,IAAA;AACA,IAAA;AAEmC,IAAA;AACjD,IAAA;AACC,MAAA;AACV,QAAA;AACU,QAAA;AACqB,QAAA;AACjC,MAAA;AACF,IAAA;AAEI,IAAA;AAC+C,MAAA;AAGvB,MAAA;AAGnB,MAAA;AACL,QAAA;AACS,QAAA;AACU,QAAA;AACrB,MAAA;AACc,IAAA;AACF,MAAA;AACV,QAAA;AACU,QAAA;AACsD,QAAA;AAClE,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAKwD,EAAA;AAC/C,IAAA;AACL,MAAA;AACS,MAAA;AACD,MAAA;AAC6B,QAAA;AACpB,UAAA;AACE,UAAA;AACP,UAAA;AACR,QAAA;AACJ,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAK0D,EAAA;AACjD,IAAA;AACL,MAAA;AACS,MAAA;AACD,MAAA;AACiC,QAAA;AACtB,UAAA;AACH,UAAA;AACJ,UAAA;AACD,UAAA;AACP,QAAA;AACJ,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAQ2B,EAAA;AACL,IAAA;AACsC,IAAA;AAE3C,IAAA;AACD,MAAA;AACV,QAAA;AACU,QAAA;AACgB,QAAA;AAC5B,MAAA;AACF,IAAA;AAEI,IAAA;AACiC,MAAA;AAGR,MAAA;AAGpB,MAAA;AACL,QAAA;AACS,QAAA;AACqB,QAAA;AAChC,MAAA;AACc,IAAA;AACF,MAAA;AACV,QAAA;AACU,QAAA;AACwD,QAAA;AACpE,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAQ2B,EAAA;AACA,IAAA;AACA,IAAA;AAE+B,IAAA;AAC7C,IAAA;AACG,MAAA;AACV,QAAA;AACU,QAAA;AACiB,QAAA;AAC7B,MAAA;AACF,IAAA;AAEiC,IAAA;AAEZ,IAAA;AACf,MAAA;AAEA,MAAA;AAC2D,QAAA;AAC/C,MAAA;AACF,QAAA;AACV,UAAA;AACU,UAAA;AACyC,UAAA;AACrD,QAAA;AACF,MAAA;AAEmB,MAAA;AAEC,QAAA;AACwB,UAAA;AACN,UAAA;AAExB,QAAA;AAEA,QAAA;AACV,UAAA;AACU,UAAA;AACyC,UAAA;AACrD,QAAA;AACF,MAAA;AAEc,MAAA;AAChB,IAAA;AAEI,IAAA;AACoC,MAAA;AAKT,MAAA;AAGtB,MAAA;AACL,QAAA;AACS,QAAA;AACS,QAAA;AACpB,MAAA;AACc,IAAA;AACF,MAAA;AACV,QAAA;AACU,QAAA;AAC+C,QAAA;AAC3D,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAKsD,EAAA;AAC7C,IAAA;AACL,MAAA;AACS,MAAA;AACD,MAAA;AAC4B,QAAA;AACd,UAAA;AAEgB,UAAA;AAEvB,UAAA;AACX,QAAA;AACJ,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AASkB,EAAA;AACT,IAAA;AACkB,MAAA;AACvB,MAAA;AACS,MAAA;AACX,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAO2B,EAAA;AACrB,IAAA;AAGiD,MAAA;AAC1C,QAAA;AACyB,UAAA;AAChC,QAAA;AACF,MAAA;AAI8D,MAAA;AACrD,QAAA;AACgD,UAAA;AAIvD,QAAA;AACF,MAAA;AAGwB,MAAA;AAClB,IAAA;AACkB,MAAA;AAC1B,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAKqB,EAAA;AAE+B,IAAA;AAGH,IAAA;AACN,MAAA;AACxC,IAAA;AAG6C,IAAA;AACF,MAAA;AAC3C,IAAA;AAG+C,IAAA;AACL,MAAA;AAC1C,IAAA;AACH,EAAA;AACF;ADmV0E;AACA;AACA;AACA","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 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 * 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 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 const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n this._replaysInFlight += 1;\n try {\n const streamId = await this._eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n this.trackStream(streamId, writer);\n } catch (error) {\n await writer.close();\n return this.createErrorResponse(500, -32000, `Replay failed: ${error}`);\n } finally {\n this._replaysInFlight -= 1;\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 * JSON-mode POSTs are left alone: `_jsonResponseCollectors` owns their\n * settlement.\n */\n private async releaseCancelledRequest(requestId: RequestId): Promise<void> {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (streamId === undefined || this._jsonResponseCollectors.has(streamId)) {\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\n .map((id) => collector.responses.get(id))\n .filter((response) => response !== undefined),\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"]}
@@ -65,8 +65,23 @@ declare class WebStreamableHTTPServerTransport implements Transport {
65
65
  private _jsonResponseCollectors;
66
66
  private _onsessionclosed?;
67
67
  private _onsessioninitialized?;
68
+ /**
69
+ * Replays whose stream id is still being resolved. `replayEventsAfter` only
70
+ * reveals which stream it was replaying once it settles, so a standalone
71
+ * send during that window has nothing to test against; persist rather than
72
+ * drop, since over-storing for the length of a replay beats losing an event.
73
+ */
74
+ private _replaysInFlight;
68
75
  private _requestToStreamMapping;
69
76
  private _standaloneSseStreamId;
77
+ /**
78
+ * Whether a client has held the standalone GET stream during this session.
79
+ * Latched rather than read from `_streamMapping`, so persistence survives
80
+ * the disconnect window the store exists to cover while still telling a
81
+ * dropped stream apart from one that was never opened. Reset with the rest
82
+ * of the per-session state, since the next session starts with no stream.
83
+ */
84
+ private _standaloneStreamOpened;
70
85
  private _started;
71
86
  private _streamMapping;
72
87
  private sessionIdGenerator;
@@ -114,6 +129,16 @@ declare class WebStreamableHTTPServerTransport implements Transport {
114
129
  * Handles unsupported HTTP methods
115
130
  */
116
131
  private handleUnsupportedRequest;
132
+ /**
133
+ * Settle the routing state of a request the client cancelled, which will
134
+ * therefore never produce a response: the same drain `send()` performs once
135
+ * a response has been written, minus the response. Idempotent, so it is a
136
+ * no-op if the response won the race against the cancellation.
137
+ *
138
+ * JSON-mode POSTs are left alone: `_jsonResponseCollectors` owns their
139
+ * settlement.
140
+ */
141
+ private releaseCancelledRequest;
117
142
  /**
118
143
  * Drop the routing state left over once every stream is gone, answering any
119
144
  * POST still waiting on a JSON response with whatever arrived rather than
@@ -124,6 +149,17 @@ declare class WebStreamableHTTPServerTransport implements Transport {
124
149
  * Answer a JSON-mode POST once every request it carried has a response
125
150
  */
126
151
  private settleJsonResponse;
152
+ /**
153
+ * Whether an event addressed to `streamId` should go to the event store.
154
+ *
155
+ * Everything but the standalone stream is persisted whenever a store is
156
+ * configured: those ids exist only because their stream did. The standalone
157
+ * id is a constant, so it resolves whether or not a client ever opened that
158
+ * stream, and storing before the first GET writes events nothing can reach —
159
+ * replay is keyed off Last-Event-Id, and a client that never held the stream
160
+ * was never handed an id to resume from.
161
+ */
162
+ private shouldPersist;
127
163
  private trackStream;
128
164
  /**
129
165
  * Write an SSE event to the stream
@@ -65,8 +65,23 @@ declare class WebStreamableHTTPServerTransport implements Transport {
65
65
  private _jsonResponseCollectors;
66
66
  private _onsessionclosed?;
67
67
  private _onsessioninitialized?;
68
+ /**
69
+ * Replays whose stream id is still being resolved. `replayEventsAfter` only
70
+ * reveals which stream it was replaying once it settles, so a standalone
71
+ * send during that window has nothing to test against; persist rather than
72
+ * drop, since over-storing for the length of a replay beats losing an event.
73
+ */
74
+ private _replaysInFlight;
68
75
  private _requestToStreamMapping;
69
76
  private _standaloneSseStreamId;
77
+ /**
78
+ * Whether a client has held the standalone GET stream during this session.
79
+ * Latched rather than read from `_streamMapping`, so persistence survives
80
+ * the disconnect window the store exists to cover while still telling a
81
+ * dropped stream apart from one that was never opened. Reset with the rest
82
+ * of the per-session state, since the next session starts with no stream.
83
+ */
84
+ private _standaloneStreamOpened;
70
85
  private _started;
71
86
  private _streamMapping;
72
87
  private sessionIdGenerator;
@@ -114,6 +129,16 @@ declare class WebStreamableHTTPServerTransport implements Transport {
114
129
  * Handles unsupported HTTP methods
115
130
  */
116
131
  private handleUnsupportedRequest;
132
+ /**
133
+ * Settle the routing state of a request the client cancelled, which will
134
+ * therefore never produce a response: the same drain `send()` performs once
135
+ * a response has been written, minus the response. Idempotent, so it is a
136
+ * no-op if the response won the race against the cancellation.
137
+ *
138
+ * JSON-mode POSTs are left alone: `_jsonResponseCollectors` owns their
139
+ * settlement.
140
+ */
141
+ private releaseCancelledRequest;
117
142
  /**
118
143
  * Drop the routing state left over once every stream is gone, answering any
119
144
  * POST still waiting on a JSON response with whatever arrived rather than
@@ -124,6 +149,17 @@ declare class WebStreamableHTTPServerTransport implements Transport {
124
149
  * Answer a JSON-mode POST once every request it carried has a response
125
150
  */
126
151
  private settleJsonResponse;
152
+ /**
153
+ * Whether an event addressed to `streamId` should go to the event store.
154
+ *
155
+ * Everything but the standalone stream is persisted whenever a store is
156
+ * configured: those ids exist only because their stream did. The standalone
157
+ * id is a constant, so it resolves whether or not a client ever opened that
158
+ * stream, and storing before the first GET writes events nothing can reach —
159
+ * replay is keyed off Last-Event-Id, and a client that never held the stream
160
+ * was never handed an id to resume from.
161
+ */
162
+ private shouldPersist;
127
163
  private trackStream;
128
164
  /**
129
165
  * Write an SSE event to the stream
@@ -10,6 +10,7 @@ import { zodToJsonSchema } from "zod-to-json-schema";
10
10
 
11
11
  // src/edge/WebStreamableHTTPServerTransport.ts
12
12
  import {
13
+ CancelledNotificationSchema,
13
14
  isInitializeRequest,
14
15
  isJSONRPCError,
15
16
  isJSONRPCRequest,
@@ -28,8 +29,23 @@ var WebStreamableHTTPServerTransport = class {
28
29
  _jsonResponseCollectors = /* @__PURE__ */ new Map();
29
30
  _onsessionclosed;
30
31
  _onsessioninitialized;
32
+ /**
33
+ * Replays whose stream id is still being resolved. `replayEventsAfter` only
34
+ * reveals which stream it was replaying once it settles, so a standalone
35
+ * send during that window has nothing to test against; persist rather than
36
+ * drop, since over-storing for the length of a replay beats losing an event.
37
+ */
38
+ _replaysInFlight = 0;
31
39
  _requestToStreamMapping = /* @__PURE__ */ new Map();
32
40
  _standaloneSseStreamId = "_GET_stream";
41
+ /**
42
+ * Whether a client has held the standalone GET stream during this session.
43
+ * Latched rather than read from `_streamMapping`, so persistence survives
44
+ * the disconnect window the store exists to cover while still telling a
45
+ * dropped stream apart from one that was never opened. Reset with the rest
46
+ * of the per-session state, since the next session starts with no stream.
47
+ */
48
+ _standaloneStreamOpened = false;
33
49
  _started = false;
34
50
  _streamMapping = /* @__PURE__ */ new Map();
35
51
  sessionIdGenerator;
@@ -51,6 +67,7 @@ var WebStreamableHTTPServerTransport = class {
51
67
  }
52
68
  }
53
69
  this._streamMapping.clear();
70
+ this._standaloneStreamOpened = false;
54
71
  this.releasePendingRequests();
55
72
  this._started = false;
56
73
  this.onclose?.();
@@ -90,25 +107,18 @@ var WebStreamableHTTPServerTransport = class {
90
107
  return;
91
108
  }
92
109
  const writer = this._streamMapping.get(streamId);
93
- if (writer) {
110
+ const store = this.shouldPersist(streamId, writer) ? this._eventStore : void 0;
111
+ if (writer || store) {
94
112
  try {
95
- if (this._eventStore) {
96
- const eventId = await this._eventStore.storeEvent(
97
- streamId,
98
- message
99
- );
100
- await this.writeSSEEventWithId(writer, eventId, message);
101
- } else {
102
- await this.writeSSEEvent(writer, message);
113
+ let eventId;
114
+ if (store) {
115
+ eventId = await store.storeEvent(streamId, message);
103
116
  }
104
- if (requestId !== void 0 && isResponse) {
105
- this._requestToStreamMapping.delete(requestId);
106
- const streamInUse = Array.from(
107
- this._requestToStreamMapping.values()
108
- ).includes(streamId);
109
- if (!streamInUse) {
110
- this._streamMapping.delete(streamId);
111
- await writer.close();
117
+ if (writer) {
118
+ if (eventId === void 0) {
119
+ await this.writeSSEEvent(writer, message);
120
+ } else {
121
+ await this.writeSSEEventWithId(writer, eventId, message);
112
122
  }
113
123
  }
114
124
  } catch (error) {
@@ -116,6 +126,24 @@ var WebStreamableHTTPServerTransport = class {
116
126
  error instanceof Error ? error : new Error(String(error))
117
127
  );
118
128
  }
129
+ if (requestId !== void 0 && isResponse) {
130
+ this._requestToStreamMapping.delete(requestId);
131
+ const streamInUse = Array.from(
132
+ this._requestToStreamMapping.values()
133
+ ).includes(streamId);
134
+ if (!streamInUse) {
135
+ this._streamMapping.delete(streamId);
136
+ if (writer) {
137
+ try {
138
+ await writer.close();
139
+ } catch (error) {
140
+ this.onerror?.(
141
+ error instanceof Error ? error : new Error(String(error))
142
+ );
143
+ }
144
+ }
145
+ }
146
+ }
119
147
  }
120
148
  }
121
149
  }
@@ -178,6 +206,7 @@ var WebStreamableHTTPServerTransport = class {
178
206
  }
179
207
  }
180
208
  this._streamMapping.clear();
209
+ this._standaloneStreamOpened = false;
181
210
  this.releasePendingRequests();
182
211
  await this._onsessionclosed?.(this.sessionId ?? "");
183
212
  this.sessionId = void 0;
@@ -347,6 +376,12 @@ var WebStreamableHTTPServerTransport = class {
347
376
  sseReadable = readable;
348
377
  }
349
378
  }
379
+ for (const message of messages) {
380
+ const cancelled = CancelledNotificationSchema.safeParse(message);
381
+ if (cancelled.success) {
382
+ await this.releaseCancelledRequest(cancelled.data.params.requestId);
383
+ }
384
+ }
350
385
  for (const message of messages) {
351
386
  this.onmessage?.(message, { authInfo: void 0 });
352
387
  }
@@ -390,6 +425,7 @@ var WebStreamableHTTPServerTransport = class {
390
425
  }
391
426
  const { readable, writable } = new TransformStream();
392
427
  const writer = writable.getWriter();
428
+ this._replaysInFlight += 1;
393
429
  try {
394
430
  const streamId = await this._eventStore.replayEventsAfter(lastEventId, {
395
431
  send: async (eventId, message) => {
@@ -400,6 +436,8 @@ var WebStreamableHTTPServerTransport = class {
400
436
  } catch (error) {
401
437
  await writer.close();
402
438
  return this.createErrorResponse(500, -32e3, `Replay failed: ${error}`);
439
+ } finally {
440
+ this._replaysInFlight -= 1;
403
441
  }
404
442
  return new Response(readable, {
405
443
  headers: {
@@ -417,6 +455,39 @@ var WebStreamableHTTPServerTransport = class {
417
455
  handleUnsupportedRequest() {
418
456
  return this.createErrorResponse(405, -32e3, "Method not allowed");
419
457
  }
458
+ /**
459
+ * Settle the routing state of a request the client cancelled, which will
460
+ * therefore never produce a response: the same drain `send()` performs once
461
+ * a response has been written, minus the response. Idempotent, so it is a
462
+ * no-op if the response won the race against the cancellation.
463
+ *
464
+ * JSON-mode POSTs are left alone: `_jsonResponseCollectors` owns their
465
+ * settlement.
466
+ */
467
+ async releaseCancelledRequest(requestId) {
468
+ const streamId = this._requestToStreamMapping.get(requestId);
469
+ if (streamId === void 0 || this._jsonResponseCollectors.has(streamId)) {
470
+ return;
471
+ }
472
+ this._requestToStreamMapping.delete(requestId);
473
+ const streamInUse = Array.from(
474
+ this._requestToStreamMapping.values()
475
+ ).includes(streamId);
476
+ if (streamInUse) {
477
+ return;
478
+ }
479
+ const writer = this._streamMapping.get(streamId);
480
+ this._streamMapping.delete(streamId);
481
+ if (writer) {
482
+ try {
483
+ await writer.close();
484
+ } catch (error) {
485
+ this.onerror?.(
486
+ error instanceof Error ? error : new Error(String(error))
487
+ );
488
+ }
489
+ }
490
+ }
420
491
  /**
421
492
  * Drop the routing state left over once every stream is gone, answering any
422
493
  * POST still waiting on a JSON response with whatever arrived rather than
@@ -449,13 +520,41 @@ var WebStreamableHTTPServerTransport = class {
449
520
  }
450
521
  collector.resolve(responses);
451
522
  }
523
+ /**
524
+ * Whether an event addressed to `streamId` should go to the event store.
525
+ *
526
+ * Everything but the standalone stream is persisted whenever a store is
527
+ * configured: those ids exist only because their stream did. The standalone
528
+ * id is a constant, so it resolves whether or not a client ever opened that
529
+ * stream, and storing before the first GET writes events nothing can reach —
530
+ * replay is keyed off Last-Event-Id, and a client that never held the stream
531
+ * was never handed an id to resume from.
532
+ */
533
+ shouldPersist(streamId, writer) {
534
+ if (this._eventStore === void 0) {
535
+ return false;
536
+ }
537
+ if (streamId !== this._standaloneSseStreamId) {
538
+ return true;
539
+ }
540
+ return this._standaloneStreamOpened || // A live writer means the stream is open now, which is stronger evidence
541
+ // than the latch. Belt and braces: it keeps a writer reaching this point
542
+ // without `trackStream` from producing an SSE event with no `id:`.
543
+ writer !== void 0 || this._replaysInFlight > 0;
544
+ }
452
545
  trackStream(streamId, writer) {
546
+ if (streamId === this._standaloneSseStreamId) {
547
+ this._standaloneStreamOpened = true;
548
+ }
453
549
  this._streamMapping.set(streamId, writer);
454
550
  const removeStreamIfCurrent = () => {
455
551
  if (this._streamMapping.get(streamId) !== writer) {
456
552
  return;
457
553
  }
458
554
  this._streamMapping.delete(streamId);
555
+ if (this._eventStore) {
556
+ return;
557
+ }
459
558
  for (const [requestId, mappedStreamId] of this._requestToStreamMapping) {
460
559
  if (mappedStreamId === streamId) {
461
560
  this._requestToStreamMapping.delete(requestId);
@@ -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 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 private _requestToStreamMapping = new Map<RequestId, StreamId>();\n\n private _standaloneSseStreamId = \"_GET_stream\";\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.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 if (writer) {\n try {\n if (this._eventStore) {\n const eventId = await this._eventStore.storeEvent(\n streamId,\n message,\n );\n await this.writeSSEEventWithId(writer, eventId, message);\n } else {\n await this.writeSSEEvent(writer, message);\n }\n\n // Close the POST stream once all of its requests are answered\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 await writer.close();\n }\n }\n } catch (error) {\n this.onerror?.(\n error instanceof Error ? error : new Error(String(error)),\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 * 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 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 // 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 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 const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n try {\n const streamId = await this._eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n this.trackStream(streamId, writer);\n } catch (error) {\n await writer.close();\n return this.createErrorResponse(500, -32000, `Replay failed: ${error}`);\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 * 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\n .map((id) => collector.responses.get(id))\n .filter((response) => response !== undefined),\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 private trackStream(\n streamId: StreamId,\n writer: WritableStreamDefaultWriter<Uint8Array>,\n ): void {\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 // Drop the routing entries that pointed at this stream, so a response\n // arriving after the client gave up is not looked up against a writer\n // that no longer exists. No-op for the standalone GET stream, which is\n // 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":[]}
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 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 * 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 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 const { readable, writable } = new TransformStream<Uint8Array>();\n const writer = writable.getWriter();\n\n this._replaysInFlight += 1;\n try {\n const streamId = await this._eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId, message) => {\n await this.writeSSEEventWithId(writer, eventId, message);\n },\n });\n this.trackStream(streamId, writer);\n } catch (error) {\n await writer.close();\n return this.createErrorResponse(500, -32000, `Replay failed: ${error}`);\n } finally {\n this._replaysInFlight -= 1;\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 * JSON-mode POSTs are left alone: `_jsonResponseCollectors` owns their\n * settlement.\n */\n private async releaseCancelledRequest(requestId: RequestId): Promise<void> {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (streamId === undefined || this._jsonResponseCollectors.has(streamId)) {\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\n .map((id) => collector.responses.get(id))\n .filter((response) => response !== undefined),\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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastmcp",
3
- "version": "4.16.1",
3
+ "version": "4.16.3",
4
4
  "main": "dist/FastMCP.js",
5
5
  "scripts": {
6
6
  "build": "tsup",