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.
- package/dist/edge/index.cjs +137 -38
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.d.cts +36 -0
- package/dist/edge/index.d.ts +36 -0
- package/dist/edge/index.js +116 -17
- package/dist/edge/index.js.map +1 -1
- package/package.json +1 -1
package/dist/edge/index.cjs
CHANGED
|
@@ -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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
110
|
+
const store = this.shouldPersist(streamId, writer) ? this._eventStore : void 0;
|
|
111
|
+
if (writer || store) {
|
|
94
112
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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 (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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
|
-
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
702
|
-
const promptArgs = _optionalChain([params, 'optionalAccess',
|
|
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',
|
|
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',
|
|
794
|
-
const toolArgs = _optionalChain([params, 'optionalAccess',
|
|
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',
|
|
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(
|
package/dist/edge/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","../../src/edge/index.ts","../../src/edge/WebStreamableHTTPServerTransport.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","sourcesContent":[null,"/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n 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":"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","file":"/home/runner/work/fastmcp/fastmcp/dist/edge/index.cjs","sourcesContent":[null,"/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CancelledNotificationSchema,\n 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"]}
|
package/dist/edge/index.d.cts
CHANGED
|
@@ -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
|
package/dist/edge/index.d.ts
CHANGED
|
@@ -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
|
package/dist/edge/index.js
CHANGED
|
@@ -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
|
-
|
|
110
|
+
const store = this.shouldPersist(streamId, writer) ? this._eventStore : void 0;
|
|
111
|
+
if (writer || store) {
|
|
94
112
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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 (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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);
|
package/dist/edge/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/edge/index.ts","../../src/edge/WebStreamableHTTPServerTransport.ts"],"sourcesContent":["/**\n * FastMCP Edge Runtime Support\n *\n * This module provides edge runtime compatibility for FastMCP, enabling\n * deployment to Cloudflare Workers, Deno Deploy, and other edge platforms.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * import { EdgeFastMCP } from \"fastmcp/edge\";\n * import { z } from \"zod\";\n *\n * const server = new EdgeFastMCP({ name: \"MyMCP\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"hello\",\n * description: \"Say hello\",\n * parameters: z.object({ name: z.string() }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n *\n * export default server;\n * ```\n */\n\nimport {\n ErrorCode,\n JSONRPCMessage,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Hono } from \"hono\";\nimport { strictJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport { WebStreamableHTTPServerTransport } from \"./WebStreamableHTTPServerTransport.js\";\nexport type {\n EventStore,\n WebStreamableHTTPServerTransportOptions,\n} from \"./WebStreamableHTTPServerTransport.js\";\n\n/**\n * Options for EdgeFastMCP\n */\nexport interface EdgeFastMCPOptions {\n description?: string;\n logger?: EdgeLogger;\n /**\n * Base path for MCP endpoints (default: \"/mcp\")\n */\n mcpPath?: string;\n name: string;\n version: string;\n}\n\n/**\n * Type for edge runtime fetch handler\n */\nexport type EdgeFetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Logger interface for edge environments\n */\nexport interface EdgeLogger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\n/**\n * Prompt definition for EdgeFastMCP\n */\nexport interface EdgePrompt {\n arguments?: Array<{ description?: string; name: string; required?: boolean }>;\n description?: string;\n load: (args: Record<string, string>) => Promise<\n | {\n messages: Array<{\n content: { text: string; type: string };\n role: string;\n }>;\n }\n | string\n >;\n name: string;\n}\n\n/**\n * Resource definition for EdgeFastMCP\n */\nexport interface EdgeResource {\n description?: string;\n load: () => Promise<\n { blob?: string; mimeType?: string; text?: string } | string\n >;\n mimeType?: string;\n name: string;\n uri: string;\n}\n\n/**\n * Tool definition for EdgeFastMCP\n */\nexport interface EdgeTool<TParams = unknown> {\n description: string;\n execute: (params: TParams) => Promise<\n | {\n content: Array<{\n data?: string;\n mimeType?: string;\n text?: string;\n type: string;\n }>;\n }\n | string\n >;\n name: string;\n parameters?: StandardSchemaV1<TParams> | z.ZodType<TParams>;\n}\n\n/**\n * Edge-compatible FastMCP server for Cloudflare Workers, Deno, and Bun\n *\n * This is a simplified implementation optimized for stateless edge environments.\n * It uses web-standard APIs only (no Node.js dependencies).\n */\nexport class EdgeFastMCP {\n #honoApp = new Hono();\n #logger: EdgeLogger;\n #mcpPath: string;\n #name: string;\n #prompts: EdgePrompt[] = [];\n #resources: EdgeResource[] = [];\n #tools: EdgeTool[] = [];\n #version: string;\n\n constructor(options: EdgeFastMCPOptions) {\n this.#name = options.name;\n this.#version = options.version;\n this.#logger = options.logger ?? console;\n this.#mcpPath = options.mcpPath ?? \"/mcp\";\n\n this.#setupRoutes();\n }\n\n /**\n * Add a prompt to the server\n */\n addPrompt(prompt: EdgePrompt): this {\n this.#prompts.push(prompt);\n return this;\n }\n\n /**\n * Add a resource to the server\n */\n addResource(resource: EdgeResource): this {\n this.#resources.push(resource);\n return this;\n }\n\n /**\n * Add a tool to the server\n */\n addTool<TParams>(tool: EdgeTool<TParams>): this {\n this.#tools.push(tool as EdgeTool);\n return this;\n }\n\n /**\n * Handle an incoming request (main entry point for edge runtimes)\n */\n async fetch(request: Request): Promise<Response> {\n return this.#honoApp.fetch(request);\n }\n\n /**\n * Get the Hono app for adding custom routes\n */\n getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Create an error HTTP response\n */\n #errorResponse(status: number, code: number, message: string): Response {\n return new Response(\n JSON.stringify({\n error: { code, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: { \"Content-Type\": \"application/json\" },\n status,\n },\n );\n }\n\n /**\n * Handle initialize request\n */\n #handleInitialize(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n capabilities: {\n prompts: this.#prompts.length > 0 ? {} : undefined,\n resources: this.#resources.length > 0 ? {} : undefined,\n tools: this.#tools.length > 0 ? {} : undefined,\n },\n protocolVersion: LATEST_PROTOCOL_VERSION,\n serverInfo: {\n name: this.#name,\n version: this.#version,\n },\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle MCP POST requests\n */\n async #handleMcpRequest(request: Request): Promise<Response> {\n // Validate headers\n const acceptHeader = request.headers.get(\"accept\");\n if (\n !acceptHeader?.includes(\"application/json\") &&\n !acceptHeader?.includes(\"text/event-stream\")\n ) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept application/json or text/event-stream\",\n );\n }\n\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return this.#errorResponse(\n 415,\n -32000,\n \"Unsupported Media Type: Content-Type must be application/json\",\n );\n }\n\n // Parse request body\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return this.#errorResponse(400, -32700, \"Parse error: Invalid JSON\");\n }\n\n // Handle single or batch requests\n const isBatch = Array.isArray(body);\n const messages = Array.isArray(body) ? body : [body];\n\n if (isBatch && messages.length === 0) {\n return this.#errorResponse(\n 400,\n ErrorCode.InvalidRequest,\n \"Invalid Request: Batch must contain at least one message\",\n );\n }\n\n const responses: JSONRPCMessage[] = [];\n\n for (const message of messages) {\n const response = await this.#handleMessage(message);\n if (response) {\n responses.push(response);\n }\n }\n\n // Return appropriate response format\n if (responses.length === 0) {\n return new Response(null, { status: 202 });\n }\n\n const responseBody = JSON.stringify(isBatch ? responses : responses[0]);\n\n return new Response(responseBody, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n status: 200,\n });\n }\n\n /**\n * Handle SSE GET requests\n */\n async #handleMcpSseRequest(request: Request): Promise<Response> {\n const acceptHeader = request.headers.get(\"accept\");\n if (!acceptHeader?.includes(\"text/event-stream\")) {\n return this.#errorResponse(\n 406,\n -32000,\n \"Not Acceptable: Client must accept text/event-stream\",\n );\n }\n\n // In stateless mode, GET requests are not supported (no server-initiated messages)\n return this.#errorResponse(\n 405,\n -32000,\n \"Method Not Allowed: SSE streams not supported in stateless mode\",\n );\n }\n\n /**\n * Handle individual MCP messages\n */\n async #handleMessage(message: unknown): Promise<JSONRPCMessage | null> {\n if (!message || typeof message !== \"object\") {\n return this.#rpcError(null, -32700, \"Parse error: Invalid message\");\n }\n\n const msg = message as {\n id?: number | string;\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n\n if (msg.jsonrpc !== \"2.0\") {\n return this.#rpcError(\n msg.id ?? null,\n -32600,\n \"Invalid Request: jsonrpc must be 2.0\",\n );\n }\n\n // Handle notifications (no response expected)\n if (!(\"id\" in msg) || msg.id === undefined) {\n return null;\n }\n\n const method = msg.method;\n const id = msg.id;\n const params = msg.params as Record<string, unknown> | undefined;\n\n try {\n switch (method) {\n case \"initialize\":\n return this.#handleInitialize(id);\n\n case \"ping\":\n return { id, jsonrpc: \"2.0\", result: {} } as JSONRPCMessage;\n\n case \"prompts/get\":\n return this.#handlePromptsGet(id, params);\n\n case \"prompts/list\":\n return this.#handlePromptsList(id);\n\n case \"resources/list\":\n return this.#handleResourcesList(id);\n\n case \"resources/read\":\n return this.#handleResourcesRead(id, params);\n\n case \"tools/call\":\n return this.#handleToolsCall(id, params);\n\n case \"tools/list\":\n return this.#handleToolsList(id);\n\n default:\n return this.#rpcError(id, -32601, `Method not found: ${method}`);\n }\n } catch (error) {\n this.#logger.error(`Error handling ${method}:`, error);\n return this.#rpcError(\n id,\n -32603,\n `Internal error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/get request\n */\n async #handlePromptsGet(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const promptName = params?.name as string;\n const promptArgs = params?.arguments as Record<string, string> | undefined;\n\n const prompt = this.#prompts.find((p) => p.name === promptName);\n if (!prompt) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Prompt not found: ${promptName}`,\n );\n }\n\n try {\n const result = await prompt.load(promptArgs ?? {});\n const messages =\n typeof result === \"string\"\n ? [{ content: { text: result, type: \"text\" }, role: \"user\" }]\n : result.messages;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { messages },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Prompt load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle prompts/list request\n */\n #handlePromptsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n prompts: this.#prompts.map((p) => ({\n arguments: p.arguments,\n description: p.description,\n name: p.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/list request\n */\n #handleResourcesList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n resources: this.#resources.map((r) => ({\n description: r.description,\n mimeType: r.mimeType,\n name: r.name,\n uri: r.uri,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Handle resources/read request\n */\n async #handleResourcesRead(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const uri = params?.uri as string;\n const resource = this.#resources.find((r) => r.uri === uri);\n\n if (!resource) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Resource not found: ${uri}`,\n );\n }\n\n try {\n const result = await resource.load();\n const content =\n typeof result === \"string\"\n ? { mimeType: resource.mimeType ?? \"text/plain\", text: result, uri }\n : { uri, ...result };\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { contents: [content] },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Resource load failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/call request\n */\n async #handleToolsCall(\n id: number | string,\n params?: Record<string, unknown>,\n ): Promise<JSONRPCMessage> {\n const toolName = params?.name as string;\n const toolArgs = params?.arguments as Record<string, unknown> | undefined;\n\n const tool = this.#tools.find((t) => t.name === toolName);\n if (!tool) {\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool not found: ${toolName}`,\n );\n }\n\n let args: unknown = toolArgs ?? {};\n\n if (tool.parameters) {\n let parsed: StandardSchemaV1.Result<unknown>;\n\n try {\n parsed = await tool.parameters[\"~standard\"].validate(toolArgs);\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool '${toolName}' parameter validation failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (parsed.issues) {\n const friendlyErrors = parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n return this.#rpcError(\n id,\n ErrorCode.InvalidParams,\n `Tool '${toolName}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n try {\n const result = await tool.execute(args);\n\n // Normalize result to content array\n const content =\n typeof result === \"string\"\n ? [{ text: result, type: \"text\" }]\n : result.content;\n\n return {\n id,\n jsonrpc: \"2.0\",\n result: { content },\n } as JSONRPCMessage;\n } catch (error) {\n return this.#rpcError(\n id,\n ErrorCode.InternalError,\n `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Handle tools/list request\n */\n #handleToolsList(id: number | string): JSONRPCMessage {\n return {\n id,\n jsonrpc: \"2.0\",\n result: {\n tools: this.#tools.map((tool) => ({\n description: tool.description,\n inputSchema: tool.parameters\n ? this.#schemaToJsonSchema(tool.parameters)\n : { type: \"object\" },\n name: tool.name,\n })),\n },\n } as JSONRPCMessage;\n }\n\n /**\n * Create an RPC error message\n */\n #rpcError(\n id: null | number | string,\n code: number,\n message: string,\n ): JSONRPCMessage {\n return {\n error: { code, message },\n id,\n jsonrpc: \"2.0\",\n } as JSONRPCMessage;\n }\n\n /**\n * Convert schema to JSON Schema\n */\n #schemaToJsonSchema(\n schema: StandardSchemaV1 | z.ZodType,\n ): Record<string, unknown> {\n try {\n // Zod 4+: use native toJSONSchema if available\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (typeof (z as any).toJSONSchema === \"function\") {\n return strictJsonSchema(\n (z as any).toJSONSchema(schema) as Record<string, unknown>,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // Zod 3 fallback: use zod-to-json-schema\n /* eslint-disable @typescript-eslint/no-explicit-any */\n if (\"_def\" in (schema as any) || schema instanceof z.ZodType) {\n return strictJsonSchema(\n zodToJsonSchema(schema as any, { target: \"openApi3\" }) as Record<\n string,\n unknown\n >,\n ) as Record<string, unknown>;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n // For StandardSchema, fall back to a generic object schema\n return { type: \"object\" };\n } catch {\n return { type: \"object\" };\n }\n }\n\n /**\n * Set up MCP and health routes\n */\n #setupRoutes(): void {\n // Health endpoint\n this.#honoApp.get(\"/health\", (c) => c.text(\"✓ Ok\"));\n\n // MCP endpoint - handles all MCP protocol messages\n this.#honoApp.post(this.#mcpPath, async (c) => {\n return this.#handleMcpRequest(c.req.raw);\n });\n\n // MCP GET endpoint for SSE streams (server-initiated messages)\n this.#honoApp.get(this.#mcpPath, async (c) => {\n return this.#handleMcpSseRequest(c.req.raw);\n });\n\n // MCP DELETE endpoint for session termination\n this.#honoApp.delete(this.#mcpPath, async () => {\n return new Response(null, { status: 204 });\n });\n }\n}\n","/**\n * Web-standard Streamable HTTP Server Transport for MCP\n *\n * This transport implements the MCP Streamable HTTP specification using\n * web standard APIs (Request, Response, TransformStream) for compatibility\n * with edge runtimes like Cloudflare Workers, Deno, and Bun.\n */\n\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n 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":[]}
|