agents 0.1.3 → 0.1.5
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 +103 -5
- package/dist/_esm-LV5FJ3HK.js +3922 -0
- package/dist/_esm-LV5FJ3HK.js.map +1 -0
- package/dist/ai-chat-agent.js +12 -3
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.js +1 -0
- package/dist/ai-react.d.ts +6 -0
- package/dist/ai-react.js +43 -9
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +1 -0
- package/dist/ai-types.js +2 -1
- package/dist/ccip-CMBYN64O.js +15 -0
- package/dist/ccip-CMBYN64O.js.map +1 -0
- package/dist/chunk-5Y6BEZDY.js +276 -0
- package/dist/chunk-5Y6BEZDY.js.map +1 -0
- package/dist/{chunk-AVYJQSLW.js → chunk-BER7KXUJ.js} +2 -1
- package/dist/chunk-BER7KXUJ.js.map +1 -0
- package/dist/{chunk-YDUDMOL6.js → chunk-HS7VEROK.js} +7 -3
- package/dist/chunk-HS7VEROK.js.map +1 -0
- package/dist/chunk-JJBFIGUC.js +5202 -0
- package/dist/chunk-JJBFIGUC.js.map +1 -0
- package/dist/chunk-PR4QN5HX.js +43 -0
- package/dist/chunk-PR4QN5HX.js.map +1 -0
- package/dist/{chunk-MH46VMM4.js → chunk-SKACXF37.js} +2 -2
- package/dist/chunk-SKACXF37.js.map +1 -0
- package/dist/chunk-TYAY6AU6.js +159 -0
- package/dist/chunk-TYAY6AU6.js.map +1 -0
- package/dist/client.js +2 -1
- package/dist/index.js +4 -3
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.js +1 -0
- package/dist/mcp/index.d.ts +12 -17
- package/dist/mcp/index.js +252 -182
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +31 -0
- package/dist/mcp/x402.js +3195 -0
- package/dist/mcp/x402.js.map +1 -0
- package/dist/observability/index.js +4 -3
- package/dist/react.js +2 -1
- package/dist/react.js.map +1 -1
- package/dist/schedule.js +2 -0
- package/dist/schedule.js.map +1 -1
- package/dist/secp256k1-M22GZP2U.js +2193 -0
- package/dist/secp256k1-M22GZP2U.js.map +1 -0
- package/package.json +10 -5
- package/src/index.ts +8 -2
- package/dist/chunk-AVYJQSLW.js.map +0 -1
- package/dist/chunk-MH46VMM4.js.map +0 -1
- package/dist/chunk-YDUDMOL6.js.map +0 -1
package/dist/mcp/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Agent,
|
|
3
|
-
getAgentByName
|
|
4
|
-
|
|
3
|
+
getAgentByName,
|
|
4
|
+
getCurrentAgent
|
|
5
|
+
} from "../chunk-HS7VEROK.js";
|
|
5
6
|
import {
|
|
6
7
|
SSEEdgeClientTransport,
|
|
7
8
|
StreamableHTTPEdgeClientTransport
|
|
8
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-SKACXF37.js";
|
|
9
10
|
import "../chunk-LL2AFX7V.js";
|
|
10
11
|
import "../chunk-QEVM4BVL.js";
|
|
11
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-BER7KXUJ.js";
|
|
13
|
+
import "../chunk-PR4QN5HX.js";
|
|
12
14
|
|
|
13
15
|
// src/mcp/index.ts
|
|
14
16
|
import {
|
|
15
|
-
JSONRPCMessageSchema as
|
|
16
|
-
isJSONRPCError as
|
|
17
|
-
isJSONRPCNotification as isJSONRPCNotification2,
|
|
18
|
-
isJSONRPCRequest as isJSONRPCRequest2,
|
|
17
|
+
JSONRPCMessageSchema as JSONRPCMessageSchema3,
|
|
18
|
+
isJSONRPCError as isJSONRPCError2,
|
|
19
19
|
isJSONRPCResponse as isJSONRPCResponse3
|
|
20
20
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
21
|
|
|
@@ -24,12 +24,10 @@ import {
|
|
|
24
24
|
JSONRPCMessageSchema,
|
|
25
25
|
InitializeRequestSchema,
|
|
26
26
|
isJSONRPCResponse,
|
|
27
|
-
|
|
28
|
-
isJSONRPCNotification,
|
|
29
|
-
isJSONRPCRequest
|
|
27
|
+
isJSONRPCNotification
|
|
30
28
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
31
|
-
var
|
|
32
|
-
var
|
|
29
|
+
var MCP_HTTP_METHOD_HEADER = "cf-mcp-method";
|
|
30
|
+
var MCP_MESSAGE_HEADER = "cf-mcp-message";
|
|
33
31
|
var MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024;
|
|
34
32
|
var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
35
33
|
let pathname = basePath;
|
|
@@ -114,10 +112,10 @@ var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
114
|
messages = arrayMessage.map((msg) => JSONRPCMessageSchema.parse(msg));
|
|
117
|
-
const
|
|
115
|
+
const maybeInitializeRequest = messages.find(
|
|
118
116
|
(msg) => InitializeRequestSchema.safeParse(msg).success
|
|
119
117
|
);
|
|
120
|
-
if (
|
|
118
|
+
if (!!maybeInitializeRequest && sessionId) {
|
|
121
119
|
const body2 = JSON.stringify({
|
|
122
120
|
error: {
|
|
123
121
|
code: -32600,
|
|
@@ -128,7 +126,7 @@ var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
128
126
|
});
|
|
129
127
|
return new Response(body2, { status: 400 });
|
|
130
128
|
}
|
|
131
|
-
if (
|
|
129
|
+
if (!!maybeInitializeRequest && messages.length > 1) {
|
|
132
130
|
const body2 = JSON.stringify({
|
|
133
131
|
error: {
|
|
134
132
|
code: -32600,
|
|
@@ -139,7 +137,7 @@ var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
139
137
|
});
|
|
140
138
|
return new Response(body2, { status: 400 });
|
|
141
139
|
}
|
|
142
|
-
if (!
|
|
140
|
+
if (!maybeInitializeRequest && !sessionId) {
|
|
143
141
|
const body2 = JSON.stringify({
|
|
144
142
|
error: {
|
|
145
143
|
code: -32e3,
|
|
@@ -156,9 +154,9 @@ var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
156
154
|
`streamable-http:${sessionId}`,
|
|
157
155
|
{ props: ctx.props }
|
|
158
156
|
);
|
|
159
|
-
const isInitialized = await agent.
|
|
160
|
-
if (
|
|
161
|
-
await agent.
|
|
157
|
+
const isInitialized = await agent.getInitializeRequest();
|
|
158
|
+
if (maybeInitializeRequest) {
|
|
159
|
+
await agent.setInitializeRequest(maybeInitializeRequest);
|
|
162
160
|
} else if (!isInitialized) {
|
|
163
161
|
const body2 = JSON.stringify({
|
|
164
162
|
error: {
|
|
@@ -180,6 +178,8 @@ var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
180
178
|
const req = new Request(request.url, {
|
|
181
179
|
headers: {
|
|
182
180
|
...existingHeaders,
|
|
181
|
+
[MCP_HTTP_METHOD_HEADER]: "POST",
|
|
182
|
+
[MCP_MESSAGE_HEADER]: JSON.stringify(messages),
|
|
183
183
|
Upgrade: "websocket"
|
|
184
184
|
}
|
|
185
185
|
});
|
|
@@ -199,28 +199,20 @@ var createStreamingHttpHandler = (basePath, namespace, corsOptions) => {
|
|
|
199
199
|
});
|
|
200
200
|
return new Response(body2, { status: 500 });
|
|
201
201
|
}
|
|
202
|
-
const requestIds = /* @__PURE__ */ new Set();
|
|
203
202
|
ws.accept();
|
|
204
203
|
ws.addEventListener("message", (event) => {
|
|
205
204
|
async function onMessage(event2) {
|
|
206
205
|
try {
|
|
207
206
|
const data = typeof event2.data === "string" ? event2.data : new TextDecoder().decode(event2.data);
|
|
208
207
|
const message = JSON.parse(data);
|
|
209
|
-
|
|
210
|
-
if (!result.success) {
|
|
208
|
+
if (message.type !== "cf_mcp_agent_event" /* CF_MCP_AGENT_EVENT */) {
|
|
211
209
|
return;
|
|
212
210
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
const messageText = `event: message
|
|
217
|
-
data: ${JSON.stringify(result.data)}
|
|
218
|
-
|
|
219
|
-
`;
|
|
220
|
-
await writer.write(encoder.encode(messageText));
|
|
221
|
-
if (requestIds.size === 0) {
|
|
211
|
+
await writer.write(encoder.encode(message.event));
|
|
212
|
+
if (message.close) {
|
|
222
213
|
ws?.close();
|
|
223
|
-
await writer.close()
|
|
214
|
+
await writer.close().catch(() => {
|
|
215
|
+
});
|
|
224
216
|
}
|
|
225
217
|
} catch (error) {
|
|
226
218
|
console.error("Error forwarding message to SSE:", error);
|
|
@@ -230,20 +222,15 @@ data: ${JSON.stringify(result.data)}
|
|
|
230
222
|
});
|
|
231
223
|
ws.addEventListener("error", (error) => {
|
|
232
224
|
async function onError(_error) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
} catch (_e) {
|
|
236
|
-
}
|
|
225
|
+
await writer.close().catch(() => {
|
|
226
|
+
});
|
|
237
227
|
}
|
|
238
228
|
onError(error).catch(console.error);
|
|
239
229
|
});
|
|
240
230
|
ws.addEventListener("close", () => {
|
|
241
231
|
async function onClose() {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
} catch (error) {
|
|
245
|
-
console.error("Error closing SSE connection:", error);
|
|
246
|
-
}
|
|
232
|
+
await writer.close().catch(() => {
|
|
233
|
+
});
|
|
247
234
|
}
|
|
248
235
|
onClose().catch(console.error);
|
|
249
236
|
});
|
|
@@ -251,21 +238,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
251
238
|
(msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(msg)
|
|
252
239
|
);
|
|
253
240
|
if (hasOnlyNotificationsOrResponses) {
|
|
254
|
-
for (const message of messages) {
|
|
255
|
-
ws.send(JSON.stringify(message));
|
|
256
|
-
}
|
|
257
241
|
ws.close();
|
|
258
242
|
return new Response(null, {
|
|
259
243
|
headers: corsHeaders(request, corsOptions),
|
|
260
244
|
status: 202
|
|
261
245
|
});
|
|
262
246
|
}
|
|
263
|
-
for (const message of messages) {
|
|
264
|
-
if (isJSONRPCRequest(message)) {
|
|
265
|
-
requestIds.add(message.id);
|
|
266
|
-
}
|
|
267
|
-
ws.send(JSON.stringify(message));
|
|
268
|
-
}
|
|
269
247
|
return new Response(readable, {
|
|
270
248
|
headers: {
|
|
271
249
|
"Cache-Control": "no-cache",
|
|
@@ -289,9 +267,19 @@ data: ${JSON.stringify(result.data)}
|
|
|
289
267
|
});
|
|
290
268
|
return new Response(body2, { status: 406 });
|
|
291
269
|
}
|
|
292
|
-
const sessionId =
|
|
270
|
+
const sessionId = request.headers.get("mcp-session-id");
|
|
293
271
|
if (!sessionId)
|
|
294
|
-
return new Response(
|
|
272
|
+
return new Response(
|
|
273
|
+
JSON.stringify({
|
|
274
|
+
error: {
|
|
275
|
+
code: -32e3,
|
|
276
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
277
|
+
},
|
|
278
|
+
id: null,
|
|
279
|
+
jsonrpc: "2.0"
|
|
280
|
+
}),
|
|
281
|
+
{ status: 400 }
|
|
282
|
+
);
|
|
295
283
|
const { readable, writable } = new TransformStream();
|
|
296
284
|
const writer = writable.getWriter();
|
|
297
285
|
const encoder = new TextEncoder();
|
|
@@ -300,7 +288,7 @@ data: ${JSON.stringify(result.data)}
|
|
|
300
288
|
`streamable-http:${sessionId}`,
|
|
301
289
|
{ props: ctx.props }
|
|
302
290
|
);
|
|
303
|
-
const isInitialized = await agent.
|
|
291
|
+
const isInitialized = await agent.getInitializeRequest();
|
|
304
292
|
if (!isInitialized) {
|
|
305
293
|
return new Response(
|
|
306
294
|
JSON.stringify({
|
|
@@ -320,6 +308,7 @@ data: ${JSON.stringify(result.data)}
|
|
|
320
308
|
new Request(request.url, {
|
|
321
309
|
headers: {
|
|
322
310
|
...existingHeaders,
|
|
311
|
+
[MCP_HTTP_METHOD_HEADER]: "GET",
|
|
323
312
|
Upgrade: "websocket"
|
|
324
313
|
}
|
|
325
314
|
})
|
|
@@ -332,24 +321,15 @@ data: ${JSON.stringify(result.data)}
|
|
|
332
321
|
});
|
|
333
322
|
}
|
|
334
323
|
ws.accept();
|
|
335
|
-
ws.send(
|
|
336
|
-
JSON.stringify({
|
|
337
|
-
jsonrpc: "2.0",
|
|
338
|
-
method: STANDALONE_SSE_METHOD,
|
|
339
|
-
params: {}
|
|
340
|
-
})
|
|
341
|
-
);
|
|
342
324
|
ws.addEventListener("message", (event) => {
|
|
343
325
|
try {
|
|
344
326
|
async function onMessage(ev) {
|
|
345
327
|
const data = typeof ev.data === "string" ? ev.data : new TextDecoder().decode(ev.data);
|
|
346
|
-
const
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
`;
|
|
352
|
-
await writer.write(encoder.encode(frame));
|
|
328
|
+
const message = JSON.parse(data);
|
|
329
|
+
if (message.type !== "cf_mcp_agent_event" /* CF_MCP_AGENT_EVENT */) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
await writer.write(encoder.encode(message.event));
|
|
353
333
|
}
|
|
354
334
|
onMessage(event).catch(console.error);
|
|
355
335
|
} catch (e) {
|
|
@@ -393,7 +373,7 @@ data: ${JSON.stringify(parsed.data)}
|
|
|
393
373
|
namespace,
|
|
394
374
|
`streamable-http:${sessionId}`
|
|
395
375
|
);
|
|
396
|
-
const isInitialized = await agent.
|
|
376
|
+
const isInitialized = await agent.getInitializeRequest();
|
|
397
377
|
if (!isInitialized) {
|
|
398
378
|
return new Response(
|
|
399
379
|
JSON.stringify({
|
|
@@ -592,8 +572,10 @@ function isDurableObjectNamespace(namespace) {
|
|
|
592
572
|
|
|
593
573
|
// src/mcp/transport.ts
|
|
594
574
|
import {
|
|
595
|
-
isJSONRPCError
|
|
596
|
-
|
|
575
|
+
isJSONRPCError,
|
|
576
|
+
isJSONRPCRequest,
|
|
577
|
+
isJSONRPCResponse as isJSONRPCResponse2,
|
|
578
|
+
JSONRPCMessageSchema as JSONRPCMessageSchema2
|
|
597
579
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
598
580
|
var McpSSETransport = class {
|
|
599
581
|
constructor(getWebSocket) {
|
|
@@ -624,59 +606,190 @@ var McpSSETransport = class {
|
|
|
624
606
|
this.onclose?.();
|
|
625
607
|
}
|
|
626
608
|
};
|
|
627
|
-
var
|
|
628
|
-
constructor(
|
|
609
|
+
var StreamableHTTPServerTransport = class {
|
|
610
|
+
constructor(options) {
|
|
629
611
|
this._started = false;
|
|
630
|
-
|
|
631
|
-
this
|
|
632
|
-
|
|
612
|
+
// This is to keep track whether all messages from a single POST request have been answered.
|
|
613
|
+
// I's fine that we don't persist this since it's only for backwards compatibility as clients
|
|
614
|
+
// should no longer batch requests, per the spec.
|
|
615
|
+
this._requestResponseMap = /* @__PURE__ */ new Map();
|
|
616
|
+
const { agent } = getCurrentAgent();
|
|
617
|
+
if (!agent)
|
|
618
|
+
throw new Error("McpAgent was not found in Transport constructor");
|
|
619
|
+
this.sessionId = agent.getSessionId();
|
|
620
|
+
this._eventStore = options.eventStore;
|
|
633
621
|
}
|
|
622
|
+
/**
|
|
623
|
+
* Starts the transport. This is required by the Transport interface but is a no-op
|
|
624
|
+
* for the Streamable HTTP transport as connections are managed per-request.
|
|
625
|
+
*/
|
|
634
626
|
async start() {
|
|
635
627
|
if (this._started) {
|
|
636
628
|
throw new Error("Transport already started");
|
|
637
629
|
}
|
|
638
630
|
this._started = true;
|
|
639
631
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
632
|
+
/**
|
|
633
|
+
* Handles GET requests for SSE stream
|
|
634
|
+
*/
|
|
635
|
+
async handleGetRequest(req) {
|
|
636
|
+
const { connection } = getCurrentAgent();
|
|
637
|
+
if (!connection)
|
|
638
|
+
throw new Error("Connection was not found in handleGetRequest");
|
|
639
|
+
if (this._eventStore) {
|
|
640
|
+
const lastEventId = req.headers.get("last-event-id");
|
|
641
|
+
if (lastEventId) {
|
|
642
|
+
await this.replayEvents(lastEventId);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
643
645
|
}
|
|
646
|
+
connection.setState({
|
|
647
|
+
_standaloneSse: true
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Replays events that would have been sent after the specified event ID
|
|
652
|
+
* Only used when resumability is enabled
|
|
653
|
+
*/
|
|
654
|
+
async replayEvents(lastEventId) {
|
|
655
|
+
if (!this._eventStore) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const { connection } = getCurrentAgent();
|
|
659
|
+
if (!connection)
|
|
660
|
+
throw new Error("Connection was not available in replayEvents");
|
|
661
|
+
try {
|
|
662
|
+
await this._eventStore?.replayEventsAfter(lastEventId, {
|
|
663
|
+
send: async (eventId, message) => {
|
|
664
|
+
try {
|
|
665
|
+
this.writeSSEEvent(connection, message, eventId);
|
|
666
|
+
} catch (error) {
|
|
667
|
+
this.onerror?.(error);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
} catch (error) {
|
|
672
|
+
this.onerror?.(error);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Writes an event to the SSE stream with proper formatting
|
|
677
|
+
*/
|
|
678
|
+
writeSSEEvent(connection, message, eventId, close) {
|
|
679
|
+
let eventData = "event: message\n";
|
|
680
|
+
if (eventId) {
|
|
681
|
+
eventData += `id: ${eventId}
|
|
682
|
+
`;
|
|
683
|
+
}
|
|
684
|
+
eventData += `data: ${JSON.stringify(message)}
|
|
685
|
+
|
|
686
|
+
`;
|
|
687
|
+
return connection.send(
|
|
688
|
+
JSON.stringify({
|
|
689
|
+
type: "cf_mcp_agent_event" /* CF_MCP_AGENT_EVENT */,
|
|
690
|
+
event: eventData,
|
|
691
|
+
close
|
|
692
|
+
})
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Handles POST requests containing JSON-RPC messages
|
|
697
|
+
*/
|
|
698
|
+
async handlePostRequest(req, parsedBody) {
|
|
699
|
+
const authInfo = req.auth;
|
|
700
|
+
const requestInfo = {
|
|
701
|
+
headers: Object.fromEntries(req.headers.entries())
|
|
702
|
+
};
|
|
703
|
+
delete requestInfo.headers[MCP_HTTP_METHOD_HEADER];
|
|
704
|
+
delete requestInfo.headers[MCP_MESSAGE_HEADER];
|
|
705
|
+
delete requestInfo.headers.upgrade;
|
|
706
|
+
const rawMessage = parsedBody;
|
|
707
|
+
let messages;
|
|
708
|
+
if (Array.isArray(rawMessage)) {
|
|
709
|
+
messages = rawMessage.map((msg) => JSONRPCMessageSchema2.parse(msg));
|
|
710
|
+
} else {
|
|
711
|
+
messages = [JSONRPCMessageSchema2.parse(rawMessage)];
|
|
712
|
+
}
|
|
713
|
+
const hasRequests = messages.some(isJSONRPCRequest);
|
|
714
|
+
if (!hasRequests) {
|
|
715
|
+
for (const message of messages) {
|
|
716
|
+
this.onmessage?.(message, { authInfo, requestInfo });
|
|
717
|
+
}
|
|
718
|
+
} else if (hasRequests) {
|
|
719
|
+
const { connection } = getCurrentAgent();
|
|
720
|
+
if (!connection)
|
|
721
|
+
throw new Error("Connection was not found in handlePostRequest");
|
|
722
|
+
const requestIds = messages.filter(isJSONRPCRequest).map((message) => message.id);
|
|
723
|
+
connection.setState({
|
|
724
|
+
requestIds
|
|
725
|
+
});
|
|
726
|
+
for (const message of messages) {
|
|
727
|
+
this.onmessage?.(message, { authInfo, requestInfo });
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
async close() {
|
|
732
|
+
const { agent } = getCurrentAgent();
|
|
733
|
+
if (!agent) throw new Error("Agent was not found in close");
|
|
734
|
+
for (const conn of agent.getConnections()) {
|
|
735
|
+
conn.close(1e3, "Session closed");
|
|
736
|
+
}
|
|
737
|
+
this.onclose?.();
|
|
738
|
+
}
|
|
739
|
+
async send(message, options) {
|
|
740
|
+
const { agent } = getCurrentAgent();
|
|
741
|
+
if (!agent) throw new Error("Agent was not found in send");
|
|
644
742
|
let requestId = options?.relatedRequestId;
|
|
645
|
-
if (isJSONRPCResponse2(message) ||
|
|
743
|
+
if (isJSONRPCResponse2(message) || isJSONRPCError(message)) {
|
|
646
744
|
requestId = message.id;
|
|
647
745
|
}
|
|
648
746
|
if (requestId === void 0) {
|
|
649
|
-
if (isJSONRPCResponse2(message) ||
|
|
747
|
+
if (isJSONRPCResponse2(message) || isJSONRPCError(message)) {
|
|
650
748
|
throw new Error(
|
|
651
749
|
"Cannot send a response on a standalone SSE stream unless resuming a previous client request"
|
|
652
750
|
);
|
|
653
751
|
}
|
|
654
|
-
|
|
655
|
-
|
|
752
|
+
let standaloneConnection;
|
|
753
|
+
for (const conn of agent.getConnections()) {
|
|
754
|
+
if (conn.state?._standaloneSse) standaloneConnection = conn;
|
|
755
|
+
}
|
|
756
|
+
if (standaloneConnection === void 0) {
|
|
656
757
|
return;
|
|
657
758
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
759
|
+
let eventId2;
|
|
760
|
+
if (this._eventStore) {
|
|
761
|
+
eventId2 = await this._eventStore.storeEvent(
|
|
762
|
+
standaloneConnection.id,
|
|
763
|
+
message
|
|
764
|
+
);
|
|
662
765
|
}
|
|
766
|
+
this.writeSSEEvent(standaloneConnection, message, eventId2);
|
|
663
767
|
return;
|
|
664
768
|
}
|
|
665
|
-
const
|
|
666
|
-
|
|
667
|
-
|
|
769
|
+
const connection = Array.from(
|
|
770
|
+
agent.getConnections()
|
|
771
|
+
).find((conn) => conn.state?.requestIds?.includes(requestId));
|
|
772
|
+
if (!connection) {
|
|
773
|
+
throw new Error(
|
|
774
|
+
`No connection established for request ID: ${String(requestId)}`
|
|
775
|
+
);
|
|
668
776
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
777
|
+
let eventId;
|
|
778
|
+
if (this._eventStore) {
|
|
779
|
+
eventId = await this._eventStore.storeEvent(connection.id, message);
|
|
780
|
+
}
|
|
781
|
+
let shouldClose = false;
|
|
782
|
+
if (isJSONRPCResponse2(message) || isJSONRPCError(message)) {
|
|
783
|
+
this._requestResponseMap.set(requestId, message);
|
|
784
|
+
const relatedIds = connection.state?.requestIds ?? [];
|
|
785
|
+
shouldClose = relatedIds.every((id) => this._requestResponseMap.has(id));
|
|
786
|
+
if (shouldClose) {
|
|
787
|
+
for (const id of relatedIds) {
|
|
788
|
+
this._requestResponseMap.delete(id);
|
|
789
|
+
}
|
|
673
790
|
}
|
|
674
|
-
} catch (error) {
|
|
675
|
-
this.onerror?.(error);
|
|
676
791
|
}
|
|
677
|
-
|
|
678
|
-
async close() {
|
|
679
|
-
this.onclose?.();
|
|
792
|
+
this.writeSSEEvent(connection, message, eventId, shouldClose);
|
|
680
793
|
}
|
|
681
794
|
};
|
|
682
795
|
|
|
@@ -685,25 +798,14 @@ import {
|
|
|
685
798
|
ElicitRequestSchema
|
|
686
799
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
687
800
|
var McpAgent = class _McpAgent extends Agent {
|
|
688
|
-
constructor(ctx, env) {
|
|
689
|
-
super(ctx, env);
|
|
690
|
-
this._requestIdToConnectionId = /* @__PURE__ */ new Map();
|
|
691
|
-
for (const connection of this.getConnections()) {
|
|
692
|
-
const meta = connection.state;
|
|
693
|
-
if (meta?.role === STANDALONE_SSE_MARKER) {
|
|
694
|
-
this._standaloneSseConnectionId = connection.id;
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
801
|
/*
|
|
700
802
|
* Helpers
|
|
701
803
|
*/
|
|
702
|
-
async
|
|
703
|
-
await this.ctx.storage.put("
|
|
804
|
+
async setInitializeRequest(initializeRequest) {
|
|
805
|
+
await this.ctx.storage.put("initializeRequest", initializeRequest);
|
|
704
806
|
}
|
|
705
|
-
async
|
|
706
|
-
return
|
|
807
|
+
async getInitializeRequest() {
|
|
808
|
+
return this.ctx.storage.get("initializeRequest");
|
|
707
809
|
}
|
|
708
810
|
/** Read the transport type for this agent.
|
|
709
811
|
* This relies on the naming scheme being `sse:${sessionId}`
|
|
@@ -722,10 +824,18 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
722
824
|
);
|
|
723
825
|
}
|
|
724
826
|
}
|
|
725
|
-
/**
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
827
|
+
/** Read the sessionId for this agent.
|
|
828
|
+
* This relies on the naming scheme being `sse:${sessionId}`
|
|
829
|
+
* or `streamable-http:${sessionId}`.
|
|
830
|
+
*/
|
|
831
|
+
getSessionId() {
|
|
832
|
+
const [_, sessionId] = this.name.split(":");
|
|
833
|
+
if (!sessionId) {
|
|
834
|
+
throw new Error(
|
|
835
|
+
"Invalid session id. McpAgent must be addressed with a valid session id."
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
return sessionId;
|
|
729
839
|
}
|
|
730
840
|
/** Get the unique WebSocket. SSE transport only. */
|
|
731
841
|
getWebSocket() {
|
|
@@ -735,14 +845,6 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
735
845
|
}
|
|
736
846
|
return websockets[0];
|
|
737
847
|
}
|
|
738
|
-
/** Get the corresponding WebSocket for a responseId. Streamable HTTP only. */
|
|
739
|
-
getWebSocketForResponseID(id) {
|
|
740
|
-
const connectionId = this._requestIdToConnectionId.get(id);
|
|
741
|
-
if (connectionId === void 0) {
|
|
742
|
-
return null;
|
|
743
|
-
}
|
|
744
|
-
return this.getConnection(connectionId) ?? null;
|
|
745
|
-
}
|
|
746
848
|
/** Returns a new transport matching the type of the Agent. */
|
|
747
849
|
initTransport() {
|
|
748
850
|
switch (this.getTransportType()) {
|
|
@@ -750,11 +852,7 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
750
852
|
return new McpSSETransport(() => this.getWebSocket());
|
|
751
853
|
}
|
|
752
854
|
case "streamable-http": {
|
|
753
|
-
return new
|
|
754
|
-
(id) => this.getWebSocketForResponseID(id),
|
|
755
|
-
(id) => this._requestIdToConnectionId.delete(id),
|
|
756
|
-
() => this.getWebSocketForStandaloneSse()
|
|
757
|
-
);
|
|
855
|
+
return new StreamableHTTPServerTransport({});
|
|
758
856
|
}
|
|
759
857
|
}
|
|
760
858
|
}
|
|
@@ -763,6 +861,12 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
763
861
|
await this.ctx.storage.put("props", props ?? {});
|
|
764
862
|
this.props = props;
|
|
765
863
|
}
|
|
864
|
+
async reinitializeServer() {
|
|
865
|
+
const initializeRequest = await this.getInitializeRequest();
|
|
866
|
+
if (initializeRequest) {
|
|
867
|
+
this._transport?.onmessage?.(initializeRequest);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
766
870
|
/*
|
|
767
871
|
* Base Agent / Parykit Server overrides
|
|
768
872
|
*/
|
|
@@ -774,9 +878,10 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
774
878
|
const server = await this.server;
|
|
775
879
|
this._transport = this.initTransport();
|
|
776
880
|
await server.connect(this._transport);
|
|
881
|
+
await this.reinitializeServer();
|
|
777
882
|
}
|
|
778
883
|
/** Validates new WebSocket connections. */
|
|
779
|
-
async onConnect(conn,
|
|
884
|
+
async onConnect(conn, { request: req }) {
|
|
780
885
|
switch (this.getTransportType()) {
|
|
781
886
|
case "sse": {
|
|
782
887
|
const websockets = Array.from(this.getConnections());
|
|
@@ -787,54 +892,19 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
787
892
|
break;
|
|
788
893
|
}
|
|
789
894
|
case "streamable-http":
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
try {
|
|
804
|
-
const data = typeof event === "string" ? event : new TextDecoder().decode(event);
|
|
805
|
-
message = JSONRPCMessageSchema2.parse(JSON.parse(data));
|
|
806
|
-
} catch (error) {
|
|
807
|
-
this._transport?.onerror?.(error);
|
|
808
|
-
return;
|
|
809
|
-
}
|
|
810
|
-
if (isJSONRPCNotification2(message) && message.method === STANDALONE_SSE_METHOD) {
|
|
811
|
-
if (this._standaloneSseConnectionId && this._standaloneSseConnectionId !== connection.id) {
|
|
812
|
-
const standaloneSseSocket = this.getConnection(
|
|
813
|
-
this._standaloneSseConnectionId
|
|
814
|
-
);
|
|
815
|
-
standaloneSseSocket?.close(1e3, "replaced");
|
|
816
|
-
}
|
|
817
|
-
connection.setState({
|
|
818
|
-
role: STANDALONE_SSE_MARKER
|
|
819
|
-
});
|
|
820
|
-
this._standaloneSseConnectionId = connection.id;
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
if (await this._handleElicitationResponse(message)) {
|
|
824
|
-
return;
|
|
825
|
-
}
|
|
826
|
-
if (isJSONRPCRequest2(message)) {
|
|
827
|
-
this._requestIdToConnectionId.set(message.id.toString(), connection.id);
|
|
828
|
-
}
|
|
829
|
-
this._transport?.onmessage?.(message);
|
|
830
|
-
}
|
|
831
|
-
/** Remove clients from our cache when they disconnect */
|
|
832
|
-
async onClose(conn, _code, _reason, _wasClean) {
|
|
833
|
-
for (const [reqId, connId] of this._requestIdToConnectionId) {
|
|
834
|
-
if (connId === conn.id) this._requestIdToConnectionId.delete(reqId);
|
|
835
|
-
}
|
|
836
|
-
if (this._standaloneSseConnectionId === conn.id) {
|
|
837
|
-
this._standaloneSseConnectionId = void 0;
|
|
895
|
+
if (this._transport instanceof StreamableHTTPServerTransport) {
|
|
896
|
+
switch (req.headers.get(MCP_HTTP_METHOD_HEADER)) {
|
|
897
|
+
case "POST": {
|
|
898
|
+
const payloadHeader = req.headers.get(MCP_MESSAGE_HEADER);
|
|
899
|
+
const parsedBody = await JSON.parse(payloadHeader ?? "{}");
|
|
900
|
+
this._transport?.handlePostRequest(req, parsedBody);
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
case "GET":
|
|
904
|
+
this._transport?.handleGetRequest(req);
|
|
905
|
+
break;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
838
908
|
}
|
|
839
909
|
}
|
|
840
910
|
/*
|
|
@@ -848,7 +918,7 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
848
918
|
try {
|
|
849
919
|
let parsedMessage;
|
|
850
920
|
try {
|
|
851
|
-
parsedMessage =
|
|
921
|
+
parsedMessage = JSONRPCMessageSchema3.parse(messageBody);
|
|
852
922
|
} catch (error) {
|
|
853
923
|
this._transport?.onerror?.(error);
|
|
854
924
|
throw error;
|
|
@@ -937,7 +1007,7 @@ var McpAgent = class _McpAgent extends Agent {
|
|
|
937
1007
|
);
|
|
938
1008
|
return true;
|
|
939
1009
|
}
|
|
940
|
-
if (
|
|
1010
|
+
if (isJSONRPCError2(message)) {
|
|
941
1011
|
const requestId = message.id?.toString();
|
|
942
1012
|
if (!requestId || !requestId.startsWith("elicit_")) return false;
|
|
943
1013
|
const pendingRequest = await this.ctx.storage.get(
|