agents 0.0.0-5342ce4 → 0.0.0-5460fd0
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 +46 -4
- package/dist/ai-chat-agent.js +138 -68
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +17 -4
- package/dist/ai-react.js +33 -27
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +5 -0
- package/dist/chunk-767EASBA.js +106 -0
- package/dist/chunk-767EASBA.js.map +1 -0
- package/dist/{chunk-XG52S6YY.js → chunk-CGWTDCBQ.js} +360 -160
- package/dist/chunk-CGWTDCBQ.js.map +1 -0
- package/dist/chunk-E3LCYPCB.js +469 -0
- package/dist/chunk-E3LCYPCB.js.map +1 -0
- package/dist/chunk-NKZZ66QY.js +116 -0
- package/dist/chunk-NKZZ66QY.js.map +1 -0
- package/dist/client.d.ts +15 -1
- package/dist/client.js +6 -126
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +124 -14
- package/dist/index.js +8 -6
- package/dist/mcp/client.d.ts +33 -13
- package/dist/mcp/client.js +3 -402
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +3 -3
- package/dist/mcp/do-oauth-client-provider.js +3 -103
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +30 -8
- package/dist/mcp/index.js +174 -173
- package/dist/mcp/index.js.map +1 -1
- package/dist/react.d.ts +85 -5
- package/dist/react.js +20 -8
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +2 -2
- package/dist/schedule.js +4 -6
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +32 -0
- package/dist/serializable.js +1 -0
- package/package.json +71 -68
- package/src/index.ts +431 -86
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-XG52S6YY.js.map +0 -1
- /package/dist/{chunk-HMLY7DHA.js.map → serializable.js.map} +0 -0
package/dist/mcp/index.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Agent
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
__privateMethod,
|
|
8
|
-
__privateSet
|
|
9
|
-
} from "../chunk-HMLY7DHA.js";
|
|
3
|
+
} from "../chunk-CGWTDCBQ.js";
|
|
4
|
+
import "../chunk-E3LCYPCB.js";
|
|
5
|
+
import "../chunk-767EASBA.js";
|
|
6
|
+
import "../chunk-NKZZ66QY.js";
|
|
10
7
|
|
|
11
8
|
// src/mcp/index.ts
|
|
12
9
|
import { DurableObject } from "cloudflare:workers";
|
|
@@ -19,37 +16,41 @@ import {
|
|
|
19
16
|
JSONRPCMessageSchema
|
|
20
17
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
18
|
var MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024;
|
|
22
|
-
function
|
|
23
|
-
const origin =
|
|
24
|
-
|
|
25
|
-
"Access-Control-Allow-
|
|
26
|
-
"Access-Control-Allow-Methods": corsOptions
|
|
27
|
-
"Access-Control-Allow-
|
|
28
|
-
"Access-Control-
|
|
19
|
+
function corsHeaders(_request, corsOptions = {}) {
|
|
20
|
+
const origin = "*";
|
|
21
|
+
return {
|
|
22
|
+
"Access-Control-Allow-Headers": corsOptions.headers || "Content-Type, mcp-session-id, mcp-protocol-version",
|
|
23
|
+
"Access-Control-Allow-Methods": corsOptions.methods || "GET, POST, OPTIONS",
|
|
24
|
+
"Access-Control-Allow-Origin": corsOptions.origin || origin,
|
|
25
|
+
"Access-Control-Expose-Headers": corsOptions.exposeHeaders || "mcp-session-id",
|
|
26
|
+
"Access-Control-Max-Age": (corsOptions.maxAge || 86400).toString()
|
|
29
27
|
};
|
|
28
|
+
}
|
|
29
|
+
function isDurableObjectNamespace(namespace) {
|
|
30
|
+
return typeof namespace === "object" && namespace !== null && "newUniqueId" in namespace && typeof namespace.newUniqueId === "function" && "idFromName" in namespace && typeof namespace.idFromName === "function";
|
|
31
|
+
}
|
|
32
|
+
function handleCORS(request, corsOptions) {
|
|
30
33
|
if (request.method === "OPTIONS") {
|
|
31
|
-
return new Response(null, { headers: corsHeaders });
|
|
34
|
+
return new Response(null, { headers: corsHeaders(request, corsOptions) });
|
|
32
35
|
}
|
|
33
36
|
return null;
|
|
34
37
|
}
|
|
35
|
-
var _getWebSocket, _started;
|
|
36
38
|
var McpSSETransport = class {
|
|
37
39
|
constructor(getWebSocket) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
__privateSet(this, _getWebSocket, getWebSocket);
|
|
40
|
+
this._started = false;
|
|
41
|
+
this._getWebSocket = getWebSocket;
|
|
41
42
|
}
|
|
42
43
|
async start() {
|
|
43
|
-
if (
|
|
44
|
+
if (this._started) {
|
|
44
45
|
throw new Error("Transport already started");
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
+
this._started = true;
|
|
47
48
|
}
|
|
48
49
|
async send(message) {
|
|
49
|
-
if (!
|
|
50
|
+
if (!this._started) {
|
|
50
51
|
throw new Error("Transport not started");
|
|
51
52
|
}
|
|
52
|
-
const websocket =
|
|
53
|
+
const websocket = this._getWebSocket();
|
|
53
54
|
if (!websocket) {
|
|
54
55
|
throw new Error("WebSocket not connected");
|
|
55
56
|
}
|
|
@@ -64,52 +65,40 @@ var McpSSETransport = class {
|
|
|
64
65
|
this.onclose?.();
|
|
65
66
|
}
|
|
66
67
|
};
|
|
67
|
-
_getWebSocket = new WeakMap();
|
|
68
|
-
_started = new WeakMap();
|
|
69
|
-
var _getWebSocketForGetRequest, _getWebSocketForMessageID, _notifyResponseIdSent, _started2;
|
|
70
68
|
var McpStreamableHttpTransport = class {
|
|
71
69
|
constructor(getWebSocketForMessageID, notifyResponseIdSent) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
__privateAdd(this, _getWebSocketForMessageID);
|
|
77
|
-
// Notify the server that a response has been sent for a given message id
|
|
78
|
-
// so that it may clean up it's mapping of message ids to connections
|
|
79
|
-
// once they are no longer needed
|
|
80
|
-
__privateAdd(this, _notifyResponseIdSent);
|
|
81
|
-
__privateAdd(this, _started2, false);
|
|
82
|
-
__privateSet(this, _getWebSocketForMessageID, getWebSocketForMessageID);
|
|
83
|
-
__privateSet(this, _notifyResponseIdSent, notifyResponseIdSent);
|
|
84
|
-
__privateSet(this, _getWebSocketForGetRequest, () => null);
|
|
70
|
+
this._started = false;
|
|
71
|
+
this._getWebSocketForMessageID = getWebSocketForMessageID;
|
|
72
|
+
this._notifyResponseIdSent = notifyResponseIdSent;
|
|
73
|
+
this._getWebSocketForGetRequest = () => null;
|
|
85
74
|
}
|
|
86
75
|
async start() {
|
|
87
|
-
if (
|
|
76
|
+
if (this._started) {
|
|
88
77
|
throw new Error("Transport already started");
|
|
89
78
|
}
|
|
90
|
-
|
|
79
|
+
this._started = true;
|
|
91
80
|
}
|
|
92
81
|
async send(message) {
|
|
93
|
-
if (!
|
|
82
|
+
if (!this._started) {
|
|
94
83
|
throw new Error("Transport not started");
|
|
95
84
|
}
|
|
96
85
|
let websocket = null;
|
|
97
86
|
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
|
|
98
|
-
websocket =
|
|
87
|
+
websocket = this._getWebSocketForMessageID(message.id.toString());
|
|
99
88
|
if (!websocket) {
|
|
100
89
|
throw new Error(
|
|
101
90
|
`Could not find WebSocket for message id: ${message.id}`
|
|
102
91
|
);
|
|
103
92
|
}
|
|
104
93
|
} else if (isJSONRPCRequest(message)) {
|
|
105
|
-
websocket =
|
|
94
|
+
websocket = this._getWebSocketForGetRequest();
|
|
106
95
|
} else if (isJSONRPCNotification(message)) {
|
|
107
96
|
websocket = null;
|
|
108
97
|
}
|
|
109
98
|
try {
|
|
110
99
|
websocket?.send(JSON.stringify(message));
|
|
111
100
|
if (isJSONRPCResponse(message)) {
|
|
112
|
-
|
|
101
|
+
this._notifyResponseIdSent(message.id.toString());
|
|
113
102
|
}
|
|
114
103
|
} catch (error) {
|
|
115
104
|
this.onerror?.(error);
|
|
@@ -120,28 +109,16 @@ var McpStreamableHttpTransport = class {
|
|
|
120
109
|
this.onclose?.();
|
|
121
110
|
}
|
|
122
111
|
};
|
|
123
|
-
|
|
124
|
-
_getWebSocketForMessageID = new WeakMap();
|
|
125
|
-
_notifyResponseIdSent = new WeakMap();
|
|
126
|
-
_started2 = new WeakMap();
|
|
127
|
-
var _status, _transport, _transportType, _requestIdToConnectionId, _agent, _McpAgent_instances, initialize_fn;
|
|
128
|
-
var _McpAgent = class _McpAgent extends DurableObject {
|
|
112
|
+
var McpAgent = class _McpAgent extends DurableObject {
|
|
129
113
|
constructor(ctx, env) {
|
|
130
114
|
var _a;
|
|
131
115
|
super(ctx, env);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
__privateAdd(this, _transportType, "unset");
|
|
136
|
-
__privateAdd(this, _requestIdToConnectionId, /* @__PURE__ */ new Map());
|
|
137
|
-
/**
|
|
138
|
-
* Since McpAgent's _aren't_ yet real "Agents", let's only expose a couple of the methods
|
|
139
|
-
* to the outer class: initialState/state/setState/onStateUpdate/sql
|
|
140
|
-
*/
|
|
141
|
-
__privateAdd(this, _agent);
|
|
116
|
+
this._status = "zero";
|
|
117
|
+
this._transportType = "unset";
|
|
118
|
+
this._requestIdToConnectionId = /* @__PURE__ */ new Map();
|
|
142
119
|
this.initRun = false;
|
|
143
120
|
const self = this;
|
|
144
|
-
|
|
121
|
+
this._agent = new (_a = class extends Agent {
|
|
145
122
|
onStateUpdate(state, source) {
|
|
146
123
|
return self.onStateUpdate(state, source);
|
|
147
124
|
}
|
|
@@ -150,23 +127,27 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
150
127
|
}
|
|
151
128
|
}, _a.options = {
|
|
152
129
|
hibernate: true
|
|
153
|
-
}, _a)(ctx, env)
|
|
130
|
+
}, _a)(ctx, env);
|
|
131
|
+
}
|
|
132
|
+
get mcp() {
|
|
133
|
+
return this._agent.mcp;
|
|
154
134
|
}
|
|
155
135
|
get state() {
|
|
156
|
-
return
|
|
136
|
+
return this._agent.state;
|
|
157
137
|
}
|
|
158
138
|
sql(strings, ...values) {
|
|
159
|
-
return
|
|
139
|
+
return this._agent.sql(strings, ...values);
|
|
160
140
|
}
|
|
161
141
|
setState(state) {
|
|
162
|
-
return
|
|
142
|
+
return this._agent.setState(state);
|
|
163
143
|
}
|
|
144
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: overriden later
|
|
164
145
|
onStateUpdate(state, source) {
|
|
165
146
|
}
|
|
166
147
|
async onStart() {
|
|
167
148
|
var _a;
|
|
168
149
|
const self = this;
|
|
169
|
-
|
|
150
|
+
this._agent = new (_a = class extends Agent {
|
|
170
151
|
constructor() {
|
|
171
152
|
super(...arguments);
|
|
172
153
|
this.initialState = self.initialState;
|
|
@@ -179,21 +160,22 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
179
160
|
}
|
|
180
161
|
}, _a.options = {
|
|
181
162
|
hibernate: true
|
|
182
|
-
}, _a)(this.ctx, this.env)
|
|
163
|
+
}, _a)(this.ctx, this.env);
|
|
183
164
|
this.props = await this.ctx.storage.get("props");
|
|
184
|
-
|
|
165
|
+
this._transportType = await this.ctx.storage.get(
|
|
185
166
|
"transportType"
|
|
186
|
-
)
|
|
167
|
+
);
|
|
187
168
|
await this._init(this.props);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
169
|
+
const server = await this.server;
|
|
170
|
+
if (this._transportType === "sse") {
|
|
171
|
+
this._transport = new McpSSETransport(() => this.getWebSocket());
|
|
172
|
+
await server.connect(this._transport);
|
|
173
|
+
} else if (this._transportType === "streamable-http") {
|
|
174
|
+
this._transport = new McpStreamableHttpTransport(
|
|
193
175
|
(id) => this.getWebSocketForResponseID(id),
|
|
194
|
-
(id) =>
|
|
195
|
-
)
|
|
196
|
-
await
|
|
176
|
+
(id) => this._requestIdToConnectionId.delete(id)
|
|
177
|
+
);
|
|
178
|
+
await server.connect(this._transport);
|
|
197
179
|
}
|
|
198
180
|
}
|
|
199
181
|
async _init(props) {
|
|
@@ -213,10 +195,17 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
213
195
|
async isInitialized() {
|
|
214
196
|
return await this.ctx.storage.get("initialized") === true;
|
|
215
197
|
}
|
|
198
|
+
async _initialize() {
|
|
199
|
+
await this.ctx.blockConcurrencyWhile(async () => {
|
|
200
|
+
this._status = "starting";
|
|
201
|
+
await this.onStart();
|
|
202
|
+
this._status = "started";
|
|
203
|
+
});
|
|
204
|
+
}
|
|
216
205
|
// Allow the worker to fetch a websocket connection to the agent
|
|
217
206
|
async fetch(request) {
|
|
218
|
-
if (
|
|
219
|
-
await
|
|
207
|
+
if (this._status !== "started") {
|
|
208
|
+
await this._initialize();
|
|
220
209
|
}
|
|
221
210
|
if (request.headers.get("Upgrade") !== "websocket") {
|
|
222
211
|
return new Response("Expected WebSocket Upgrade request", {
|
|
@@ -225,6 +214,7 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
225
214
|
}
|
|
226
215
|
const url = new URL(request.url);
|
|
227
216
|
const path = url.pathname;
|
|
217
|
+
const server = await this.server;
|
|
228
218
|
switch (path) {
|
|
229
219
|
case "/sse": {
|
|
230
220
|
const websockets = this.ctx.getWebSockets();
|
|
@@ -232,24 +222,24 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
232
222
|
return new Response("Websocket already connected", { status: 400 });
|
|
233
223
|
}
|
|
234
224
|
await this.ctx.storage.put("transportType", "sse");
|
|
235
|
-
|
|
236
|
-
if (!
|
|
237
|
-
|
|
238
|
-
await
|
|
225
|
+
this._transportType = "sse";
|
|
226
|
+
if (!this._transport) {
|
|
227
|
+
this._transport = new McpSSETransport(() => this.getWebSocket());
|
|
228
|
+
await server.connect(this._transport);
|
|
239
229
|
}
|
|
240
|
-
return
|
|
230
|
+
return this._agent.fetch(request);
|
|
241
231
|
}
|
|
242
232
|
case "/streamable-http": {
|
|
243
|
-
if (!
|
|
244
|
-
|
|
233
|
+
if (!this._transport) {
|
|
234
|
+
this._transport = new McpStreamableHttpTransport(
|
|
245
235
|
(id) => this.getWebSocketForResponseID(id),
|
|
246
|
-
(id) =>
|
|
247
|
-
)
|
|
248
|
-
await
|
|
236
|
+
(id) => this._requestIdToConnectionId.delete(id)
|
|
237
|
+
);
|
|
238
|
+
await server.connect(this._transport);
|
|
249
239
|
}
|
|
250
240
|
await this.ctx.storage.put("transportType", "streamable-http");
|
|
251
|
-
|
|
252
|
-
return
|
|
241
|
+
this._transportType = "streamable-http";
|
|
242
|
+
return this._agent.fetch(request);
|
|
253
243
|
}
|
|
254
244
|
default:
|
|
255
245
|
return new Response(
|
|
@@ -268,19 +258,19 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
268
258
|
return websockets[0];
|
|
269
259
|
}
|
|
270
260
|
getWebSocketForResponseID(id) {
|
|
271
|
-
const connectionId =
|
|
261
|
+
const connectionId = this._requestIdToConnectionId.get(id);
|
|
272
262
|
if (connectionId === void 0) {
|
|
273
263
|
return null;
|
|
274
264
|
}
|
|
275
|
-
return
|
|
265
|
+
return this._agent.getConnection(connectionId) ?? null;
|
|
276
266
|
}
|
|
277
267
|
// All messages received here. This is currently never called
|
|
278
268
|
async onMessage(connection, event) {
|
|
279
|
-
if (
|
|
269
|
+
if (this._transportType !== "streamable-http") {
|
|
280
270
|
const err = new Error(
|
|
281
271
|
"Internal Server Error: Expected streamable-http protocol"
|
|
282
272
|
);
|
|
283
|
-
|
|
273
|
+
this._transport?.onerror?.(err);
|
|
284
274
|
return;
|
|
285
275
|
}
|
|
286
276
|
let message;
|
|
@@ -288,21 +278,21 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
288
278
|
const data = typeof event === "string" ? event : new TextDecoder().decode(event);
|
|
289
279
|
message = JSONRPCMessageSchema.parse(JSON.parse(data));
|
|
290
280
|
} catch (error) {
|
|
291
|
-
|
|
281
|
+
this._transport?.onerror?.(error);
|
|
292
282
|
return;
|
|
293
283
|
}
|
|
294
284
|
if (isJSONRPCRequest(message)) {
|
|
295
|
-
|
|
285
|
+
this._requestIdToConnectionId.set(message.id.toString(), connection.id);
|
|
296
286
|
}
|
|
297
|
-
|
|
287
|
+
this._transport?.onmessage?.(message);
|
|
298
288
|
}
|
|
299
289
|
// All messages received over SSE after the initial connection has been established
|
|
300
290
|
// will be passed here
|
|
301
|
-
async onSSEMcpMessage(
|
|
302
|
-
if (
|
|
303
|
-
await
|
|
291
|
+
async onSSEMcpMessage(_sessionId, request) {
|
|
292
|
+
if (this._status !== "started") {
|
|
293
|
+
await this._initialize();
|
|
304
294
|
}
|
|
305
|
-
if (
|
|
295
|
+
if (this._transportType !== "sse") {
|
|
306
296
|
return new Error("Internal Server Error: Expected SSE protocol");
|
|
307
297
|
}
|
|
308
298
|
try {
|
|
@@ -311,35 +301,36 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
311
301
|
try {
|
|
312
302
|
parsedMessage = JSONRPCMessageSchema.parse(message);
|
|
313
303
|
} catch (error) {
|
|
314
|
-
|
|
304
|
+
this._transport?.onerror?.(error);
|
|
315
305
|
throw error;
|
|
316
306
|
}
|
|
317
|
-
|
|
307
|
+
this._transport?.onmessage?.(parsedMessage);
|
|
318
308
|
return null;
|
|
319
309
|
} catch (error) {
|
|
320
|
-
|
|
310
|
+
console.error("Error forwarding message to SSE:", error);
|
|
311
|
+
this._transport?.onerror?.(error);
|
|
321
312
|
return error;
|
|
322
313
|
}
|
|
323
314
|
}
|
|
324
315
|
// Delegate all websocket events to the underlying agent
|
|
325
316
|
async webSocketMessage(ws, event) {
|
|
326
|
-
if (
|
|
327
|
-
await
|
|
317
|
+
if (this._status !== "started") {
|
|
318
|
+
await this._initialize();
|
|
328
319
|
}
|
|
329
|
-
return await
|
|
320
|
+
return await this._agent.webSocketMessage(ws, event);
|
|
330
321
|
}
|
|
331
322
|
// WebSocket event handlers for hibernation support
|
|
332
323
|
async webSocketError(ws, error) {
|
|
333
|
-
if (
|
|
334
|
-
await
|
|
324
|
+
if (this._status !== "started") {
|
|
325
|
+
await this._initialize();
|
|
335
326
|
}
|
|
336
|
-
return await
|
|
327
|
+
return await this._agent.webSocketError(ws, error);
|
|
337
328
|
}
|
|
338
329
|
async webSocketClose(ws, code, reason, wasClean) {
|
|
339
|
-
if (
|
|
340
|
-
await
|
|
330
|
+
if (this._status !== "started") {
|
|
331
|
+
await this._initialize();
|
|
341
332
|
}
|
|
342
|
-
return await
|
|
333
|
+
return await this._agent.webSocketClose(ws, code, reason, wasClean);
|
|
343
334
|
}
|
|
344
335
|
static mount(path, {
|
|
345
336
|
binding = "MCP_OBJECT",
|
|
@@ -358,11 +349,21 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
358
349
|
const basePattern = new URLPattern({ pathname });
|
|
359
350
|
const messagePattern = new URLPattern({ pathname: `${pathname}/message` });
|
|
360
351
|
return {
|
|
361
|
-
|
|
352
|
+
async fetch(request, env, ctx) {
|
|
362
353
|
const corsResponse = handleCORS(request, corsOptions);
|
|
363
354
|
if (corsResponse) return corsResponse;
|
|
364
355
|
const url = new URL(request.url);
|
|
365
|
-
const
|
|
356
|
+
const bindingValue = env[binding];
|
|
357
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
358
|
+
console.error(
|
|
359
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
360
|
+
);
|
|
361
|
+
return new Response("Invalid binding", { status: 500 });
|
|
362
|
+
}
|
|
363
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
364
|
+
return new Response("Invalid binding", { status: 500 });
|
|
365
|
+
}
|
|
366
|
+
const namespace = bindingValue;
|
|
366
367
|
if (request.method === "GET" && basePattern.test(url)) {
|
|
367
368
|
const sessionId = url.searchParams.get("sessionId") || namespace.newUniqueId().toString();
|
|
368
369
|
const { readable, writable } = new TransformStream();
|
|
@@ -420,10 +421,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
420
421
|
onMessage(event).catch(console.error);
|
|
421
422
|
});
|
|
422
423
|
ws.addEventListener("error", (error) => {
|
|
423
|
-
async function onError(
|
|
424
|
+
async function onError(_error) {
|
|
424
425
|
try {
|
|
425
426
|
await writer.close();
|
|
426
|
-
} catch (
|
|
427
|
+
} catch (_e) {
|
|
427
428
|
}
|
|
428
429
|
}
|
|
429
430
|
onError(error).catch(console.error);
|
|
@@ -440,10 +441,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
440
441
|
});
|
|
441
442
|
return new Response(readable, {
|
|
442
443
|
headers: {
|
|
443
|
-
"Content-Type": "text/event-stream",
|
|
444
444
|
"Cache-Control": "no-cache",
|
|
445
445
|
Connection: "keep-alive",
|
|
446
|
-
"
|
|
446
|
+
"Content-Type": "text/event-stream",
|
|
447
|
+
...corsHeaders(request, corsOptions)
|
|
447
448
|
}
|
|
448
449
|
});
|
|
449
450
|
}
|
|
@@ -478,23 +479,23 @@ data: ${JSON.stringify(result.data)}
|
|
|
478
479
|
const error = await doStub.onSSEMcpMessage(sessionId, request);
|
|
479
480
|
if (error) {
|
|
480
481
|
return new Response(error.message, {
|
|
481
|
-
status: 400,
|
|
482
482
|
headers: {
|
|
483
|
-
"Content-Type": "text/event-stream",
|
|
484
483
|
"Cache-Control": "no-cache",
|
|
485
484
|
Connection: "keep-alive",
|
|
486
|
-
"
|
|
487
|
-
|
|
485
|
+
"Content-Type": "text/event-stream",
|
|
486
|
+
...corsHeaders(request, corsOptions)
|
|
487
|
+
},
|
|
488
|
+
status: 400
|
|
488
489
|
});
|
|
489
490
|
}
|
|
490
491
|
return new Response("Accepted", {
|
|
491
|
-
status: 202,
|
|
492
492
|
headers: {
|
|
493
|
-
"Content-Type": "text/event-stream",
|
|
494
493
|
"Cache-Control": "no-cache",
|
|
495
494
|
Connection: "keep-alive",
|
|
496
|
-
"
|
|
497
|
-
|
|
495
|
+
"Content-Type": "text/event-stream",
|
|
496
|
+
...corsHeaders(request, corsOptions)
|
|
497
|
+
},
|
|
498
|
+
status: 202
|
|
498
499
|
});
|
|
499
500
|
}
|
|
500
501
|
return new Response("Not Found", { status: 404 });
|
|
@@ -511,35 +512,45 @@ data: ${JSON.stringify(result.data)}
|
|
|
511
512
|
}
|
|
512
513
|
const basePattern = new URLPattern({ pathname });
|
|
513
514
|
return {
|
|
514
|
-
|
|
515
|
+
async fetch(request, env, ctx) {
|
|
515
516
|
const corsResponse = handleCORS(request, corsOptions);
|
|
516
517
|
if (corsResponse) {
|
|
517
518
|
return corsResponse;
|
|
518
519
|
}
|
|
519
520
|
const url = new URL(request.url);
|
|
520
|
-
const
|
|
521
|
+
const bindingValue = env[binding];
|
|
522
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
523
|
+
console.error(
|
|
524
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
525
|
+
);
|
|
526
|
+
return new Response("Invalid binding", { status: 500 });
|
|
527
|
+
}
|
|
528
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
529
|
+
return new Response("Invalid binding", { status: 500 });
|
|
530
|
+
}
|
|
531
|
+
const namespace = bindingValue;
|
|
521
532
|
if (request.method === "POST" && basePattern.test(url)) {
|
|
522
533
|
const acceptHeader = request.headers.get("accept");
|
|
523
534
|
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
|
|
524
535
|
const body2 = JSON.stringify({
|
|
525
|
-
jsonrpc: "2.0",
|
|
526
536
|
error: {
|
|
527
537
|
code: -32e3,
|
|
528
538
|
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
529
539
|
},
|
|
530
|
-
id: null
|
|
540
|
+
id: null,
|
|
541
|
+
jsonrpc: "2.0"
|
|
531
542
|
});
|
|
532
543
|
return new Response(body2, { status: 406 });
|
|
533
544
|
}
|
|
534
545
|
const ct = request.headers.get("content-type");
|
|
535
546
|
if (!ct || !ct.includes("application/json")) {
|
|
536
547
|
const body2 = JSON.stringify({
|
|
537
|
-
jsonrpc: "2.0",
|
|
538
548
|
error: {
|
|
539
549
|
code: -32e3,
|
|
540
550
|
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
541
551
|
},
|
|
542
|
-
id: null
|
|
552
|
+
id: null,
|
|
553
|
+
jsonrpc: "2.0"
|
|
543
554
|
});
|
|
544
555
|
return new Response(body2, { status: 415 });
|
|
545
556
|
}
|
|
@@ -549,12 +560,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
549
560
|
);
|
|
550
561
|
if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {
|
|
551
562
|
const body2 = JSON.stringify({
|
|
552
|
-
jsonrpc: "2.0",
|
|
553
563
|
error: {
|
|
554
564
|
code: -32e3,
|
|
555
565
|
message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`
|
|
556
566
|
},
|
|
557
|
-
id: null
|
|
567
|
+
id: null,
|
|
568
|
+
jsonrpc: "2.0"
|
|
558
569
|
});
|
|
559
570
|
return new Response(body2, { status: 413 });
|
|
560
571
|
}
|
|
@@ -562,14 +573,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
562
573
|
let rawMessage;
|
|
563
574
|
try {
|
|
564
575
|
rawMessage = await request.json();
|
|
565
|
-
} catch (
|
|
576
|
+
} catch (_error) {
|
|
566
577
|
const body2 = JSON.stringify({
|
|
567
|
-
jsonrpc: "2.0",
|
|
568
578
|
error: {
|
|
569
579
|
code: -32700,
|
|
570
580
|
message: "Parse error: Invalid JSON"
|
|
571
581
|
},
|
|
572
|
-
id: null
|
|
582
|
+
id: null,
|
|
583
|
+
jsonrpc: "2.0"
|
|
573
584
|
});
|
|
574
585
|
return new Response(body2, { status: 400 });
|
|
575
586
|
}
|
|
@@ -583,12 +594,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
583
594
|
for (const msg of arrayMessage) {
|
|
584
595
|
if (!JSONRPCMessageSchema.safeParse(msg).success) {
|
|
585
596
|
const body2 = JSON.stringify({
|
|
586
|
-
jsonrpc: "2.0",
|
|
587
597
|
error: {
|
|
588
598
|
code: -32700,
|
|
589
599
|
message: "Parse error: Invalid JSON-RPC message"
|
|
590
600
|
},
|
|
591
|
-
id: null
|
|
601
|
+
id: null,
|
|
602
|
+
jsonrpc: "2.0"
|
|
592
603
|
});
|
|
593
604
|
return new Response(body2, { status: 400 });
|
|
594
605
|
}
|
|
@@ -599,34 +610,34 @@ data: ${JSON.stringify(result.data)}
|
|
|
599
610
|
);
|
|
600
611
|
if (isInitializationRequest && sessionId) {
|
|
601
612
|
const body2 = JSON.stringify({
|
|
602
|
-
jsonrpc: "2.0",
|
|
603
613
|
error: {
|
|
604
614
|
code: -32600,
|
|
605
615
|
message: "Invalid Request: Initialization requests must not include a sessionId"
|
|
606
616
|
},
|
|
607
|
-
id: null
|
|
617
|
+
id: null,
|
|
618
|
+
jsonrpc: "2.0"
|
|
608
619
|
});
|
|
609
620
|
return new Response(body2, { status: 400 });
|
|
610
621
|
}
|
|
611
622
|
if (isInitializationRequest && messages.length > 1) {
|
|
612
623
|
const body2 = JSON.stringify({
|
|
613
|
-
jsonrpc: "2.0",
|
|
614
624
|
error: {
|
|
615
625
|
code: -32600,
|
|
616
626
|
message: "Invalid Request: Only one initialization request is allowed"
|
|
617
627
|
},
|
|
618
|
-
id: null
|
|
628
|
+
id: null,
|
|
629
|
+
jsonrpc: "2.0"
|
|
619
630
|
});
|
|
620
631
|
return new Response(body2, { status: 400 });
|
|
621
632
|
}
|
|
622
633
|
if (!isInitializationRequest && !sessionId) {
|
|
623
634
|
const body2 = JSON.stringify({
|
|
624
|
-
jsonrpc: "2.0",
|
|
625
635
|
error: {
|
|
626
636
|
code: -32e3,
|
|
627
637
|
message: "Bad Request: Mcp-Session-Id header is required"
|
|
628
638
|
},
|
|
629
|
-
id: null
|
|
639
|
+
id: null,
|
|
640
|
+
jsonrpc: "2.0"
|
|
630
641
|
});
|
|
631
642
|
return new Response(body2, { status: 400 });
|
|
632
643
|
}
|
|
@@ -635,15 +646,16 @@ data: ${JSON.stringify(result.data)}
|
|
|
635
646
|
const doStub = namespace.get(id);
|
|
636
647
|
const isInitialized = await doStub.isInitialized();
|
|
637
648
|
if (isInitializationRequest) {
|
|
649
|
+
await doStub._init(ctx.props);
|
|
638
650
|
await doStub.setInitialized();
|
|
639
651
|
} else if (!isInitialized) {
|
|
640
652
|
const body2 = JSON.stringify({
|
|
641
|
-
jsonrpc: "2.0",
|
|
642
653
|
error: {
|
|
643
654
|
code: -32001,
|
|
644
655
|
message: "Session not found"
|
|
645
656
|
},
|
|
646
|
-
id: null
|
|
657
|
+
id: null,
|
|
658
|
+
jsonrpc: "2.0"
|
|
647
659
|
});
|
|
648
660
|
return new Response(body2, { status: 404 });
|
|
649
661
|
}
|
|
@@ -666,12 +678,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
666
678
|
console.error("Failed to establish WebSocket connection");
|
|
667
679
|
await writer.close();
|
|
668
680
|
const body2 = JSON.stringify({
|
|
669
|
-
jsonrpc: "2.0",
|
|
670
681
|
error: {
|
|
671
682
|
code: -32001,
|
|
672
683
|
message: "Failed to establish WebSocket connection"
|
|
673
684
|
},
|
|
674
|
-
id: null
|
|
685
|
+
id: null,
|
|
686
|
+
jsonrpc: "2.0"
|
|
675
687
|
});
|
|
676
688
|
return new Response(body2, { status: 500 });
|
|
677
689
|
}
|
|
@@ -704,10 +716,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
704
716
|
onMessage(event).catch(console.error);
|
|
705
717
|
});
|
|
706
718
|
ws.addEventListener("error", (error) => {
|
|
707
|
-
async function onError(
|
|
719
|
+
async function onError(_error) {
|
|
708
720
|
try {
|
|
709
721
|
await writer.close();
|
|
710
|
-
} catch (
|
|
722
|
+
} catch (_e) {
|
|
711
723
|
}
|
|
712
724
|
}
|
|
713
725
|
onError(error).catch(console.error);
|
|
@@ -730,7 +742,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
730
742
|
ws.send(JSON.stringify(message));
|
|
731
743
|
}
|
|
732
744
|
ws.close();
|
|
733
|
-
return new Response(null, {
|
|
745
|
+
return new Response(null, {
|
|
746
|
+
headers: corsHeaders(request, corsOptions),
|
|
747
|
+
status: 202
|
|
748
|
+
});
|
|
734
749
|
}
|
|
735
750
|
for (const message of messages) {
|
|
736
751
|
if (isJSONRPCRequest(message)) {
|
|
@@ -740,42 +755,28 @@ data: ${JSON.stringify(result.data)}
|
|
|
740
755
|
}
|
|
741
756
|
return new Response(readable, {
|
|
742
757
|
headers: {
|
|
743
|
-
"Content-Type": "text/event-stream",
|
|
744
758
|
"Cache-Control": "no-cache",
|
|
745
759
|
Connection: "keep-alive",
|
|
760
|
+
"Content-Type": "text/event-stream",
|
|
746
761
|
"mcp-session-id": sessionId,
|
|
747
|
-
|
|
762
|
+
...corsHeaders(request, corsOptions)
|
|
748
763
|
},
|
|
749
764
|
status: 200
|
|
750
765
|
});
|
|
751
766
|
}
|
|
752
767
|
const body = JSON.stringify({
|
|
753
|
-
jsonrpc: "2.0",
|
|
754
768
|
error: {
|
|
755
769
|
code: -32e3,
|
|
756
770
|
message: "Method not allowed"
|
|
757
771
|
},
|
|
758
|
-
id: null
|
|
772
|
+
id: null,
|
|
773
|
+
jsonrpc: "2.0"
|
|
759
774
|
});
|
|
760
775
|
return new Response(body, { status: 405 });
|
|
761
776
|
}
|
|
762
777
|
};
|
|
763
778
|
}
|
|
764
779
|
};
|
|
765
|
-
_status = new WeakMap();
|
|
766
|
-
_transport = new WeakMap();
|
|
767
|
-
_transportType = new WeakMap();
|
|
768
|
-
_requestIdToConnectionId = new WeakMap();
|
|
769
|
-
_agent = new WeakMap();
|
|
770
|
-
_McpAgent_instances = new WeakSet();
|
|
771
|
-
initialize_fn = async function() {
|
|
772
|
-
await this.ctx.blockConcurrencyWhile(async () => {
|
|
773
|
-
__privateSet(this, _status, "starting");
|
|
774
|
-
await this.onStart();
|
|
775
|
-
__privateSet(this, _status, "started");
|
|
776
|
-
});
|
|
777
|
-
};
|
|
778
|
-
var McpAgent = _McpAgent;
|
|
779
780
|
export {
|
|
780
781
|
McpAgent
|
|
781
782
|
};
|