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