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