agents 0.0.0-cdfc590 → 0.0.0-cec3cca
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/ai-chat-agent.d.ts +10 -10
- package/dist/ai-chat-agent.js +6 -6
- package/dist/{ai-chat-v5-migration-gdyLiTd8.js → ai-chat-v5-migration-DBHGW4Hv.js} +2 -2
- package/dist/{ai-chat-v5-migration-gdyLiTd8.js.map → ai-chat-v5-migration-DBHGW4Hv.js.map} +1 -1
- package/dist/ai-chat-v5-migration.js +1 -1
- package/dist/ai-react.d.ts +9 -9
- package/dist/ai-react.js +1 -1
- package/dist/{ai-types-UZlfLOYP.js → ai-types-B3aQaFv3.js} +2 -2
- package/dist/{ai-types-UZlfLOYP.js.map → ai-types-B3aQaFv3.js.map} +1 -1
- package/dist/{ai-types-BWW4umHY.d.ts → ai-types-D5YoPrBZ.d.ts} +2 -2
- package/dist/ai-types.d.ts +4 -4
- package/dist/ai-types.js +1 -1
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/{client-CZBVDDoO.js → client-9Ld2_lnt.js} +2 -2
- package/dist/{client-CZBVDDoO.js.map → client-9Ld2_lnt.js.map} +1 -1
- package/dist/{client-DjR-lC16.js → client-BfiZ3HQd.js} +3 -3
- package/dist/{client-DjR-lC16.js.map → client-BfiZ3HQd.js.map} +1 -1
- package/dist/{client-CmMi85Sj.d.ts → client-CbWe9FBd.d.ts} +10 -10
- package/dist/{client-CrWcaPgn.d.ts → client-Csp_m13H.d.ts} +25 -23
- package/dist/client.d.ts +8 -8
- package/dist/client.js +2 -2
- package/dist/codemode/ai.js +5 -5
- package/dist/{do-oauth-client-provider-B2jr6UNq.js → do-oauth-client-provider-CswoD5Lu.js} +2 -2
- package/dist/{do-oauth-client-provider-B2jr6UNq.js.map → do-oauth-client-provider-CswoD5Lu.js.map} +1 -1
- package/dist/{do-oauth-client-provider-CCwGwnrA.d.ts → do-oauth-client-provider-DGc5pP0l.d.ts} +2 -2
- package/dist/{index-Daqy_D9E.d.ts → index-DFqsR7mb.d.ts} +48 -46
- package/dist/{index-W4JUkafc.d.ts → index-DhJCaDWd.d.ts} +7 -3
- package/dist/index.d.ts +36 -36
- package/dist/index.js +5 -5
- package/dist/mcp/client.d.ts +3 -3
- package/dist/mcp/client.js +1 -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 +88 -9
- package/dist/mcp/index.js +549 -26
- package/dist/mcp/index.js.map +1 -1
- package/dist/{mcp-BEwaCsxO.d.ts → mcp-Dw5vDrY8.d.ts} +2 -2
- package/dist/observability/index.d.ts +2 -2
- package/dist/observability/index.js +5 -5
- package/dist/{react-Cl4ZPPhW.d.ts → react-NCPvtyCY.d.ts} +28 -26
- package/dist/react.d.ts +9 -9
- package/dist/react.js +1 -1
- package/dist/{serializable-gtr9YMhp.d.ts → serializable-CymX8ovI.d.ts} +8 -3
- package/dist/serializable.d.ts +5 -5
- package/dist/{src-COfG--3R.js → src-Dz0H9hSU.js} +47 -26
- package/dist/src-Dz0H9hSU.js.map +1 -0
- package/package.json +14 -8
- package/dist/src-COfG--3R.js.map +0 -1
- package/src/index.ts +0 -2031
package/dist/mcp/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { MessageType } from "../ai-types-
|
|
2
|
-
import "../client-
|
|
3
|
-
import { SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport } from "../client-
|
|
4
|
-
import "../do-oauth-client-provider-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { t as MessageType } from "../ai-types-B3aQaFv3.js";
|
|
2
|
+
import "../client-BfiZ3HQd.js";
|
|
3
|
+
import { a as SSEEdgeClientTransport, i as StreamableHTTPEdgeClientTransport } from "../client-9Ld2_lnt.js";
|
|
4
|
+
import "../do-oauth-client-provider-CswoD5Lu.js";
|
|
5
|
+
import { c as getCurrentAgent, s as getAgentByName, t as Agent } from "../src-Dz0H9hSU.js";
|
|
6
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
|
+
import { ElicitRequestSchema, InitializeRequestSchema, JSONRPCMessageSchema, isInitializeRequest, isJSONRPCError, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResponse } from "@modelcontextprotocol/sdk/types.js";
|
|
7
8
|
|
|
8
9
|
//#region src/mcp/utils.ts
|
|
9
10
|
/**
|
|
@@ -20,7 +21,7 @@ const MCP_HTTP_METHOD_HEADER = "cf-mcp-method";
|
|
|
20
21
|
*/
|
|
21
22
|
const MCP_MESSAGE_HEADER = "cf-mcp-message";
|
|
22
23
|
const MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024;
|
|
23
|
-
const createStreamingHttpHandler = (basePath, namespace,
|
|
24
|
+
const createStreamingHttpHandler = (basePath, namespace, options = {}) => {
|
|
24
25
|
let pathname = basePath;
|
|
25
26
|
if (basePath === "/") pathname = "/*";
|
|
26
27
|
const basePattern = new URLPattern({ pathname });
|
|
@@ -129,7 +130,10 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
129
130
|
return new Response(body$1, { status: 400 });
|
|
130
131
|
}
|
|
131
132
|
sessionId = sessionId ?? namespace.newUniqueId().toString();
|
|
132
|
-
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
133
|
+
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
134
|
+
props: ctx.props,
|
|
135
|
+
jurisdiction: options.jurisdiction
|
|
136
|
+
});
|
|
133
137
|
const isInitialized = await agent.getInitializeRequest();
|
|
134
138
|
if (maybeInitializeRequest) await agent.setInitializeRequest(maybeInitializeRequest);
|
|
135
139
|
else if (!isInitialized) {
|
|
@@ -204,7 +208,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
204
208
|
if (messages.every((msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(msg))) {
|
|
205
209
|
ws.close();
|
|
206
210
|
return new Response(null, {
|
|
207
|
-
headers: corsHeaders(request, corsOptions),
|
|
211
|
+
headers: corsHeaders(request, options.corsOptions),
|
|
208
212
|
status: 202
|
|
209
213
|
});
|
|
210
214
|
}
|
|
@@ -214,7 +218,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
214
218
|
Connection: "keep-alive",
|
|
215
219
|
"Content-Type": "text/event-stream",
|
|
216
220
|
"mcp-session-id": sessionId,
|
|
217
|
-
...corsHeaders(request, corsOptions)
|
|
221
|
+
...corsHeaders(request, options.corsOptions)
|
|
218
222
|
},
|
|
219
223
|
status: 200
|
|
220
224
|
});
|
|
@@ -242,7 +246,10 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
242
246
|
const { readable, writable } = new TransformStream();
|
|
243
247
|
const writer = writable.getWriter();
|
|
244
248
|
const encoder = new TextEncoder();
|
|
245
|
-
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
249
|
+
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, {
|
|
250
|
+
props: ctx.props,
|
|
251
|
+
jurisdiction: options.jurisdiction
|
|
252
|
+
});
|
|
246
253
|
if (!await agent.getInitializeRequest()) return new Response(JSON.stringify({
|
|
247
254
|
jsonrpc: "2.0",
|
|
248
255
|
error: {
|
|
@@ -291,7 +298,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
291
298
|
Connection: "keep-alive",
|
|
292
299
|
"Content-Type": "text/event-stream",
|
|
293
300
|
"mcp-session-id": sessionId,
|
|
294
|
-
...corsHeaders(request, corsOptions)
|
|
301
|
+
...corsHeaders(request, options.corsOptions)
|
|
295
302
|
},
|
|
296
303
|
status: 200
|
|
297
304
|
});
|
|
@@ -306,9 +313,9 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
306
313
|
id: null
|
|
307
314
|
}), {
|
|
308
315
|
status: 400,
|
|
309
|
-
headers: corsHeaders(request, corsOptions)
|
|
316
|
+
headers: corsHeaders(request, options.corsOptions)
|
|
310
317
|
});
|
|
311
|
-
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}
|
|
318
|
+
const agent = await getAgentByName(namespace, `streamable-http:${sessionId}`, { jurisdiction: options.jurisdiction });
|
|
312
319
|
if (!await agent.getInitializeRequest()) return new Response(JSON.stringify({
|
|
313
320
|
jsonrpc: "2.0",
|
|
314
321
|
error: {
|
|
@@ -318,12 +325,12 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
318
325
|
id: null
|
|
319
326
|
}), {
|
|
320
327
|
status: 404,
|
|
321
|
-
headers: corsHeaders(request, corsOptions)
|
|
328
|
+
headers: corsHeaders(request, options.corsOptions)
|
|
322
329
|
});
|
|
323
330
|
ctx.waitUntil(agent.destroy().catch(() => {}));
|
|
324
331
|
return new Response(null, {
|
|
325
332
|
status: 204,
|
|
326
|
-
headers: corsHeaders(request, corsOptions)
|
|
333
|
+
headers: corsHeaders(request, options.corsOptions)
|
|
327
334
|
});
|
|
328
335
|
}
|
|
329
336
|
}
|
|
@@ -338,7 +345,7 @@ const createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
338
345
|
return new Response(body, { status: 404 });
|
|
339
346
|
};
|
|
340
347
|
};
|
|
341
|
-
const createLegacySseHandler = (basePath, namespace,
|
|
348
|
+
const createLegacySseHandler = (basePath, namespace, options = {}) => {
|
|
342
349
|
let pathname = basePath;
|
|
343
350
|
if (basePath === "/") pathname = "/*";
|
|
344
351
|
const basePattern = new URLPattern({ pathname });
|
|
@@ -355,7 +362,10 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
355
362
|
endpointUrl.searchParams.set("sessionId", sessionId);
|
|
356
363
|
const endpointMessage = `event: endpoint\ndata: ${endpointUrl.pathname + endpointUrl.search + endpointUrl.hash}\n\n`;
|
|
357
364
|
writer.write(encoder.encode(endpointMessage));
|
|
358
|
-
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
365
|
+
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
366
|
+
props: ctx.props,
|
|
367
|
+
jurisdiction: options.jurisdiction
|
|
368
|
+
});
|
|
359
369
|
const existingHeaders = {};
|
|
360
370
|
request.headers.forEach((value, key) => {
|
|
361
371
|
existingHeaders[key] = value;
|
|
@@ -407,7 +417,7 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
407
417
|
"Cache-Control": "no-cache",
|
|
408
418
|
Connection: "keep-alive",
|
|
409
419
|
"Content-Type": "text/event-stream",
|
|
410
|
-
...corsHeaders(request, corsOptions)
|
|
420
|
+
...corsHeaders(request, options.corsOptions)
|
|
411
421
|
} });
|
|
412
422
|
}
|
|
413
423
|
if (request.method === "POST" && messagePattern.test(url)) {
|
|
@@ -417,7 +427,10 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
417
427
|
if (!contentType.includes("application/json")) return new Response(`Unsupported content-type: ${contentType}`, { status: 400 });
|
|
418
428
|
const contentLength = Number.parseInt(request.headers.get("content-length") || "0", 10);
|
|
419
429
|
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}`, {
|
|
430
|
+
const agent = await getAgentByName(namespace, `sse:${sessionId}`, {
|
|
431
|
+
props: ctx.props,
|
|
432
|
+
jurisdiction: options.jurisdiction
|
|
433
|
+
});
|
|
421
434
|
const messageBody = await request.json();
|
|
422
435
|
const error = await agent.onSSEMcpMessage(sessionId, messageBody);
|
|
423
436
|
if (error) return new Response(error.message, {
|
|
@@ -425,7 +438,7 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
425
438
|
"Cache-Control": "no-cache",
|
|
426
439
|
Connection: "keep-alive",
|
|
427
440
|
"Content-Type": "text/event-stream",
|
|
428
|
-
...corsHeaders(request, corsOptions)
|
|
441
|
+
...corsHeaders(request, options.corsOptions)
|
|
429
442
|
},
|
|
430
443
|
status: 400
|
|
431
444
|
});
|
|
@@ -434,7 +447,7 @@ const createLegacySseHandler = (basePath, namespace, corsOptions) => {
|
|
|
434
447
|
"Cache-Control": "no-cache",
|
|
435
448
|
Connection: "keep-alive",
|
|
436
449
|
"Content-Type": "text/event-stream",
|
|
437
|
-
...corsHeaders(request, corsOptions)
|
|
450
|
+
...corsHeaders(request, options.corsOptions)
|
|
438
451
|
},
|
|
439
452
|
status: 202
|
|
440
453
|
});
|
|
@@ -624,6 +637,510 @@ var StreamableHTTPServerTransport = class {
|
|
|
624
637
|
}
|
|
625
638
|
};
|
|
626
639
|
|
|
640
|
+
//#endregion
|
|
641
|
+
//#region src/mcp/worker-transport.ts
|
|
642
|
+
const SUPPORTED_PROTOCOL_VERSIONS = ["2025-03-26", "2025-06-18"];
|
|
643
|
+
const DEFAULT_PROTOCOL_VERSION = "2025-03-26";
|
|
644
|
+
const MCP_PROTOCOL_VERSION_HEADER = "MCP-Protocol-Version";
|
|
645
|
+
var WorkerTransport = class {
|
|
646
|
+
constructor(options) {
|
|
647
|
+
this.started = false;
|
|
648
|
+
this.initialized = false;
|
|
649
|
+
this.enableJsonResponse = false;
|
|
650
|
+
this.standaloneSseStreamId = "_GET_stream";
|
|
651
|
+
this.streamMapping = /* @__PURE__ */ new Map();
|
|
652
|
+
this.requestToStreamMapping = /* @__PURE__ */ new Map();
|
|
653
|
+
this.requestResponseMap = /* @__PURE__ */ new Map();
|
|
654
|
+
this.sessionIdGenerator = options?.sessionIdGenerator;
|
|
655
|
+
this.enableJsonResponse = options?.enableJsonResponse ?? false;
|
|
656
|
+
this.onsessioninitialized = options?.onsessioninitialized;
|
|
657
|
+
this.corsOptions = options?.corsOptions;
|
|
658
|
+
}
|
|
659
|
+
async start() {
|
|
660
|
+
if (this.started) throw new Error("Transport already started");
|
|
661
|
+
this.started = true;
|
|
662
|
+
}
|
|
663
|
+
validateProtocolVersion(request) {
|
|
664
|
+
const versionHeader = request.headers.get(MCP_PROTOCOL_VERSION_HEADER);
|
|
665
|
+
if (!versionHeader) {
|
|
666
|
+
if (!this.protocolVersion || this.protocolVersion === DEFAULT_PROTOCOL_VERSION) return;
|
|
667
|
+
return new Response(JSON.stringify({
|
|
668
|
+
jsonrpc: "2.0",
|
|
669
|
+
error: {
|
|
670
|
+
code: -32e3,
|
|
671
|
+
message: `Bad Request: ${MCP_PROTOCOL_VERSION_HEADER} header is required`
|
|
672
|
+
},
|
|
673
|
+
id: null
|
|
674
|
+
}), {
|
|
675
|
+
status: 400,
|
|
676
|
+
headers: {
|
|
677
|
+
"Content-Type": "application/json",
|
|
678
|
+
...this.getHeaders()
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
if (!SUPPORTED_PROTOCOL_VERSIONS.includes(versionHeader)) return new Response(JSON.stringify({
|
|
683
|
+
jsonrpc: "2.0",
|
|
684
|
+
error: {
|
|
685
|
+
code: -32e3,
|
|
686
|
+
message: `Bad Request: Unsupported ${MCP_PROTOCOL_VERSION_HEADER}: ${versionHeader}. Supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")}`
|
|
687
|
+
},
|
|
688
|
+
id: null
|
|
689
|
+
}), {
|
|
690
|
+
status: 400,
|
|
691
|
+
headers: {
|
|
692
|
+
"Content-Type": "application/json",
|
|
693
|
+
...this.getHeaders()
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
if (this.protocolVersion && versionHeader !== this.protocolVersion) return new Response(JSON.stringify({
|
|
697
|
+
jsonrpc: "2.0",
|
|
698
|
+
error: {
|
|
699
|
+
code: -32e3,
|
|
700
|
+
message: `Bad Request: ${MCP_PROTOCOL_VERSION_HEADER} mismatch. Expected: ${this.protocolVersion}, Got: ${versionHeader}`
|
|
701
|
+
},
|
|
702
|
+
id: null
|
|
703
|
+
}), {
|
|
704
|
+
status: 400,
|
|
705
|
+
headers: {
|
|
706
|
+
"Content-Type": "application/json",
|
|
707
|
+
...this.getHeaders()
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
getHeaders({ forPreflight } = {}) {
|
|
712
|
+
const options = {
|
|
713
|
+
origin: "*",
|
|
714
|
+
headers: "Content-Type, Accept, Authorization, mcp-session-id, MCP-Protocol-Version",
|
|
715
|
+
methods: "GET, POST, DELETE, OPTIONS",
|
|
716
|
+
exposeHeaders: "mcp-session-id",
|
|
717
|
+
maxAge: 86400,
|
|
718
|
+
...this.corsOptions
|
|
719
|
+
};
|
|
720
|
+
if (forPreflight) return {
|
|
721
|
+
"Access-Control-Allow-Origin": options.origin,
|
|
722
|
+
"Access-Control-Allow-Headers": options.headers,
|
|
723
|
+
"Access-Control-Allow-Methods": options.methods,
|
|
724
|
+
"Access-Control-Max-Age": options.maxAge.toString()
|
|
725
|
+
};
|
|
726
|
+
return {
|
|
727
|
+
"Access-Control-Allow-Origin": options.origin,
|
|
728
|
+
"Access-Control-Expose-Headers": options.exposeHeaders
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
async handleRequest(request, parsedBody) {
|
|
732
|
+
switch (request.method) {
|
|
733
|
+
case "OPTIONS": return this.handleOptionsRequest(request);
|
|
734
|
+
case "GET": return this.handleGetRequest(request);
|
|
735
|
+
case "POST": return this.handlePostRequest(request, parsedBody);
|
|
736
|
+
case "DELETE": return this.handleDeleteRequest(request);
|
|
737
|
+
default: return this.handleUnsupportedRequest();
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
async handleGetRequest(request) {
|
|
741
|
+
if (!request.headers.get("Accept")?.includes("text/event-stream")) return new Response(JSON.stringify({
|
|
742
|
+
jsonrpc: "2.0",
|
|
743
|
+
error: {
|
|
744
|
+
code: -32e3,
|
|
745
|
+
message: "Not Acceptable: Client must accept text/event-stream"
|
|
746
|
+
},
|
|
747
|
+
id: null
|
|
748
|
+
}), {
|
|
749
|
+
status: 406,
|
|
750
|
+
headers: {
|
|
751
|
+
"Content-Type": "application/json",
|
|
752
|
+
...this.getHeaders()
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
const sessionError = this.validateSession(request);
|
|
756
|
+
if (sessionError) return sessionError;
|
|
757
|
+
const versionError = this.validateProtocolVersion(request);
|
|
758
|
+
if (versionError) return versionError;
|
|
759
|
+
const streamId = this.standaloneSseStreamId;
|
|
760
|
+
if (this.streamMapping.get(streamId) !== void 0) return new Response(JSON.stringify({
|
|
761
|
+
jsonrpc: "2.0",
|
|
762
|
+
error: {
|
|
763
|
+
code: -32e3,
|
|
764
|
+
message: "Conflict: Only one SSE stream is allowed per session"
|
|
765
|
+
},
|
|
766
|
+
id: null
|
|
767
|
+
}), {
|
|
768
|
+
status: 409,
|
|
769
|
+
headers: {
|
|
770
|
+
"Content-Type": "application/json",
|
|
771
|
+
...this.getHeaders()
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
const { readable, writable } = new TransformStream();
|
|
775
|
+
const writer = writable.getWriter();
|
|
776
|
+
const encoder = new TextEncoder();
|
|
777
|
+
const headers = new Headers({
|
|
778
|
+
"Content-Type": "text/event-stream",
|
|
779
|
+
"Cache-Control": "no-cache",
|
|
780
|
+
Connection: "keep-alive",
|
|
781
|
+
...this.getHeaders()
|
|
782
|
+
});
|
|
783
|
+
if (this.sessionId !== void 0) headers.set("mcp-session-id", this.sessionId);
|
|
784
|
+
const keepAlive = setInterval(() => {
|
|
785
|
+
try {
|
|
786
|
+
writer.write(encoder.encode("event: ping\ndata: \n\n"));
|
|
787
|
+
} catch {
|
|
788
|
+
clearInterval(keepAlive);
|
|
789
|
+
}
|
|
790
|
+
}, 3e4);
|
|
791
|
+
this.streamMapping.set(streamId, {
|
|
792
|
+
writer,
|
|
793
|
+
encoder,
|
|
794
|
+
cleanup: () => {
|
|
795
|
+
clearInterval(keepAlive);
|
|
796
|
+
this.streamMapping.delete(streamId);
|
|
797
|
+
writer.close().catch(() => {});
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
return new Response(readable, { headers });
|
|
801
|
+
}
|
|
802
|
+
async handlePostRequest(request, parsedBody) {
|
|
803
|
+
const acceptHeader = request.headers.get("Accept");
|
|
804
|
+
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) return new Response(JSON.stringify({
|
|
805
|
+
jsonrpc: "2.0",
|
|
806
|
+
error: {
|
|
807
|
+
code: -32e3,
|
|
808
|
+
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
809
|
+
},
|
|
810
|
+
id: null
|
|
811
|
+
}), {
|
|
812
|
+
status: 406,
|
|
813
|
+
headers: {
|
|
814
|
+
"Content-Type": "application/json",
|
|
815
|
+
...this.getHeaders()
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
if (!request.headers.get("Content-Type")?.includes("application/json")) return new Response(JSON.stringify({
|
|
819
|
+
jsonrpc: "2.0",
|
|
820
|
+
error: {
|
|
821
|
+
code: -32e3,
|
|
822
|
+
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
823
|
+
},
|
|
824
|
+
id: null
|
|
825
|
+
}), {
|
|
826
|
+
status: 415,
|
|
827
|
+
headers: {
|
|
828
|
+
"Content-Type": "application/json",
|
|
829
|
+
...this.getHeaders()
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
let rawMessage = parsedBody;
|
|
833
|
+
if (rawMessage === void 0) try {
|
|
834
|
+
rawMessage = await request.json();
|
|
835
|
+
} catch {
|
|
836
|
+
return new Response(JSON.stringify({
|
|
837
|
+
jsonrpc: "2.0",
|
|
838
|
+
error: {
|
|
839
|
+
code: -32700,
|
|
840
|
+
message: "Parse error: Invalid JSON"
|
|
841
|
+
},
|
|
842
|
+
id: null
|
|
843
|
+
}), {
|
|
844
|
+
status: 400,
|
|
845
|
+
headers: {
|
|
846
|
+
"Content-Type": "application/json",
|
|
847
|
+
...this.getHeaders()
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
let messages;
|
|
852
|
+
try {
|
|
853
|
+
if (Array.isArray(rawMessage)) messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));
|
|
854
|
+
else messages = [JSONRPCMessageSchema.parse(rawMessage)];
|
|
855
|
+
} catch {
|
|
856
|
+
return new Response(JSON.stringify({
|
|
857
|
+
jsonrpc: "2.0",
|
|
858
|
+
error: {
|
|
859
|
+
code: -32700,
|
|
860
|
+
message: "Parse error: Invalid JSON-RPC message"
|
|
861
|
+
},
|
|
862
|
+
id: null
|
|
863
|
+
}), {
|
|
864
|
+
status: 400,
|
|
865
|
+
headers: {
|
|
866
|
+
"Content-Type": "application/json",
|
|
867
|
+
...this.getHeaders()
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
const requestInfo = { headers: Object.fromEntries(request.headers.entries()) };
|
|
872
|
+
const isInitializationRequest = messages.some(isInitializeRequest);
|
|
873
|
+
if (isInitializationRequest) {
|
|
874
|
+
if (this.initialized && this.sessionId !== void 0) return new Response(JSON.stringify({
|
|
875
|
+
jsonrpc: "2.0",
|
|
876
|
+
error: {
|
|
877
|
+
code: -32600,
|
|
878
|
+
message: "Invalid Request: Server already initialized"
|
|
879
|
+
},
|
|
880
|
+
id: null
|
|
881
|
+
}), {
|
|
882
|
+
status: 400,
|
|
883
|
+
headers: {
|
|
884
|
+
"Content-Type": "application/json",
|
|
885
|
+
...this.getHeaders()
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
if (messages.length > 1) return new Response(JSON.stringify({
|
|
889
|
+
jsonrpc: "2.0",
|
|
890
|
+
error: {
|
|
891
|
+
code: -32600,
|
|
892
|
+
message: "Invalid Request: Only one initialization request is allowed"
|
|
893
|
+
},
|
|
894
|
+
id: null
|
|
895
|
+
}), {
|
|
896
|
+
status: 400,
|
|
897
|
+
headers: {
|
|
898
|
+
"Content-Type": "application/json",
|
|
899
|
+
...this.getHeaders()
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
const initRequest = messages.find(isInitializeRequest);
|
|
903
|
+
if (initRequest?.params) {
|
|
904
|
+
const version = initRequest.params.protocolVersion;
|
|
905
|
+
if (version && SUPPORTED_PROTOCOL_VERSIONS.includes(version)) this.protocolVersion = version;
|
|
906
|
+
else this.protocolVersion = DEFAULT_PROTOCOL_VERSION;
|
|
907
|
+
}
|
|
908
|
+
this.sessionId = this.sessionIdGenerator?.();
|
|
909
|
+
this.initialized = true;
|
|
910
|
+
if (this.sessionId && this.onsessioninitialized) this.onsessioninitialized(this.sessionId);
|
|
911
|
+
}
|
|
912
|
+
if (!isInitializationRequest) {
|
|
913
|
+
const sessionError = this.validateSession(request);
|
|
914
|
+
if (sessionError) return sessionError;
|
|
915
|
+
const versionError = this.validateProtocolVersion(request);
|
|
916
|
+
if (versionError) return versionError;
|
|
917
|
+
}
|
|
918
|
+
if (!messages.some(isJSONRPCRequest)) {
|
|
919
|
+
for (const message of messages) this.onmessage?.(message, { requestInfo });
|
|
920
|
+
return new Response(null, {
|
|
921
|
+
status: 202,
|
|
922
|
+
headers: { ...this.getHeaders() }
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
const streamId = crypto.randomUUID();
|
|
926
|
+
if (this.enableJsonResponse) return new Promise((resolve) => {
|
|
927
|
+
this.streamMapping.set(streamId, {
|
|
928
|
+
resolveJson: resolve,
|
|
929
|
+
cleanup: () => {
|
|
930
|
+
this.streamMapping.delete(streamId);
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
for (const message of messages) if (isJSONRPCRequest(message)) this.requestToStreamMapping.set(message.id, streamId);
|
|
934
|
+
for (const message of messages) this.onmessage?.(message, { requestInfo });
|
|
935
|
+
});
|
|
936
|
+
const { readable, writable } = new TransformStream();
|
|
937
|
+
const writer = writable.getWriter();
|
|
938
|
+
const encoder = new TextEncoder();
|
|
939
|
+
const headers = new Headers({
|
|
940
|
+
"Content-Type": "text/event-stream",
|
|
941
|
+
"Cache-Control": "no-cache",
|
|
942
|
+
Connection: "keep-alive",
|
|
943
|
+
...this.getHeaders()
|
|
944
|
+
});
|
|
945
|
+
if (this.sessionId !== void 0) headers.set("mcp-session-id", this.sessionId);
|
|
946
|
+
this.streamMapping.set(streamId, {
|
|
947
|
+
writer,
|
|
948
|
+
encoder,
|
|
949
|
+
cleanup: () => {
|
|
950
|
+
this.streamMapping.delete(streamId);
|
|
951
|
+
writer.close().catch(() => {});
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
for (const message of messages) if (isJSONRPCRequest(message)) this.requestToStreamMapping.set(message.id, streamId);
|
|
955
|
+
for (const message of messages) this.onmessage?.(message, { requestInfo });
|
|
956
|
+
return new Response(readable, { headers });
|
|
957
|
+
}
|
|
958
|
+
async handleDeleteRequest(request) {
|
|
959
|
+
const sessionError = this.validateSession(request);
|
|
960
|
+
if (sessionError) return sessionError;
|
|
961
|
+
const versionError = this.validateProtocolVersion(request);
|
|
962
|
+
if (versionError) return versionError;
|
|
963
|
+
await this.close();
|
|
964
|
+
return new Response(null, {
|
|
965
|
+
status: 200,
|
|
966
|
+
headers: { ...this.getHeaders() }
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
handleOptionsRequest(_request) {
|
|
970
|
+
return new Response(null, {
|
|
971
|
+
status: 200,
|
|
972
|
+
headers: { ...this.getHeaders({ forPreflight: true }) }
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
handleUnsupportedRequest() {
|
|
976
|
+
return new Response(JSON.stringify({
|
|
977
|
+
jsonrpc: "2.0",
|
|
978
|
+
error: {
|
|
979
|
+
code: -32e3,
|
|
980
|
+
message: "Method not allowed."
|
|
981
|
+
},
|
|
982
|
+
id: null
|
|
983
|
+
}), {
|
|
984
|
+
status: 405,
|
|
985
|
+
headers: {
|
|
986
|
+
Allow: "GET, POST, DELETE, OPTIONS",
|
|
987
|
+
"Content-Type": "application/json"
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
validateSession(request) {
|
|
992
|
+
if (this.sessionIdGenerator === void 0) return;
|
|
993
|
+
if (!this.initialized) return new Response(JSON.stringify({
|
|
994
|
+
jsonrpc: "2.0",
|
|
995
|
+
error: {
|
|
996
|
+
code: -32e3,
|
|
997
|
+
message: "Bad Request: Server not initialized"
|
|
998
|
+
},
|
|
999
|
+
id: null
|
|
1000
|
+
}), {
|
|
1001
|
+
status: 400,
|
|
1002
|
+
headers: {
|
|
1003
|
+
"Content-Type": "application/json",
|
|
1004
|
+
...this.getHeaders()
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
const sessionId = request.headers.get("mcp-session-id");
|
|
1008
|
+
if (!sessionId) return new Response(JSON.stringify({
|
|
1009
|
+
jsonrpc: "2.0",
|
|
1010
|
+
error: {
|
|
1011
|
+
code: -32e3,
|
|
1012
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
1013
|
+
},
|
|
1014
|
+
id: null
|
|
1015
|
+
}), {
|
|
1016
|
+
status: 400,
|
|
1017
|
+
headers: {
|
|
1018
|
+
"Content-Type": "application/json",
|
|
1019
|
+
...this.getHeaders()
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
if (sessionId !== this.sessionId) return new Response(JSON.stringify({
|
|
1023
|
+
jsonrpc: "2.0",
|
|
1024
|
+
error: {
|
|
1025
|
+
code: -32001,
|
|
1026
|
+
message: "Session not found"
|
|
1027
|
+
},
|
|
1028
|
+
id: null
|
|
1029
|
+
}), {
|
|
1030
|
+
status: 404,
|
|
1031
|
+
headers: {
|
|
1032
|
+
"Content-Type": "application/json",
|
|
1033
|
+
...this.getHeaders()
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
async close() {
|
|
1038
|
+
for (const { cleanup } of this.streamMapping.values()) cleanup();
|
|
1039
|
+
this.streamMapping.clear();
|
|
1040
|
+
this.requestResponseMap.clear();
|
|
1041
|
+
this.onclose?.();
|
|
1042
|
+
}
|
|
1043
|
+
async send(message) {
|
|
1044
|
+
let requestId;
|
|
1045
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) requestId = message.id;
|
|
1046
|
+
if (requestId === void 0) {
|
|
1047
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) throw new Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");
|
|
1048
|
+
const standaloneSse = this.streamMapping.get(this.standaloneSseStreamId);
|
|
1049
|
+
if (standaloneSse === void 0) return;
|
|
1050
|
+
if (standaloneSse.writer && standaloneSse.encoder) {
|
|
1051
|
+
const data = `event: message\ndata: ${JSON.stringify(message)}\n\n`;
|
|
1052
|
+
await standaloneSse.writer.write(standaloneSse.encoder.encode(data));
|
|
1053
|
+
}
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
const streamId = this.requestToStreamMapping.get(requestId);
|
|
1057
|
+
if (!streamId) throw new Error(`No connection established for request ID: ${String(requestId)}`);
|
|
1058
|
+
const response = this.streamMapping.get(streamId);
|
|
1059
|
+
if (!response) throw new Error(`No connection established for request ID: ${String(requestId)}`);
|
|
1060
|
+
if (!this.enableJsonResponse) {
|
|
1061
|
+
if (response.writer && response.encoder) {
|
|
1062
|
+
const data = `event: message\ndata: ${JSON.stringify(message)}\n\n`;
|
|
1063
|
+
await response.writer.write(response.encoder.encode(data));
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
|
|
1067
|
+
this.requestResponseMap.set(requestId, message);
|
|
1068
|
+
const relatedIds = Array.from(this.requestToStreamMapping.entries()).filter(([, sid]) => sid === streamId).map(([id]) => id);
|
|
1069
|
+
if (relatedIds.every((id) => this.requestResponseMap.has(id))) {
|
|
1070
|
+
if (this.enableJsonResponse && response.resolveJson) {
|
|
1071
|
+
const responses = relatedIds.map((id) => this.requestResponseMap.get(id));
|
|
1072
|
+
const headers = new Headers({
|
|
1073
|
+
"Content-Type": "application/json",
|
|
1074
|
+
...this.getHeaders()
|
|
1075
|
+
});
|
|
1076
|
+
if (this.sessionId !== void 0) headers.set("mcp-session-id", this.sessionId);
|
|
1077
|
+
const body = responses.length === 1 ? responses[0] : responses;
|
|
1078
|
+
response.resolveJson(new Response(JSON.stringify(body), { headers }));
|
|
1079
|
+
} else response.cleanup();
|
|
1080
|
+
for (const id of relatedIds) {
|
|
1081
|
+
this.requestResponseMap.delete(id);
|
|
1082
|
+
this.requestToStreamMapping.delete(id);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
//#endregion
|
|
1090
|
+
//#region src/mcp/auth-context.ts
|
|
1091
|
+
const authContextStorage = new AsyncLocalStorage();
|
|
1092
|
+
function getMcpAuthContext() {
|
|
1093
|
+
return authContextStorage.getStore();
|
|
1094
|
+
}
|
|
1095
|
+
function runWithAuthContext(context, fn) {
|
|
1096
|
+
return authContextStorage.run(context, fn);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
//#endregion
|
|
1100
|
+
//#region src/mcp/handler.ts
|
|
1101
|
+
function createMcpHandler(server, options = {}) {
|
|
1102
|
+
const route = options.route ?? "/mcp";
|
|
1103
|
+
return async (request, _env, ctx) => {
|
|
1104
|
+
const url = new URL(request.url);
|
|
1105
|
+
if (route && url.pathname !== route) return new Response("Not Found", { status: 404 });
|
|
1106
|
+
const oauthCtx = ctx;
|
|
1107
|
+
const authContext = oauthCtx.props ? { props: oauthCtx.props } : void 0;
|
|
1108
|
+
const transport = new WorkerTransport(options);
|
|
1109
|
+
await server.connect(transport);
|
|
1110
|
+
const handleRequest = async () => {
|
|
1111
|
+
return await transport.handleRequest(request);
|
|
1112
|
+
};
|
|
1113
|
+
try {
|
|
1114
|
+
if (authContext) return await runWithAuthContext(authContext, handleRequest);
|
|
1115
|
+
else return await handleRequest();
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
console.error("MCP handler error:", error);
|
|
1118
|
+
return new Response(JSON.stringify({
|
|
1119
|
+
jsonrpc: "2.0",
|
|
1120
|
+
error: {
|
|
1121
|
+
code: -32603,
|
|
1122
|
+
message: error instanceof Error ? error.message : "Internal server error"
|
|
1123
|
+
},
|
|
1124
|
+
id: null
|
|
1125
|
+
}), {
|
|
1126
|
+
status: 500,
|
|
1127
|
+
headers: { "Content-Type": "application/json" }
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
let didWarnAboutExperimentalCreateMcpHandler = false;
|
|
1133
|
+
/**
|
|
1134
|
+
* @deprecated This has been renamed to createMcpHandler, and experimental_createMcpHandler will be removed in the next major version
|
|
1135
|
+
*/
|
|
1136
|
+
function experimental_createMcpHandler(server, options = {}) {
|
|
1137
|
+
if (!didWarnAboutExperimentalCreateMcpHandler) {
|
|
1138
|
+
didWarnAboutExperimentalCreateMcpHandler = true;
|
|
1139
|
+
console.warn("experimental_createMcpHandler is deprecated, use createMcpHandler instead. experimental_createMcpHandler will be removed in the next major version.");
|
|
1140
|
+
}
|
|
1141
|
+
return createMcpHandler(server, options);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
627
1144
|
//#endregion
|
|
628
1145
|
//#region src/mcp/index.ts
|
|
629
1146
|
var McpAgent = class McpAgent extends Agent {
|
|
@@ -813,7 +1330,7 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
813
1330
|
/** Return a handler for the given path for this MCP.
|
|
814
1331
|
* Defaults to Streamable HTTP transport.
|
|
815
1332
|
*/
|
|
816
|
-
static serve(path, { binding = "MCP_OBJECT", corsOptions, transport = "streamable-http" } = {}) {
|
|
1333
|
+
static serve(path, { binding = "MCP_OBJECT", corsOptions, transport = "streamable-http", jurisdiction } = {}) {
|
|
817
1334
|
return { async fetch(request, env, ctx) {
|
|
818
1335
|
const corsResponse = handleCORS(request, corsOptions);
|
|
819
1336
|
if (corsResponse) return corsResponse;
|
|
@@ -822,8 +1339,14 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
822
1339
|
if (!isDurableObjectNamespace(bindingValue)) throw new Error(`Invalid McpAgent binding for ${binding}. Make sure it's a Durable Object binding.`);
|
|
823
1340
|
const namespace = bindingValue;
|
|
824
1341
|
switch (transport) {
|
|
825
|
-
case "streamable-http": return createStreamingHttpHandler(path, namespace,
|
|
826
|
-
|
|
1342
|
+
case "streamable-http": return createStreamingHttpHandler(path, namespace, {
|
|
1343
|
+
corsOptions,
|
|
1344
|
+
jurisdiction
|
|
1345
|
+
})(request, ctx);
|
|
1346
|
+
case "sse": return createLegacySseHandler(path, namespace, {
|
|
1347
|
+
corsOptions,
|
|
1348
|
+
jurisdiction
|
|
1349
|
+
})(request, ctx);
|
|
827
1350
|
default: return new Response("Invalid MCP transport mode. Only `streamable-http` or `sse` are allowed.", { status: 500 });
|
|
828
1351
|
}
|
|
829
1352
|
} };
|
|
@@ -843,5 +1366,5 @@ var McpAgent = class McpAgent extends Agent {
|
|
|
843
1366
|
};
|
|
844
1367
|
|
|
845
1368
|
//#endregion
|
|
846
|
-
export { ElicitRequestSchema, McpAgent, SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport };
|
|
1369
|
+
export { ElicitRequestSchema, McpAgent, SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport, WorkerTransport, createMcpHandler, experimental_createMcpHandler, getMcpAuthContext };
|
|
847
1370
|
//# sourceMappingURL=index.js.map
|