agents 0.0.0-2cc0f02 → 0.0.0-2e73791
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/README.md +126 -3
- package/dist/ai-chat-agent.d.ts +231 -22
- package/dist/ai-chat-agent.js +691 -121
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/{ai-chat-v5-migration-gdyLiTd8.js → ai-chat-v5-migration-DguhuLKF.js} +2 -2
- package/dist/{ai-chat-v5-migration-gdyLiTd8.js.map → ai-chat-v5-migration-DguhuLKF.js.map} +1 -1
- package/dist/ai-chat-v5-migration.js +1 -1
- package/dist/ai-react.d.ts +145 -16
- package/dist/ai-react.js +389 -75
- package/dist/ai-react.js.map +1 -1
- package/dist/{ai-types-B0GBFDwi.js → ai-types-DEtF_8Km.js} +10 -2
- package/dist/ai-types-DEtF_8Km.js.map +1 -0
- package/dist/{ai-types-BWW4umHY.d.ts → ai-types-U8lYA0o8.d.ts} +41 -9
- package/dist/ai-types.d.ts +4 -4
- package/dist/ai-types.js +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +28 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client-Cfw92Wb_.d.ts +834 -0
- package/dist/{client-CmMi85Sj.d.ts → client-ClORm6f0.d.ts} +10 -10
- package/dist/{client-zS-OCVJA.js → client-DjTPRM8-.js} +3 -3
- package/dist/{client-zS-OCVJA.js.map → client-DjTPRM8-.js.map} +1 -1
- package/dist/client-QZa2Rq0l.js +1105 -0
- package/dist/client-QZa2Rq0l.js.map +1 -0
- package/dist/client.d.ts +8 -8
- package/dist/client.js +2 -2
- package/dist/codemode/ai.js +7 -6
- package/dist/codemode/ai.js.map +1 -1
- package/dist/context-BkKbAa1R.js +8 -0
- package/dist/context-BkKbAa1R.js.map +1 -0
- package/dist/context-_sPQqJWv.d.ts +24 -0
- package/dist/context.d.ts +6 -0
- package/dist/context.js +3 -0
- package/dist/{do-oauth-client-provider-CCwGwnrA.d.ts → do-oauth-client-provider-B-ryFIPr.d.ts} +21 -6
- package/dist/{do-oauth-client-provider-B2jr6UNq.js → do-oauth-client-provider-B1fVIshX.js} +71 -9
- package/dist/do-oauth-client-provider-B1fVIshX.js.map +1 -0
- package/dist/{index-W4JUkafc.d.ts → index-CyDpAVHZ.d.ts} +7 -3
- package/dist/{index-DWcUTPtX.d.ts → index-xIS9I1YX.d.ts} +83 -65
- package/dist/index.d.ts +36 -36
- package/dist/index.js +6 -5
- package/dist/mcp/client.d.ts +4 -4
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/do-oauth-client-provider.js +1 -1
- package/dist/mcp/index.d.ts +140 -12
- package/dist/mcp/index.js +636 -41
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.js +10 -6
- package/dist/mcp/x402.js.map +1 -1
- package/dist/{mcp-BEwaCsxO.d.ts → mcp-CzbSsLfc.d.ts} +2 -2
- package/dist/observability/index.d.ts +2 -2
- package/dist/observability/index.js +6 -5
- package/dist/{react-B8BT6PYZ.d.ts → react-ElpIreHg.d.ts} +35 -17
- package/dist/react.d.ts +15 -10
- package/dist/react.js +57 -57
- package/dist/react.js.map +1 -1
- package/dist/{serializable-gtr9YMhp.d.ts → serializable-C4GLimgv.d.ts} +8 -3
- package/dist/serializable.d.ts +5 -5
- package/dist/{src-C9xZ0CrH.js → src-BZDh910Z.js} +130 -128
- package/dist/src-BZDh910Z.js.map +1 -0
- package/package.json +61 -44
- package/dist/ai-types-B0GBFDwi.js.map +0 -1
- package/dist/client-C-u-lCFT.d.ts +0 -5311
- package/dist/client-WbaRgKYN.js +0 -788
- package/dist/client-WbaRgKYN.js.map +0 -1
- package/dist/do-oauth-client-provider-B2jr6UNq.js.map +0 -1
- package/dist/src-C9xZ0CrH.js.map +0 -1
- package/src/index.ts +0 -2031
package/dist/mcp/index.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { MessageType } from "../ai-types-
|
|
3
|
-
import "../client-
|
|
4
|
-
import "../
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
1
|
+
import "../context-BkKbAa1R.js";
|
|
2
|
+
import { t as MessageType } from "../ai-types-DEtF_8Km.js";
|
|
3
|
+
import "../client-DjTPRM8-.js";
|
|
4
|
+
import "../client-QZa2Rq0l.js";
|
|
5
|
+
import "../do-oauth-client-provider-B1fVIshX.js";
|
|
6
|
+
import { c as getCurrentAgent, s as getAgentByName, t as Agent } from "../src-BZDh910Z.js";
|
|
7
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
9
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
10
|
+
import { ElicitRequestSchema, InitializeRequestSchema, JSONRPCMessageSchema, SUPPORTED_PROTOCOL_VERSIONS, isInitializeRequest, isJSONRPCError, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResponse } from "@modelcontextprotocol/sdk/types.js";
|
|
7
11
|
|
|
8
12
|
//#region src/mcp/utils.ts
|
|
9
13
|
/**
|
|
@@ -20,7 +24,7 @@ const MCP_HTTP_METHOD_HEADER = "cf-mcp-method";
|
|
|
20
24
|
*/
|
|
21
25
|
const MCP_MESSAGE_HEADER = "cf-mcp-message";
|
|
22
26
|
const MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024;
|
|
23
|
-
const createStreamingHttpHandler = (basePath, namespace,
|
|
27
|
+
const createStreamingHttpHandler = (basePath, namespace, options = {}) => {
|
|
24
28
|
let pathname = basePath;
|
|
25
29
|
if (basePath === "/") pathname = "/*";
|
|
26
30
|
const basePattern = new URLPattern({ pathname });
|
|
@@ -129,7 +133,10 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
129
133
|
return new Response(body$1, { status: 400 });
|
|
130
134
|
}
|
|
131
135
|
sessionId = sessionId ?? namespace.newUniqueId().toString();
|
|
132
|
-
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
136
|
+
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
137
|
+
props: ctx.props,
|
|
138
|
+
jurisdiction: options.jurisdiction
|
|
139
|
+
});
|
|
133
140
|
const isInitialized = await agent.getInitializeRequest();
|
|
134
141
|
if (maybeInitializeRequest) await agent.setInitializeRequest(maybeInitializeRequest);
|
|
135
142
|
else if (!isInitialized) {
|
|
@@ -204,7 +211,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
204
211
|
if (messages.every((msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(msg))) {
|
|
205
212
|
ws.close();
|
|
206
213
|
return new Response(null, {
|
|
207
|
-
headers: corsHeaders(request, corsOptions),
|
|
214
|
+
headers: corsHeaders(request, options.corsOptions),
|
|
208
215
|
status: 202
|
|
209
216
|
});
|
|
210
217
|
}
|
|
@@ -214,7 +221,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
214
221
|
Connection: "keep-alive",
|
|
215
222
|
"Content-Type": "text/event-stream",
|
|
216
223
|
"mcp-session-id": sessionId,
|
|
217
|
-
...corsHeaders(request, corsOptions)
|
|
224
|
+
...corsHeaders(request, options.corsOptions)
|
|
218
225
|
},
|
|
219
226
|
status: 200
|
|
220
227
|
});
|
|
@@ -242,7 +249,10 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
242
249
|
const { readable, writable } = new TransformStream();
|
|
243
250
|
const writer = writable.getWriter();
|
|
244
251
|
const encoder = new TextEncoder();
|
|
245
|
-
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
252
|
+
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
253
|
+
props: ctx.props,
|
|
254
|
+
jurisdiction: options.jurisdiction
|
|
255
|
+
});
|
|
246
256
|
if (!await agent.getInitializeRequest()) return new Response(JSON.stringify({
|
|
247
257
|
jsonrpc: "2.0",
|
|
248
258
|
error: {
|
|
@@ -291,7 +301,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
291
301
|
Connection: "keep-alive",
|
|
292
302
|
"Content-Type": "text/event-stream",
|
|
293
303
|
"mcp-session-id": sessionId,
|
|
294
|
-
...corsHeaders(request, corsOptions)
|
|
304
|
+
...corsHeaders(request, options.corsOptions)
|
|
295
305
|
},
|
|
296
306
|
status: 200
|
|
297
307
|
});
|
|
@@ -306,9 +316,9 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
306
316
|
id: null
|
|
307
317
|
}), {
|
|
308
318
|
status: 400,
|
|
309
|
-
headers: corsHeaders(request, corsOptions)
|
|
319
|
+
headers: corsHeaders(request, options.corsOptions)
|
|
310
320
|
});
|
|
311
|
-
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}
|
|
321
|
+
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, { jurisdiction: options.jurisdiction });
|
|
312
322
|
if (!await agent.getInitializeRequest()) return new Response(JSON.stringify({
|
|
313
323
|
jsonrpc: "2.0",
|
|
314
324
|
error: {
|
|
@@ -318,12 +328,12 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
318
328
|
id: null
|
|
319
329
|
}), {
|
|
320
330
|
status: 404,
|
|
321
|
-
headers: corsHeaders(request, corsOptions)
|
|
331
|
+
headers: corsHeaders(request, options.corsOptions)
|
|
322
332
|
});
|
|
323
333
|
ctx.waitUntil(agent.destroy().catch(() => {}));
|
|
324
334
|
return new Response(null, {
|
|
325
335
|
status: 204,
|
|
326
|
-
headers: corsHeaders(request, corsOptions)
|
|
336
|
+
headers: corsHeaders(request, options.corsOptions)
|
|
327
337
|
});
|
|
328
338
|
}
|
|
329
339
|
}
|
|
@@ -338,7 +348,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
338
348
|
return new Response(body, { status: 404 });
|
|
339
349
|
};
|
|
340
350
|
};
|
|
341
|
-
const createLegacySseHandler = (basePath, namespace,
|
|
351
|
+
const createLegacySseHandler = (basePath, namespace, options = {}) => {
|
|
342
352
|
let pathname = basePath;
|
|
343
353
|
if (basePath === "/") pathname = "/*";
|
|
344
354
|
const basePattern = new URLPattern({ pathname });
|
|
@@ -355,7 +365,10 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
355
365
|
endpointUrl.searchParams.set("sessionId", sessionId);
|
|
356
366
|
const endpointMessage = `event: endpoint\ndata: ${endpointUrl.pathname + endpointUrl.search + endpointUrl.hash}\n\n`;
|
|
357
367
|
writer.write(encoder.encode(endpointMessage));
|
|
358
|
-
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
368
|
+
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
369
|
+
props: ctx.props,
|
|
370
|
+
jurisdiction: options.jurisdiction
|
|
371
|
+
});
|
|
359
372
|
const existingHeaders = {};
|
|
360
373
|
request.headers.forEach((value, key) => {
|
|
361
374
|
existingHeaders[key] = value;
|
|
@@ -407,7 +420,7 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
407
420
|
"Cache-Control": "no-cache",
|
|
408
421
|
Connection: "keep-alive",
|
|
409
422
|
"Content-Type": "text/event-stream",
|
|
410
|
-
...corsHeaders(request, corsOptions)
|
|
423
|
+
...corsHeaders(request, options.corsOptions)
|
|
411
424
|
} });
|
|
412
425
|
}
|
|
413
426
|
if (request.method === "POST" && messagePattern.test(url)) {
|
|
@@ -417,15 +430,19 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
417
430
|
if (!contentType.includes("application/json")) return new Response(`Unsupported content-type: ${contentType}`, { status: 400 });
|
|
418
431
|
const contentLength = Number.parseInt(request.headers.get("content-length") || "0", 10);
|
|
419
432
|
if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) return new Response(`Request body too large: ${contentLength} bytes`, { status: 400 });
|
|
420
|
-
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
433
|
+
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
434
|
+
props: ctx.props,
|
|
435
|
+
jurisdiction: options.jurisdiction
|
|
436
|
+
});
|
|
421
437
|
const messageBody = await request.json();
|
|
422
|
-
const
|
|
438
|
+
const extraInfo = { requestInfo: { headers: Object.fromEntries(request.headers.entries()) } };
|
|
439
|
+
const error = await agent.onSSEMcpMessage(sessionId, messageBody, extraInfo);
|
|
423
440
|
if (error) return new Response(error.message, {
|
|
424
441
|
headers: {
|
|
425
442
|
"Cache-Control": "no-cache",
|
|
426
443
|
Connection: "keep-alive",
|
|
427
444
|
"Content-Type": "text/event-stream",
|
|
428
|
-
...corsHeaders(request, corsOptions)
|
|
445
|
+
...corsHeaders(request, options.corsOptions)
|
|
429
446
|
},
|
|
430
447
|
status: 400
|
|
431
448
|
});
|
|
@@ -434,7 +451,7 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
434
451
|
"Cache-Control": "no-cache",
|
|
435
452
|
Connection: "keep-alive",
|
|
436
453
|
"Content-Type": "text/event-stream",
|
|
437
|
-
...corsHeaders(request, corsOptions)
|
|
454
|
+
...corsHeaders(request, options.corsOptions)
|
|
438
455
|
},
|
|
439
456
|
status: 202
|
|
440
457
|
});
|
|
@@ -463,9 +480,12 @@ function isDurableObjectNamespace(namespace) {
|
|
|
463
480
|
//#endregion
|
|
464
481
|
//#region src/mcp/transport.ts
|
|
465
482
|
var McpSSETransport = class {
|
|
466
|
-
constructor(
|
|
483
|
+
constructor() {
|
|
467
484
|
this._started = false;
|
|
468
|
-
|
|
485
|
+
const { agent } = getCurrentAgent();
|
|
486
|
+
if (!agent) throw new Error("McpAgent was not found in Transport constructor");
|
|
487
|
+
this.sessionId = agent.getSessionId();
|
|
488
|
+
this._getWebSocket = () => agent.getWebSocket();
|
|
469
489
|
}
|
|
470
490
|
async start() {
|
|
471
491
|
if (this._started) throw new Error("Transport already started");
|
|
@@ -573,19 +593,35 @@ var StreamableHTTPServerTransport = class {
|
|
|
573
593
|
if (Array.isArray(rawMessage)) messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));
|
|
574
594
|
else messages = [JSONRPCMessageSchema.parse(rawMessage)];
|
|
575
595
|
const hasRequests = messages.some(isJSONRPCRequest);
|
|
576
|
-
if (!hasRequests) for (const message of messages)
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
596
|
+
if (!hasRequests) for (const message of messages) {
|
|
597
|
+
if (this.messageInterceptor) {
|
|
598
|
+
if (await this.messageInterceptor(message, {
|
|
599
|
+
authInfo,
|
|
600
|
+
requestInfo
|
|
601
|
+
})) continue;
|
|
602
|
+
}
|
|
603
|
+
this.onmessage?.(message, {
|
|
604
|
+
authInfo,
|
|
605
|
+
requestInfo
|
|
606
|
+
});
|
|
607
|
+
}
|
|
580
608
|
else if (hasRequests) {
|
|
581
609
|
const { connection } = getCurrentAgent();
|
|
582
610
|
if (!connection) throw new Error("Connection was not found in handlePostRequest");
|
|
583
611
|
const requestIds = messages.filter(isJSONRPCRequest).map((message) => message.id);
|
|
584
612
|
connection.setState({ requestIds });
|
|
585
|
-
for (const message of messages)
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
613
|
+
for (const message of messages) {
|
|
614
|
+
if (this.messageInterceptor) {
|
|
615
|
+
if (await this.messageInterceptor(message, {
|
|
616
|
+
authInfo,
|
|
617
|
+
requestInfo
|
|
618
|
+
})) continue;
|
|
619
|
+
}
|
|
620
|
+
this.onmessage?.(message, {
|
|
621
|
+
authInfo,
|
|
622
|
+
requestInfo
|
|
623
|
+
});
|
|
624
|
+
}
|
|
589
625
|
}
|
|
590
626
|
}
|
|
591
627
|
async close() {
|
|
@@ -624,6 +660,553 @@ var StreamableHTTPServerTransport = class {
|
|
|
624
660
|
}
|
|
625
661
|
};
|
|
626
662
|
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region src/mcp/client-transports.ts
|
|
665
|
+
/**
|
|
666
|
+
* Deprecated transport wrappers
|
|
667
|
+
*/
|
|
668
|
+
let didWarnAboutSSEEdgeClientTransport = false;
|
|
669
|
+
/**
|
|
670
|
+
* @deprecated Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. This alias will be removed in the next major version.
|
|
671
|
+
*/
|
|
672
|
+
var SSEEdgeClientTransport = class extends SSEClientTransport {
|
|
673
|
+
constructor(url, options) {
|
|
674
|
+
super(url, options);
|
|
675
|
+
if (!didWarnAboutSSEEdgeClientTransport) {
|
|
676
|
+
didWarnAboutSSEEdgeClientTransport = true;
|
|
677
|
+
console.warn("SSEEdgeClientTransport is deprecated. Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. SSEEdgeClientTransport will be removed in the next major version.");
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
let didWarnAboutStreamableHTTPEdgeClientTransport = false;
|
|
682
|
+
/**
|
|
683
|
+
* @deprecated Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. This alias will be removed in the next major version.
|
|
684
|
+
*/
|
|
685
|
+
var StreamableHTTPEdgeClientTransport = class extends StreamableHTTPClientTransport {
|
|
686
|
+
constructor(url, options) {
|
|
687
|
+
super(url, options);
|
|
688
|
+
if (!didWarnAboutStreamableHTTPEdgeClientTransport) {
|
|
689
|
+
didWarnAboutStreamableHTTPEdgeClientTransport = true;
|
|
690
|
+
console.warn("StreamableHTTPEdgeClientTransport is deprecated. Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. StreamableHTTPEdgeClientTransport will be removed in the next major version.");
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
//#endregion
|
|
696
|
+
//#region src/mcp/worker-transport.ts
|
|
697
|
+
const MCP_PROTOCOL_VERSION_HEADER = "MCP-Protocol-Version";
|
|
698
|
+
var WorkerTransport = class {
|
|
699
|
+
constructor(options) {
|
|
700
|
+
this.started = false;
|
|
701
|
+
this.initialized = false;
|
|
702
|
+
this.enableJsonResponse = false;
|
|
703
|
+
this.standaloneSseStreamId = "_GET_stream";
|
|
704
|
+
this.streamMapping = /* @__PURE__ */ new Map();
|
|
705
|
+
this.requestToStreamMapping = /* @__PURE__ */ new Map();
|
|
706
|
+
this.requestResponseMap = /* @__PURE__ */ new Map();
|
|
707
|
+
this.stateRestored = false;
|
|
708
|
+
this.sessionIdGenerator = options?.sessionIdGenerator;
|
|
709
|
+
this.enableJsonResponse = options?.enableJsonResponse ?? false;
|
|
710
|
+
this.onsessioninitialized = options?.onsessioninitialized;
|
|
711
|
+
this.corsOptions = options?.corsOptions;
|
|
712
|
+
this.storage = options?.storage;
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Restore transport state from persistent storage.
|
|
716
|
+
* This is automatically called on start.
|
|
717
|
+
*/
|
|
718
|
+
async restoreState() {
|
|
719
|
+
if (!this.storage || this.stateRestored) return;
|
|
720
|
+
const state = await Promise.resolve(this.storage.get());
|
|
721
|
+
if (state) {
|
|
722
|
+
this.sessionId = state.sessionId;
|
|
723
|
+
this.initialized = state.initialized;
|
|
724
|
+
}
|
|
725
|
+
this.stateRestored = true;
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Persist current transport state to storage.
|
|
729
|
+
*/
|
|
730
|
+
async saveState() {
|
|
731
|
+
if (!this.storage) return;
|
|
732
|
+
const state = {
|
|
733
|
+
sessionId: this.sessionId,
|
|
734
|
+
initialized: this.initialized
|
|
735
|
+
};
|
|
736
|
+
await Promise.resolve(this.storage.set(state));
|
|
737
|
+
}
|
|
738
|
+
async start() {
|
|
739
|
+
if (this.started) throw new Error("Transport already started");
|
|
740
|
+
this.started = true;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Validates the MCP-Protocol-Version header on incoming requests.
|
|
744
|
+
*
|
|
745
|
+
* This performs a simple check: if a version header is present, it must be
|
|
746
|
+
* in the SUPPORTED_PROTOCOL_VERSIONS list. We do not track the negotiated
|
|
747
|
+
* version or enforce version consistency across requests - the SDK handles
|
|
748
|
+
* version negotiation during initialization, and we simply reject any
|
|
749
|
+
* explicitly unsupported versions.
|
|
750
|
+
*
|
|
751
|
+
* - Header present and supported: Accept
|
|
752
|
+
* - Header present and unsupported: 400 Bad Request
|
|
753
|
+
* - Header missing: Accept (version validation is optional)
|
|
754
|
+
*/
|
|
755
|
+
validateProtocolVersion(request) {
|
|
756
|
+
const protocolVersion = request.headers.get(MCP_PROTOCOL_VERSION_HEADER);
|
|
757
|
+
if (protocolVersion !== null && !SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)) return new Response(JSON.stringify({
|
|
758
|
+
jsonrpc: "2.0",
|
|
759
|
+
error: {
|
|
760
|
+
code: -32e3,
|
|
761
|
+
message: `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`
|
|
762
|
+
},
|
|
763
|
+
id: null
|
|
764
|
+
}), {
|
|
765
|
+
status: 400,
|
|
766
|
+
headers: {
|
|
767
|
+
"Content-Type": "application/json",
|
|
768
|
+
...this.getHeaders()
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
getHeaders({ forPreflight } = {}) {
|
|
773
|
+
const options = {
|
|
774
|
+
origin: "*",
|
|
775
|
+
headers: "Content-Type, Accept, Authorization, mcp-session-id, MCP-Protocol-Version",
|
|
776
|
+
methods: "GET, POST, DELETE, OPTIONS",
|
|
777
|
+
exposeHeaders: "mcp-session-id",
|
|
778
|
+
maxAge: 86400,
|
|
779
|
+
...this.corsOptions
|
|
780
|
+
};
|
|
781
|
+
if (forPreflight) return {
|
|
782
|
+
"Access-Control-Allow-Origin": options.origin,
|
|
783
|
+
"Access-Control-Allow-Headers": options.headers,
|
|
784
|
+
"Access-Control-Allow-Methods": options.methods,
|
|
785
|
+
"Access-Control-Max-Age": options.maxAge.toString()
|
|
786
|
+
};
|
|
787
|
+
return {
|
|
788
|
+
"Access-Control-Allow-Origin": options.origin,
|
|
789
|
+
"Access-Control-Expose-Headers": options.exposeHeaders
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
async handleRequest(request, parsedBody) {
|
|
793
|
+
await this.restoreState();
|
|
794
|
+
switch (request.method) {
|
|
795
|
+
case "OPTIONS": return this.handleOptionsRequest(request);
|
|
796
|
+
case "GET": return this.handleGetRequest(request);
|
|
797
|
+
case "POST": return this.handlePostRequest(request, parsedBody);
|
|
798
|
+
case "DELETE": return this.handleDeleteRequest(request);
|
|
799
|
+
default: return this.handleUnsupportedRequest();
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async handleGetRequest(request) {
|
|
803
|
+
if (!request.headers.get("Accept")?.includes("text/event-stream")) return new Response(JSON.stringify({
|
|
804
|
+
jsonrpc: "2.0",
|
|
805
|
+
error: {
|
|
806
|
+
code: -32e3,
|
|
807
|
+
message: "Not Acceptable: Client must accept text/event-stream"
|
|
808
|
+
},
|
|
809
|
+
id: null
|
|
810
|
+
}), {
|
|
811
|
+
status: 406,
|
|
812
|
+
headers: {
|
|
813
|
+
"Content-Type": "application/json",
|
|
814
|
+
...this.getHeaders()
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
const sessionError = this.validateSession(request);
|
|
818
|
+
if (sessionError) return sessionError;
|
|
819
|
+
const versionError = this.validateProtocolVersion(request);
|
|
820
|
+
if (versionError) return versionError;
|
|
821
|
+
const streamId = this.standaloneSseStreamId;
|
|
822
|
+
if (this.streamMapping.get(streamId) !== void 0) return new Response(JSON.stringify({
|
|
823
|
+
jsonrpc: "2.0",
|
|
824
|
+
error: {
|
|
825
|
+
code: -32e3,
|
|
826
|
+
message: "Conflict: Only one SSE stream is allowed per session"
|
|
827
|
+
},
|
|
828
|
+
id: null
|
|
829
|
+
}), {
|
|
830
|
+
status: 409,
|
|
831
|
+
headers: {
|
|
832
|
+
"Content-Type": "application/json",
|
|
833
|
+
...this.getHeaders()
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
const { readable, writable } = new TransformStream();
|
|
837
|
+
const writer = writable.getWriter();
|
|
838
|
+
const encoder = new TextEncoder();
|
|
839
|
+
const headers = new Headers({
|
|
840
|
+
"Content-Type": "text/event-stream",
|
|
841
|
+
"Cache-Control": "no-cache",
|
|
842
|
+
Connection: "keep-alive",
|
|
843
|
+
...this.getHeaders()
|
|
844
|
+
});
|
|
845
|
+
if (this.sessionId !== void 0) headers.set("mcp-session-id", this.sessionId);
|
|
846
|
+
const keepAlive = setInterval(() => {
|
|
847
|
+
try {
|
|
848
|
+
writer.write(encoder.encode("event: ping\ndata: \n\n"));
|
|
849
|
+
} catch {
|
|
850
|
+
clearInterval(keepAlive);
|
|
851
|
+
}
|
|
852
|
+
}, 3e4);
|
|
853
|
+
this.streamMapping.set(streamId, {
|
|
854
|
+
writer,
|
|
855
|
+
encoder,
|
|
856
|
+
cleanup: () => {
|
|
857
|
+
clearInterval(keepAlive);
|
|
858
|
+
this.streamMapping.delete(streamId);
|
|
859
|
+
writer.close().catch(() => {});
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
return new Response(readable, { headers });
|
|
863
|
+
}
|
|
864
|
+
async handlePostRequest(request, parsedBody) {
|
|
865
|
+
const acceptHeader = request.headers.get("Accept");
|
|
866
|
+
if (!acceptHeader?.includes("application/json") || !acceptHeader?.includes("text/event-stream")) return new Response(JSON.stringify({
|
|
867
|
+
jsonrpc: "2.0",
|
|
868
|
+
error: {
|
|
869
|
+
code: -32e3,
|
|
870
|
+
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
871
|
+
},
|
|
872
|
+
id: null
|
|
873
|
+
}), {
|
|
874
|
+
status: 406,
|
|
875
|
+
headers: {
|
|
876
|
+
"Content-Type": "application/json",
|
|
877
|
+
...this.getHeaders()
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
if (!request.headers.get("Content-Type")?.includes("application/json")) return new Response(JSON.stringify({
|
|
881
|
+
jsonrpc: "2.0",
|
|
882
|
+
error: {
|
|
883
|
+
code: -32e3,
|
|
884
|
+
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
885
|
+
},
|
|
886
|
+
id: null
|
|
887
|
+
}), {
|
|
888
|
+
status: 415,
|
|
889
|
+
headers: {
|
|
890
|
+
"Content-Type": "application/json",
|
|
891
|
+
...this.getHeaders()
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
let rawMessage = parsedBody;
|
|
895
|
+
if (rawMessage === void 0) try {
|
|
896
|
+
rawMessage = await request.json();
|
|
897
|
+
} catch {
|
|
898
|
+
return new Response(JSON.stringify({
|
|
899
|
+
jsonrpc: "2.0",
|
|
900
|
+
error: {
|
|
901
|
+
code: -32700,
|
|
902
|
+
message: "Parse error: Invalid JSON"
|
|
903
|
+
},
|
|
904
|
+
id: null
|
|
905
|
+
}), {
|
|
906
|
+
status: 400,
|
|
907
|
+
headers: {
|
|
908
|
+
"Content-Type": "application/json",
|
|
909
|
+
...this.getHeaders()
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
let messages;
|
|
914
|
+
try {
|
|
915
|
+
if (Array.isArray(rawMessage)) messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));
|
|
916
|
+
else messages = [JSONRPCMessageSchema.parse(rawMessage)];
|
|
917
|
+
} catch {
|
|
918
|
+
return new Response(JSON.stringify({
|
|
919
|
+
jsonrpc: "2.0",
|
|
920
|
+
error: {
|
|
921
|
+
code: -32700,
|
|
922
|
+
message: "Parse error: Invalid JSON-RPC message"
|
|
923
|
+
},
|
|
924
|
+
id: null
|
|
925
|
+
}), {
|
|
926
|
+
status: 400,
|
|
927
|
+
headers: {
|
|
928
|
+
"Content-Type": "application/json",
|
|
929
|
+
...this.getHeaders()
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
const requestInfo = { headers: Object.fromEntries(request.headers.entries()) };
|
|
934
|
+
const isInitializationRequest = messages.some(isInitializeRequest);
|
|
935
|
+
if (isInitializationRequest) {
|
|
936
|
+
if (this.initialized && this.sessionId !== void 0) return new Response(JSON.stringify({
|
|
937
|
+
jsonrpc: "2.0",
|
|
938
|
+
error: {
|
|
939
|
+
code: -32600,
|
|
940
|
+
message: "Invalid Request: Server already initialized"
|
|
941
|
+
},
|
|
942
|
+
id: null
|
|
943
|
+
}), {
|
|
944
|
+
status: 400,
|
|
945
|
+
headers: {
|
|
946
|
+
"Content-Type": "application/json",
|
|
947
|
+
...this.getHeaders()
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
if (messages.length > 1) return new Response(JSON.stringify({
|
|
951
|
+
jsonrpc: "2.0",
|
|
952
|
+
error: {
|
|
953
|
+
code: -32600,
|
|
954
|
+
message: "Invalid Request: Only one initialization request is allowed"
|
|
955
|
+
},
|
|
956
|
+
id: null
|
|
957
|
+
}), {
|
|
958
|
+
status: 400,
|
|
959
|
+
headers: {
|
|
960
|
+
"Content-Type": "application/json",
|
|
961
|
+
...this.getHeaders()
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
this.sessionId = this.sessionIdGenerator?.();
|
|
965
|
+
this.initialized = true;
|
|
966
|
+
await this.saveState();
|
|
967
|
+
if (this.sessionId && this.onsessioninitialized) this.onsessioninitialized(this.sessionId);
|
|
968
|
+
}
|
|
969
|
+
if (!isInitializationRequest) {
|
|
970
|
+
const sessionError = this.validateSession(request);
|
|
971
|
+
if (sessionError) return sessionError;
|
|
972
|
+
const versionError = this.validateProtocolVersion(request);
|
|
973
|
+
if (versionError) return versionError;
|
|
974
|
+
}
|
|
975
|
+
if (!messages.some(isJSONRPCRequest)) {
|
|
976
|
+
for (const message of messages) this.onmessage?.(message, { requestInfo });
|
|
977
|
+
return new Response(null, {
|
|
978
|
+
status: 202,
|
|
979
|
+
headers: { ...this.getHeaders() }
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
const streamId = crypto.randomUUID();
|
|
983
|
+
if (this.enableJsonResponse) return new Promise((resolve) => {
|
|
984
|
+
this.streamMapping.set(streamId, {
|
|
985
|
+
resolveJson: resolve,
|
|
986
|
+
cleanup: () => {
|
|
987
|
+
this.streamMapping.delete(streamId);
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
for (const message of messages) if (isJSONRPCRequest(message)) this.requestToStreamMapping.set(message.id, streamId);
|
|
991
|
+
for (const message of messages) this.onmessage?.(message, { requestInfo });
|
|
992
|
+
});
|
|
993
|
+
const { readable, writable } = new TransformStream();
|
|
994
|
+
const writer = writable.getWriter();
|
|
995
|
+
const encoder = new TextEncoder();
|
|
996
|
+
const headers = new Headers({
|
|
997
|
+
"Content-Type": "text/event-stream",
|
|
998
|
+
"Cache-Control": "no-cache",
|
|
999
|
+
Connection: "keep-alive",
|
|
1000
|
+
...this.getHeaders()
|
|
1001
|
+
});
|
|
1002
|
+
if (this.sessionId !== void 0) headers.set("mcp-session-id", this.sessionId);
|
|
1003
|
+
this.streamMapping.set(streamId, {
|
|
1004
|
+
writer,
|
|
1005
|
+
encoder,
|
|
1006
|
+
cleanup: () => {
|
|
1007
|
+
this.streamMapping.delete(streamId);
|
|
1008
|
+
writer.close().catch(() => {});
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
for (const message of messages) if (isJSONRPCRequest(message)) this.requestToStreamMapping.set(message.id, streamId);
|
|
1012
|
+
for (const message of messages) this.onmessage?.(message, { requestInfo });
|
|
1013
|
+
return new Response(readable, { headers });
|
|
1014
|
+
}
|
|
1015
|
+
async handleDeleteRequest(request) {
|
|
1016
|
+
const sessionError = this.validateSession(request);
|
|
1017
|
+
if (sessionError) return sessionError;
|
|
1018
|
+
const versionError = this.validateProtocolVersion(request);
|
|
1019
|
+
if (versionError) return versionError;
|
|
1020
|
+
await this.close();
|
|
1021
|
+
return new Response(null, {
|
|
1022
|
+
status: 200,
|
|
1023
|
+
headers: { ...this.getHeaders() }
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
handleOptionsRequest(_request) {
|
|
1027
|
+
return new Response(null, {
|
|
1028
|
+
status: 200,
|
|
1029
|
+
headers: { ...this.getHeaders({ forPreflight: true }) }
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
handleUnsupportedRequest() {
|
|
1033
|
+
return new Response(JSON.stringify({
|
|
1034
|
+
jsonrpc: "2.0",
|
|
1035
|
+
error: {
|
|
1036
|
+
code: -32e3,
|
|
1037
|
+
message: "Method not allowed."
|
|
1038
|
+
},
|
|
1039
|
+
id: null
|
|
1040
|
+
}), {
|
|
1041
|
+
status: 405,
|
|
1042
|
+
headers: {
|
|
1043
|
+
Allow: "GET, POST, DELETE, OPTIONS",
|
|
1044
|
+
"Content-Type": "application/json"
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
validateSession(request) {
|
|
1049
|
+
if (this.sessionIdGenerator === void 0) return;
|
|
1050
|
+
if (!this.initialized) return new Response(JSON.stringify({
|
|
1051
|
+
jsonrpc: "2.0",
|
|
1052
|
+
error: {
|
|
1053
|
+
code: -32e3,
|
|
1054
|
+
message: "Bad Request: Server not initialized"
|
|
1055
|
+
},
|
|
1056
|
+
id: null
|
|
1057
|
+
}), {
|
|
1058
|
+
status: 400,
|
|
1059
|
+
headers: {
|
|
1060
|
+
"Content-Type": "application/json",
|
|
1061
|
+
...this.getHeaders()
|
|
1062
|
+
}
|
|
1063
|
+
});
|
|
1064
|
+
const sessionId = request.headers.get("mcp-session-id");
|
|
1065
|
+
if (!sessionId) return new Response(JSON.stringify({
|
|
1066
|
+
jsonrpc: "2.0",
|
|
1067
|
+
error: {
|
|
1068
|
+
code: -32e3,
|
|
1069
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
1070
|
+
},
|
|
1071
|
+
id: null
|
|
1072
|
+
}), {
|
|
1073
|
+
status: 400,
|
|
1074
|
+
headers: {
|
|
1075
|
+
"Content-Type": "application/json",
|
|
1076
|
+
...this.getHeaders()
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
if (sessionId !== this.sessionId) return new Response(JSON.stringify({
|
|
1080
|
+
jsonrpc: "2.0",
|
|
1081
|
+
error: {
|
|
1082
|
+
code: -32001,
|
|
1083
|
+
message: "Session not found"
|
|
1084
|
+
},
|
|
1085
|
+
id: null
|
|
1086
|
+
}), {
|
|
1087
|
+
status: 404,
|
|
1088
|
+
headers: {
|
|
1089
|
+
"Content-Type": "application/json",
|
|
1090
|
+
...this.getHeaders()
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
async close() {
|
|
1095
|
+
for (const { cleanup } of this.streamMapping.values()) cleanup();
|
|
1096
|
+
this.streamMapping.clear();
|
|
1097
|
+
this.requestResponseMap.clear();
|
|
1098
|
+
this.onclose?.();
|
|
1099
|
+
}
|
|
1100
|
+
async send(message, options) {
|
|
1101
|
+
let requestId = options?.relatedRequestId;
|
|
1102
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) requestId = message.id;
|
|
1103
|
+
if (requestId === void 0) {
|
|
1104
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) throw new Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");
|
|
1105
|
+
const standaloneSse = this.streamMapping.get(this.standaloneSseStreamId);
|
|
1106
|
+
if (standaloneSse === void 0) return;
|
|
1107
|
+
if (standaloneSse.writer && standaloneSse.encoder) {
|
|
1108
|
+
const data = `event: message\ndata: ${JSON.stringify(message)}\n\n`;
|
|
1109
|
+
await standaloneSse.writer.write(standaloneSse.encoder.encode(data));
|
|
1110
|
+
}
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
const streamId = this.requestToStreamMapping.get(requestId);
|
|
1114
|
+
if (!streamId) throw new Error(`No connection established for request ID: ${String(requestId)}`);
|
|
1115
|
+
const response = this.streamMapping.get(streamId);
|
|
1116
|
+
if (!response) throw new Error(`No connection established for request ID: ${String(requestId)}`);
|
|
1117
|
+
if (!this.enableJsonResponse) {
|
|
1118
|
+
if (response.writer && response.encoder) {
|
|
1119
|
+
const data = `event: message\ndata: ${JSON.stringify(message)}\n\n`;
|
|
1120
|
+
await response.writer.write(response.encoder.encode(data));
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
|
|
1124
|
+
this.requestResponseMap.set(requestId, message);
|
|
1125
|
+
const relatedIds = Array.from(this.requestToStreamMapping.entries()).filter(([, sid]) => sid === streamId).map(([id]) => id);
|
|
1126
|
+
if (relatedIds.every((id) => this.requestResponseMap.has(id))) {
|
|
1127
|
+
if (this.enableJsonResponse && response.resolveJson) {
|
|
1128
|
+
const responses = relatedIds.map((id) => this.requestResponseMap.get(id));
|
|
1129
|
+
const headers = new Headers({
|
|
1130
|
+
"Content-Type": "application/json",
|
|
1131
|
+
...this.getHeaders()
|
|
1132
|
+
});
|
|
1133
|
+
if (this.sessionId !== void 0) headers.set("mcp-session-id", this.sessionId);
|
|
1134
|
+
const body = responses.length === 1 ? responses[0] : responses;
|
|
1135
|
+
response.resolveJson(new Response(JSON.stringify(body), { headers }));
|
|
1136
|
+
} else response.cleanup();
|
|
1137
|
+
for (const id of relatedIds) {
|
|
1138
|
+
this.requestResponseMap.delete(id);
|
|
1139
|
+
this.requestToStreamMapping.delete(id);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
//#endregion
|
|
1147
|
+
//#region src/mcp/auth-context.ts
|
|
1148
|
+
const authContextStorage = new AsyncLocalStorage();
|
|
1149
|
+
function getMcpAuthContext() {
|
|
1150
|
+
return authContextStorage.getStore();
|
|
1151
|
+
}
|
|
1152
|
+
function runWithAuthContext(context, fn) {
|
|
1153
|
+
return authContextStorage.run(context, fn);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
//#endregion
|
|
1157
|
+
//#region src/mcp/handler.ts
|
|
1158
|
+
function createMcpHandler(server, options = {}) {
|
|
1159
|
+
const route = options.route ?? "/mcp";
|
|
1160
|
+
return async (request, _env, ctx) => {
|
|
1161
|
+
const url = new URL(request.url);
|
|
1162
|
+
if (route && url.pathname !== route) return new Response("Not Found", { status: 404 });
|
|
1163
|
+
const transport = options.transport ?? new WorkerTransport({
|
|
1164
|
+
sessionIdGenerator: options.sessionIdGenerator,
|
|
1165
|
+
enableJsonResponse: options.enableJsonResponse,
|
|
1166
|
+
onsessioninitialized: options.onsessioninitialized,
|
|
1167
|
+
corsOptions: options.corsOptions,
|
|
1168
|
+
storage: options.storage
|
|
1169
|
+
});
|
|
1170
|
+
const buildAuthContext = () => {
|
|
1171
|
+
if (options.authContext) return options.authContext;
|
|
1172
|
+
if (ctx.props && Object.keys(ctx.props).length > 0) return { props: ctx.props };
|
|
1173
|
+
};
|
|
1174
|
+
const handleRequest = async () => {
|
|
1175
|
+
return await transport.handleRequest(request);
|
|
1176
|
+
};
|
|
1177
|
+
const authContext = buildAuthContext();
|
|
1178
|
+
if (!transport.started) await server.connect(transport);
|
|
1179
|
+
try {
|
|
1180
|
+
if (authContext) return await runWithAuthContext(authContext, handleRequest);
|
|
1181
|
+
else return await handleRequest();
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
console.error("MCP handler error:", error);
|
|
1184
|
+
return new Response(JSON.stringify({
|
|
1185
|
+
jsonrpc: "2.0",
|
|
1186
|
+
error: {
|
|
1187
|
+
code: -32603,
|
|
1188
|
+
message: error instanceof Error ? error.message : "Internal server error"
|
|
1189
|
+
},
|
|
1190
|
+
id: null
|
|
1191
|
+
}), {
|
|
1192
|
+
status: 500,
|
|
1193
|
+
headers: { "Content-Type": "application/json" }
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
let didWarnAboutExperimentalCreateMcpHandler = false;
|
|
1199
|
+
/**
|
|
1200
|
+
* @deprecated This has been renamed to createMcpHandler, and experimental_createMcpHandler will be removed in the next major version
|
|
1201
|
+
*/
|
|
1202
|
+
function experimental_createMcpHandler(server, options = {}) {
|
|
1203
|
+
if (!didWarnAboutExperimentalCreateMcpHandler) {
|
|
1204
|
+
didWarnAboutExperimentalCreateMcpHandler = true;
|
|
1205
|
+
console.warn("experimental_createMcpHandler is deprecated, use createMcpHandler instead. experimental_createMcpHandler will be removed in the next major version.");
|
|
1206
|
+
}
|
|
1207
|
+
return createMcpHandler(server, options);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
627
1210
|
//#endregion
|
|
628
1211
|
//#region src/mcp/index.ts
|
|
629
1212
|
var McpAgent = class McpAgent extends Agent {
|
|
@@ -663,8 +1246,14 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
663
1246
|
/** Returns a new transport matching the type of the Agent. */
|
|
664
1247
|
initTransport() {
|
|
665
1248
|
switch (this.getTransportType()) {
|
|
666
|
-
case "sse": return new McpSSETransport(
|
|
667
|
-
case "streamable-http":
|
|
1249
|
+
case "sse": return new McpSSETransport();
|
|
1250
|
+
case "streamable-http": {
|
|
1251
|
+
const transport = new StreamableHTTPServerTransport({});
|
|
1252
|
+
transport.messageInterceptor = async (message) => {
|
|
1253
|
+
return this._handleElicitationResponse(message);
|
|
1254
|
+
};
|
|
1255
|
+
return transport;
|
|
1256
|
+
}
|
|
668
1257
|
}
|
|
669
1258
|
}
|
|
670
1259
|
/** Update and store the props */
|
|
@@ -716,7 +1305,7 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
716
1305
|
}
|
|
717
1306
|
}
|
|
718
1307
|
/** Handles MCP Messages for the legacy SSE transport. */
|
|
719
|
-
async onSSEMcpMessage(_sessionId, messageBody) {
|
|
1308
|
+
async onSSEMcpMessage(_sessionId, messageBody, extraInfo) {
|
|
720
1309
|
if (this.getTransportType() !== "sse") return /* @__PURE__ */ new Error("Internal Server Error: Expected SSE transport");
|
|
721
1310
|
try {
|
|
722
1311
|
let parsedMessage;
|
|
@@ -727,7 +1316,7 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
727
1316
|
throw error;
|
|
728
1317
|
}
|
|
729
1318
|
if (await this._handleElicitationResponse(parsedMessage)) return null;
|
|
730
|
-
this._transport?.onmessage?.(parsedMessage);
|
|
1319
|
+
this._transport?.onmessage?.(parsedMessage, extraInfo);
|
|
731
1320
|
return null;
|
|
732
1321
|
} catch (error) {
|
|
733
1322
|
console.error("Error forwarding message to SSE:", error);
|
|
@@ -813,7 +1402,7 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
813
1402
|
/** Return a handler for the given path for this MCP.
|
|
814
1403
|
* Defaults to Streamable HTTP transport.
|
|
815
1404
|
*/
|
|
816
|
-
static serve(path, { binding = "MCP_OBJECT", corsOptions, transport = "streamable-http" } = {}) {
|
|
1405
|
+
static serve(path, { binding = "MCP_OBJECT", corsOptions, transport = "streamable-http", jurisdiction } = {}) {
|
|
817
1406
|
return { async fetch(request, env, ctx) {
|
|
818
1407
|
const corsResponse = handleCORS(request, corsOptions);
|
|
819
1408
|
if (corsResponse) return corsResponse;
|
|
@@ -822,8 +1411,14 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
822
1411
|
if (!isDurableObjectNamespace(bindingValue)) throw new Error(`Invalid McpAgent binding for ${binding}. Make sure it's a Durable Object binding.`);
|
|
823
1412
|
const namespace = bindingValue;
|
|
824
1413
|
switch (transport) {
|
|
825
|
-
case "streamable-http": return createStreamingHttpHandler(path, namespace,
|
|
826
|
-
|
|
1414
|
+
case "streamable-http": return createStreamingHttpHandler(path, namespace, {
|
|
1415
|
+
corsOptions,
|
|
1416
|
+
jurisdiction
|
|
1417
|
+
})(request, ctx);
|
|
1418
|
+
case "sse": return createLegacySseHandler(path, namespace, {
|
|
1419
|
+
corsOptions,
|
|
1420
|
+
jurisdiction
|
|
1421
|
+
})(request, ctx);
|
|
827
1422
|
default: return new Response("Invalid MCP transport mode. Only `streamable-http` or `sse` are allowed.", { status: 500 });
|
|
828
1423
|
}
|
|
829
1424
|
} };
|
|
@@ -843,5 +1438,5 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
843
1438
|
};
|
|
844
1439
|
|
|
845
1440
|
//#endregion
|
|
846
|
-
export { ElicitRequestSchema, McpAgent, SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport };
|
|
1441
|
+
export { ElicitRequestSchema, McpAgent, SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport, WorkerTransport, createMcpHandler, experimental_createMcpHandler, getMcpAuthContext };
|
|
847
1442
|
//# sourceMappingURL=index.js.map
|