agents 0.0.0-fbf5181 → 0.0.0-fce47ef
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 +48 -37
- 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-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/{chunk-XG52S6YY.js → chunk-ZRRXJUAA.js} +357 -160
- package/dist/chunk-ZRRXJUAA.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 +123 -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 -7
- package/dist/mcp/index.js +179 -174
- 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 -65
- package/src/index.ts +429 -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-ZRRXJUAA.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",
|
|
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,18 +349,32 @@ 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();
|
|
369
370
|
const writer = writable.getWriter();
|
|
370
371
|
const encoder = new TextEncoder();
|
|
372
|
+
const endpointUrl = new URL(request.url);
|
|
373
|
+
endpointUrl.pathname = encodeURI(`${pathname}/message`);
|
|
374
|
+
endpointUrl.searchParams.set("sessionId", sessionId);
|
|
375
|
+
const relativeUrlWithSession = endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;
|
|
371
376
|
const endpointMessage = `event: endpoint
|
|
372
|
-
data: ${
|
|
377
|
+
data: ${relativeUrlWithSession}
|
|
373
378
|
|
|
374
379
|
`;
|
|
375
380
|
writer.write(encoder.encode(endpointMessage));
|
|
@@ -416,10 +421,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
416
421
|
onMessage(event).catch(console.error);
|
|
417
422
|
});
|
|
418
423
|
ws.addEventListener("error", (error) => {
|
|
419
|
-
async function onError(
|
|
424
|
+
async function onError(_error) {
|
|
420
425
|
try {
|
|
421
426
|
await writer.close();
|
|
422
|
-
} catch (
|
|
427
|
+
} catch (_e) {
|
|
423
428
|
}
|
|
424
429
|
}
|
|
425
430
|
onError(error).catch(console.error);
|
|
@@ -436,10 +441,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
436
441
|
});
|
|
437
442
|
return new Response(readable, {
|
|
438
443
|
headers: {
|
|
439
|
-
"Content-Type": "text/event-stream",
|
|
440
444
|
"Cache-Control": "no-cache",
|
|
441
445
|
Connection: "keep-alive",
|
|
442
|
-
"
|
|
446
|
+
"Content-Type": "text/event-stream",
|
|
447
|
+
...corsHeaders(request, corsOptions)
|
|
443
448
|
}
|
|
444
449
|
});
|
|
445
450
|
}
|
|
@@ -474,23 +479,23 @@ data: ${JSON.stringify(result.data)}
|
|
|
474
479
|
const error = await doStub.onSSEMcpMessage(sessionId, request);
|
|
475
480
|
if (error) {
|
|
476
481
|
return new Response(error.message, {
|
|
477
|
-
status: 400,
|
|
478
482
|
headers: {
|
|
479
|
-
"Content-Type": "text/event-stream",
|
|
480
483
|
"Cache-Control": "no-cache",
|
|
481
484
|
Connection: "keep-alive",
|
|
482
|
-
"
|
|
483
|
-
|
|
485
|
+
"Content-Type": "text/event-stream",
|
|
486
|
+
...corsHeaders(request, corsOptions)
|
|
487
|
+
},
|
|
488
|
+
status: 400
|
|
484
489
|
});
|
|
485
490
|
}
|
|
486
491
|
return new Response("Accepted", {
|
|
487
|
-
status: 202,
|
|
488
492
|
headers: {
|
|
489
|
-
"Content-Type": "text/event-stream",
|
|
490
493
|
"Cache-Control": "no-cache",
|
|
491
494
|
Connection: "keep-alive",
|
|
492
|
-
"
|
|
493
|
-
|
|
495
|
+
"Content-Type": "text/event-stream",
|
|
496
|
+
...corsHeaders(request, corsOptions)
|
|
497
|
+
},
|
|
498
|
+
status: 202
|
|
494
499
|
});
|
|
495
500
|
}
|
|
496
501
|
return new Response("Not Found", { status: 404 });
|
|
@@ -507,35 +512,45 @@ data: ${JSON.stringify(result.data)}
|
|
|
507
512
|
}
|
|
508
513
|
const basePattern = new URLPattern({ pathname });
|
|
509
514
|
return {
|
|
510
|
-
|
|
515
|
+
async fetch(request, env, ctx) {
|
|
511
516
|
const corsResponse = handleCORS(request, corsOptions);
|
|
512
517
|
if (corsResponse) {
|
|
513
518
|
return corsResponse;
|
|
514
519
|
}
|
|
515
520
|
const url = new URL(request.url);
|
|
516
|
-
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;
|
|
517
532
|
if (request.method === "POST" && basePattern.test(url)) {
|
|
518
533
|
const acceptHeader = request.headers.get("accept");
|
|
519
534
|
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
|
|
520
535
|
const body2 = JSON.stringify({
|
|
521
|
-
jsonrpc: "2.0",
|
|
522
536
|
error: {
|
|
523
537
|
code: -32e3,
|
|
524
538
|
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
525
539
|
},
|
|
526
|
-
id: null
|
|
540
|
+
id: null,
|
|
541
|
+
jsonrpc: "2.0"
|
|
527
542
|
});
|
|
528
543
|
return new Response(body2, { status: 406 });
|
|
529
544
|
}
|
|
530
545
|
const ct = request.headers.get("content-type");
|
|
531
546
|
if (!ct || !ct.includes("application/json")) {
|
|
532
547
|
const body2 = JSON.stringify({
|
|
533
|
-
jsonrpc: "2.0",
|
|
534
548
|
error: {
|
|
535
549
|
code: -32e3,
|
|
536
550
|
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
537
551
|
},
|
|
538
|
-
id: null
|
|
552
|
+
id: null,
|
|
553
|
+
jsonrpc: "2.0"
|
|
539
554
|
});
|
|
540
555
|
return new Response(body2, { status: 415 });
|
|
541
556
|
}
|
|
@@ -545,12 +560,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
545
560
|
);
|
|
546
561
|
if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {
|
|
547
562
|
const body2 = JSON.stringify({
|
|
548
|
-
jsonrpc: "2.0",
|
|
549
563
|
error: {
|
|
550
564
|
code: -32e3,
|
|
551
565
|
message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`
|
|
552
566
|
},
|
|
553
|
-
id: null
|
|
567
|
+
id: null,
|
|
568
|
+
jsonrpc: "2.0"
|
|
554
569
|
});
|
|
555
570
|
return new Response(body2, { status: 413 });
|
|
556
571
|
}
|
|
@@ -558,14 +573,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
558
573
|
let rawMessage;
|
|
559
574
|
try {
|
|
560
575
|
rawMessage = await request.json();
|
|
561
|
-
} catch (
|
|
576
|
+
} catch (_error) {
|
|
562
577
|
const body2 = JSON.stringify({
|
|
563
|
-
jsonrpc: "2.0",
|
|
564
578
|
error: {
|
|
565
579
|
code: -32700,
|
|
566
580
|
message: "Parse error: Invalid JSON"
|
|
567
581
|
},
|
|
568
|
-
id: null
|
|
582
|
+
id: null,
|
|
583
|
+
jsonrpc: "2.0"
|
|
569
584
|
});
|
|
570
585
|
return new Response(body2, { status: 400 });
|
|
571
586
|
}
|
|
@@ -579,12 +594,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
579
594
|
for (const msg of arrayMessage) {
|
|
580
595
|
if (!JSONRPCMessageSchema.safeParse(msg).success) {
|
|
581
596
|
const body2 = JSON.stringify({
|
|
582
|
-
jsonrpc: "2.0",
|
|
583
597
|
error: {
|
|
584
598
|
code: -32700,
|
|
585
599
|
message: "Parse error: Invalid JSON-RPC message"
|
|
586
600
|
},
|
|
587
|
-
id: null
|
|
601
|
+
id: null,
|
|
602
|
+
jsonrpc: "2.0"
|
|
588
603
|
});
|
|
589
604
|
return new Response(body2, { status: 400 });
|
|
590
605
|
}
|
|
@@ -595,34 +610,34 @@ data: ${JSON.stringify(result.data)}
|
|
|
595
610
|
);
|
|
596
611
|
if (isInitializationRequest && sessionId) {
|
|
597
612
|
const body2 = JSON.stringify({
|
|
598
|
-
jsonrpc: "2.0",
|
|
599
613
|
error: {
|
|
600
614
|
code: -32600,
|
|
601
615
|
message: "Invalid Request: Initialization requests must not include a sessionId"
|
|
602
616
|
},
|
|
603
|
-
id: null
|
|
617
|
+
id: null,
|
|
618
|
+
jsonrpc: "2.0"
|
|
604
619
|
});
|
|
605
620
|
return new Response(body2, { status: 400 });
|
|
606
621
|
}
|
|
607
622
|
if (isInitializationRequest && messages.length > 1) {
|
|
608
623
|
const body2 = JSON.stringify({
|
|
609
|
-
jsonrpc: "2.0",
|
|
610
624
|
error: {
|
|
611
625
|
code: -32600,
|
|
612
626
|
message: "Invalid Request: Only one initialization request is allowed"
|
|
613
627
|
},
|
|
614
|
-
id: null
|
|
628
|
+
id: null,
|
|
629
|
+
jsonrpc: "2.0"
|
|
615
630
|
});
|
|
616
631
|
return new Response(body2, { status: 400 });
|
|
617
632
|
}
|
|
618
633
|
if (!isInitializationRequest && !sessionId) {
|
|
619
634
|
const body2 = JSON.stringify({
|
|
620
|
-
jsonrpc: "2.0",
|
|
621
635
|
error: {
|
|
622
636
|
code: -32e3,
|
|
623
637
|
message: "Bad Request: Mcp-Session-Id header is required"
|
|
624
638
|
},
|
|
625
|
-
id: null
|
|
639
|
+
id: null,
|
|
640
|
+
jsonrpc: "2.0"
|
|
626
641
|
});
|
|
627
642
|
return new Response(body2, { status: 400 });
|
|
628
643
|
}
|
|
@@ -631,15 +646,16 @@ data: ${JSON.stringify(result.data)}
|
|
|
631
646
|
const doStub = namespace.get(id);
|
|
632
647
|
const isInitialized = await doStub.isInitialized();
|
|
633
648
|
if (isInitializationRequest) {
|
|
649
|
+
await doStub._init(ctx.props);
|
|
634
650
|
await doStub.setInitialized();
|
|
635
651
|
} else if (!isInitialized) {
|
|
636
652
|
const body2 = JSON.stringify({
|
|
637
|
-
jsonrpc: "2.0",
|
|
638
653
|
error: {
|
|
639
654
|
code: -32001,
|
|
640
655
|
message: "Session not found"
|
|
641
656
|
},
|
|
642
|
-
id: null
|
|
657
|
+
id: null,
|
|
658
|
+
jsonrpc: "2.0"
|
|
643
659
|
});
|
|
644
660
|
return new Response(body2, { status: 404 });
|
|
645
661
|
}
|
|
@@ -662,12 +678,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
662
678
|
console.error("Failed to establish WebSocket connection");
|
|
663
679
|
await writer.close();
|
|
664
680
|
const body2 = JSON.stringify({
|
|
665
|
-
jsonrpc: "2.0",
|
|
666
681
|
error: {
|
|
667
682
|
code: -32001,
|
|
668
683
|
message: "Failed to establish WebSocket connection"
|
|
669
684
|
},
|
|
670
|
-
id: null
|
|
685
|
+
id: null,
|
|
686
|
+
jsonrpc: "2.0"
|
|
671
687
|
});
|
|
672
688
|
return new Response(body2, { status: 500 });
|
|
673
689
|
}
|
|
@@ -700,10 +716,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
700
716
|
onMessage(event).catch(console.error);
|
|
701
717
|
});
|
|
702
718
|
ws.addEventListener("error", (error) => {
|
|
703
|
-
async function onError(
|
|
719
|
+
async function onError(_error) {
|
|
704
720
|
try {
|
|
705
721
|
await writer.close();
|
|
706
|
-
} catch (
|
|
722
|
+
} catch (_e) {
|
|
707
723
|
}
|
|
708
724
|
}
|
|
709
725
|
onError(error).catch(console.error);
|
|
@@ -726,7 +742,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
726
742
|
ws.send(JSON.stringify(message));
|
|
727
743
|
}
|
|
728
744
|
ws.close();
|
|
729
|
-
return new Response(null, {
|
|
745
|
+
return new Response(null, {
|
|
746
|
+
headers: corsHeaders(request, corsOptions),
|
|
747
|
+
status: 202
|
|
748
|
+
});
|
|
730
749
|
}
|
|
731
750
|
for (const message of messages) {
|
|
732
751
|
if (isJSONRPCRequest(message)) {
|
|
@@ -736,42 +755,28 @@ data: ${JSON.stringify(result.data)}
|
|
|
736
755
|
}
|
|
737
756
|
return new Response(readable, {
|
|
738
757
|
headers: {
|
|
739
|
-
"Content-Type": "text/event-stream",
|
|
740
758
|
"Cache-Control": "no-cache",
|
|
741
759
|
Connection: "keep-alive",
|
|
760
|
+
"Content-Type": "text/event-stream",
|
|
742
761
|
"mcp-session-id": sessionId,
|
|
743
|
-
|
|
762
|
+
...corsHeaders(request, corsOptions)
|
|
744
763
|
},
|
|
745
764
|
status: 200
|
|
746
765
|
});
|
|
747
766
|
}
|
|
748
767
|
const body = JSON.stringify({
|
|
749
|
-
jsonrpc: "2.0",
|
|
750
768
|
error: {
|
|
751
769
|
code: -32e3,
|
|
752
770
|
message: "Method not allowed"
|
|
753
771
|
},
|
|
754
|
-
id: null
|
|
772
|
+
id: null,
|
|
773
|
+
jsonrpc: "2.0"
|
|
755
774
|
});
|
|
756
775
|
return new Response(body, { status: 405 });
|
|
757
776
|
}
|
|
758
777
|
};
|
|
759
778
|
}
|
|
760
779
|
};
|
|
761
|
-
_status = new WeakMap();
|
|
762
|
-
_transport = new WeakMap();
|
|
763
|
-
_transportType = new WeakMap();
|
|
764
|
-
_requestIdToConnectionId = new WeakMap();
|
|
765
|
-
_agent = new WeakMap();
|
|
766
|
-
_McpAgent_instances = new WeakSet();
|
|
767
|
-
initialize_fn = async function() {
|
|
768
|
-
await this.ctx.blockConcurrencyWhile(async () => {
|
|
769
|
-
__privateSet(this, _status, "starting");
|
|
770
|
-
await this.onStart();
|
|
771
|
-
__privateSet(this, _status, "started");
|
|
772
|
-
});
|
|
773
|
-
};
|
|
774
|
-
var McpAgent = _McpAgent;
|
|
775
780
|
export {
|
|
776
781
|
McpAgent
|
|
777
782
|
};
|