agents 0.0.0-3f532ba → 0.0.0-40bd73c
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 +127 -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 +48 -37
- 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 +196 -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 -65
- 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));
|
|
@@ -378,9 +386,14 @@ data: ${encodeURI(`${pathname}/message`)}?sessionId=${sessionId}
|
|
|
378
386
|
await doStub._init(ctx.props);
|
|
379
387
|
const upgradeUrl = new URL(request.url);
|
|
380
388
|
upgradeUrl.pathname = "/sse";
|
|
389
|
+
const existingHeaders = {};
|
|
390
|
+
request.headers.forEach((value, key) => {
|
|
391
|
+
existingHeaders[key] = value;
|
|
392
|
+
});
|
|
381
393
|
const response = await doStub.fetch(
|
|
382
394
|
new Request(upgradeUrl, {
|
|
383
395
|
headers: {
|
|
396
|
+
...existingHeaders,
|
|
384
397
|
Upgrade: "websocket",
|
|
385
398
|
// Required by PartyServer
|
|
386
399
|
"x-partykit-room": sessionId
|
|
@@ -416,10 +429,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
416
429
|
onMessage(event).catch(console.error);
|
|
417
430
|
});
|
|
418
431
|
ws.addEventListener("error", (error) => {
|
|
419
|
-
async function onError(
|
|
432
|
+
async function onError(_error) {
|
|
420
433
|
try {
|
|
421
434
|
await writer.close();
|
|
422
|
-
} catch (
|
|
435
|
+
} catch (_e) {
|
|
423
436
|
}
|
|
424
437
|
}
|
|
425
438
|
onError(error).catch(console.error);
|
|
@@ -436,10 +449,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
436
449
|
});
|
|
437
450
|
return new Response(readable, {
|
|
438
451
|
headers: {
|
|
439
|
-
"Content-Type": "text/event-stream",
|
|
440
452
|
"Cache-Control": "no-cache",
|
|
441
453
|
Connection: "keep-alive",
|
|
442
|
-
"
|
|
454
|
+
"Content-Type": "text/event-stream",
|
|
455
|
+
...corsHeaders(request, corsOptions)
|
|
443
456
|
}
|
|
444
457
|
});
|
|
445
458
|
}
|
|
@@ -474,23 +487,23 @@ data: ${JSON.stringify(result.data)}
|
|
|
474
487
|
const error = await doStub.onSSEMcpMessage(sessionId, request);
|
|
475
488
|
if (error) {
|
|
476
489
|
return new Response(error.message, {
|
|
477
|
-
status: 400,
|
|
478
490
|
headers: {
|
|
479
|
-
"Content-Type": "text/event-stream",
|
|
480
491
|
"Cache-Control": "no-cache",
|
|
481
492
|
Connection: "keep-alive",
|
|
482
|
-
"
|
|
483
|
-
|
|
493
|
+
"Content-Type": "text/event-stream",
|
|
494
|
+
...corsHeaders(request, corsOptions)
|
|
495
|
+
},
|
|
496
|
+
status: 400
|
|
484
497
|
});
|
|
485
498
|
}
|
|
486
499
|
return new Response("Accepted", {
|
|
487
|
-
status: 202,
|
|
488
500
|
headers: {
|
|
489
|
-
"Content-Type": "text/event-stream",
|
|
490
501
|
"Cache-Control": "no-cache",
|
|
491
502
|
Connection: "keep-alive",
|
|
492
|
-
"
|
|
493
|
-
|
|
503
|
+
"Content-Type": "text/event-stream",
|
|
504
|
+
...corsHeaders(request, corsOptions)
|
|
505
|
+
},
|
|
506
|
+
status: 202
|
|
494
507
|
});
|
|
495
508
|
}
|
|
496
509
|
return new Response("Not Found", { status: 404 });
|
|
@@ -507,35 +520,45 @@ data: ${JSON.stringify(result.data)}
|
|
|
507
520
|
}
|
|
508
521
|
const basePattern = new URLPattern({ pathname });
|
|
509
522
|
return {
|
|
510
|
-
|
|
523
|
+
async fetch(request, env, ctx) {
|
|
511
524
|
const corsResponse = handleCORS(request, corsOptions);
|
|
512
525
|
if (corsResponse) {
|
|
513
526
|
return corsResponse;
|
|
514
527
|
}
|
|
515
528
|
const url = new URL(request.url);
|
|
516
|
-
const
|
|
529
|
+
const bindingValue = env[binding];
|
|
530
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
531
|
+
console.error(
|
|
532
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
533
|
+
);
|
|
534
|
+
return new Response("Invalid binding", { status: 500 });
|
|
535
|
+
}
|
|
536
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
537
|
+
return new Response("Invalid binding", { status: 500 });
|
|
538
|
+
}
|
|
539
|
+
const namespace = bindingValue;
|
|
517
540
|
if (request.method === "POST" && basePattern.test(url)) {
|
|
518
541
|
const acceptHeader = request.headers.get("accept");
|
|
519
542
|
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
|
|
520
543
|
const body2 = JSON.stringify({
|
|
521
|
-
jsonrpc: "2.0",
|
|
522
544
|
error: {
|
|
523
545
|
code: -32e3,
|
|
524
546
|
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
525
547
|
},
|
|
526
|
-
id: null
|
|
548
|
+
id: null,
|
|
549
|
+
jsonrpc: "2.0"
|
|
527
550
|
});
|
|
528
551
|
return new Response(body2, { status: 406 });
|
|
529
552
|
}
|
|
530
553
|
const ct = request.headers.get("content-type");
|
|
531
554
|
if (!ct || !ct.includes("application/json")) {
|
|
532
555
|
const body2 = JSON.stringify({
|
|
533
|
-
jsonrpc: "2.0",
|
|
534
556
|
error: {
|
|
535
557
|
code: -32e3,
|
|
536
558
|
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
537
559
|
},
|
|
538
|
-
id: null
|
|
560
|
+
id: null,
|
|
561
|
+
jsonrpc: "2.0"
|
|
539
562
|
});
|
|
540
563
|
return new Response(body2, { status: 415 });
|
|
541
564
|
}
|
|
@@ -545,12 +568,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
545
568
|
);
|
|
546
569
|
if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {
|
|
547
570
|
const body2 = JSON.stringify({
|
|
548
|
-
jsonrpc: "2.0",
|
|
549
571
|
error: {
|
|
550
572
|
code: -32e3,
|
|
551
573
|
message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`
|
|
552
574
|
},
|
|
553
|
-
id: null
|
|
575
|
+
id: null,
|
|
576
|
+
jsonrpc: "2.0"
|
|
554
577
|
});
|
|
555
578
|
return new Response(body2, { status: 413 });
|
|
556
579
|
}
|
|
@@ -558,14 +581,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
558
581
|
let rawMessage;
|
|
559
582
|
try {
|
|
560
583
|
rawMessage = await request.json();
|
|
561
|
-
} catch (
|
|
584
|
+
} catch (_error) {
|
|
562
585
|
const body2 = JSON.stringify({
|
|
563
|
-
jsonrpc: "2.0",
|
|
564
586
|
error: {
|
|
565
587
|
code: -32700,
|
|
566
588
|
message: "Parse error: Invalid JSON"
|
|
567
589
|
},
|
|
568
|
-
id: null
|
|
590
|
+
id: null,
|
|
591
|
+
jsonrpc: "2.0"
|
|
569
592
|
});
|
|
570
593
|
return new Response(body2, { status: 400 });
|
|
571
594
|
}
|
|
@@ -579,12 +602,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
579
602
|
for (const msg of arrayMessage) {
|
|
580
603
|
if (!JSONRPCMessageSchema.safeParse(msg).success) {
|
|
581
604
|
const body2 = JSON.stringify({
|
|
582
|
-
jsonrpc: "2.0",
|
|
583
605
|
error: {
|
|
584
606
|
code: -32700,
|
|
585
607
|
message: "Parse error: Invalid JSON-RPC message"
|
|
586
608
|
},
|
|
587
|
-
id: null
|
|
609
|
+
id: null,
|
|
610
|
+
jsonrpc: "2.0"
|
|
588
611
|
});
|
|
589
612
|
return new Response(body2, { status: 400 });
|
|
590
613
|
}
|
|
@@ -595,34 +618,34 @@ data: ${JSON.stringify(result.data)}
|
|
|
595
618
|
);
|
|
596
619
|
if (isInitializationRequest && sessionId) {
|
|
597
620
|
const body2 = JSON.stringify({
|
|
598
|
-
jsonrpc: "2.0",
|
|
599
621
|
error: {
|
|
600
622
|
code: -32600,
|
|
601
623
|
message: "Invalid Request: Initialization requests must not include a sessionId"
|
|
602
624
|
},
|
|
603
|
-
id: null
|
|
625
|
+
id: null,
|
|
626
|
+
jsonrpc: "2.0"
|
|
604
627
|
});
|
|
605
628
|
return new Response(body2, { status: 400 });
|
|
606
629
|
}
|
|
607
630
|
if (isInitializationRequest && messages.length > 1) {
|
|
608
631
|
const body2 = JSON.stringify({
|
|
609
|
-
jsonrpc: "2.0",
|
|
610
632
|
error: {
|
|
611
633
|
code: -32600,
|
|
612
634
|
message: "Invalid Request: Only one initialization request is allowed"
|
|
613
635
|
},
|
|
614
|
-
id: null
|
|
636
|
+
id: null,
|
|
637
|
+
jsonrpc: "2.0"
|
|
615
638
|
});
|
|
616
639
|
return new Response(body2, { status: 400 });
|
|
617
640
|
}
|
|
618
641
|
if (!isInitializationRequest && !sessionId) {
|
|
619
642
|
const body2 = JSON.stringify({
|
|
620
|
-
jsonrpc: "2.0",
|
|
621
643
|
error: {
|
|
622
644
|
code: -32e3,
|
|
623
645
|
message: "Bad Request: Mcp-Session-Id header is required"
|
|
624
646
|
},
|
|
625
|
-
id: null
|
|
647
|
+
id: null,
|
|
648
|
+
jsonrpc: "2.0"
|
|
626
649
|
});
|
|
627
650
|
return new Response(body2, { status: 400 });
|
|
628
651
|
}
|
|
@@ -631,15 +654,16 @@ data: ${JSON.stringify(result.data)}
|
|
|
631
654
|
const doStub = namespace.get(id);
|
|
632
655
|
const isInitialized = await doStub.isInitialized();
|
|
633
656
|
if (isInitializationRequest) {
|
|
657
|
+
await doStub._init(ctx.props);
|
|
634
658
|
await doStub.setInitialized();
|
|
635
659
|
} else if (!isInitialized) {
|
|
636
660
|
const body2 = JSON.stringify({
|
|
637
|
-
jsonrpc: "2.0",
|
|
638
661
|
error: {
|
|
639
662
|
code: -32001,
|
|
640
663
|
message: "Session not found"
|
|
641
664
|
},
|
|
642
|
-
id: null
|
|
665
|
+
id: null,
|
|
666
|
+
jsonrpc: "2.0"
|
|
643
667
|
});
|
|
644
668
|
return new Response(body2, { status: 404 });
|
|
645
669
|
}
|
|
@@ -648,9 +672,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
648
672
|
const encoder = new TextEncoder();
|
|
649
673
|
const upgradeUrl = new URL(request.url);
|
|
650
674
|
upgradeUrl.pathname = "/streamable-http";
|
|
675
|
+
const existingHeaders = {};
|
|
676
|
+
request.headers.forEach((value, key) => {
|
|
677
|
+
existingHeaders[key] = value;
|
|
678
|
+
});
|
|
651
679
|
const response = await doStub.fetch(
|
|
652
680
|
new Request(upgradeUrl, {
|
|
653
681
|
headers: {
|
|
682
|
+
...existingHeaders,
|
|
654
683
|
Upgrade: "websocket",
|
|
655
684
|
// Required by PartyServer
|
|
656
685
|
"x-partykit-room": sessionId
|
|
@@ -662,12 +691,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
662
691
|
console.error("Failed to establish WebSocket connection");
|
|
663
692
|
await writer.close();
|
|
664
693
|
const body2 = JSON.stringify({
|
|
665
|
-
jsonrpc: "2.0",
|
|
666
694
|
error: {
|
|
667
695
|
code: -32001,
|
|
668
696
|
message: "Failed to establish WebSocket connection"
|
|
669
697
|
},
|
|
670
|
-
id: null
|
|
698
|
+
id: null,
|
|
699
|
+
jsonrpc: "2.0"
|
|
671
700
|
});
|
|
672
701
|
return new Response(body2, { status: 500 });
|
|
673
702
|
}
|
|
@@ -700,10 +729,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
700
729
|
onMessage(event).catch(console.error);
|
|
701
730
|
});
|
|
702
731
|
ws.addEventListener("error", (error) => {
|
|
703
|
-
async function onError(
|
|
732
|
+
async function onError(_error) {
|
|
704
733
|
try {
|
|
705
734
|
await writer.close();
|
|
706
|
-
} catch (
|
|
735
|
+
} catch (_e) {
|
|
707
736
|
}
|
|
708
737
|
}
|
|
709
738
|
onError(error).catch(console.error);
|
|
@@ -726,7 +755,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
726
755
|
ws.send(JSON.stringify(message));
|
|
727
756
|
}
|
|
728
757
|
ws.close();
|
|
729
|
-
return new Response(null, {
|
|
758
|
+
return new Response(null, {
|
|
759
|
+
headers: corsHeaders(request, corsOptions),
|
|
760
|
+
status: 202
|
|
761
|
+
});
|
|
730
762
|
}
|
|
731
763
|
for (const message of messages) {
|
|
732
764
|
if (isJSONRPCRequest(message)) {
|
|
@@ -736,43 +768,31 @@ data: ${JSON.stringify(result.data)}
|
|
|
736
768
|
}
|
|
737
769
|
return new Response(readable, {
|
|
738
770
|
headers: {
|
|
739
|
-
"Content-Type": "text/event-stream",
|
|
740
771
|
"Cache-Control": "no-cache",
|
|
741
772
|
Connection: "keep-alive",
|
|
773
|
+
"Content-Type": "text/event-stream",
|
|
742
774
|
"mcp-session-id": sessionId,
|
|
743
|
-
|
|
775
|
+
...corsHeaders(request, corsOptions)
|
|
744
776
|
},
|
|
745
777
|
status: 200
|
|
746
778
|
});
|
|
747
779
|
}
|
|
748
780
|
const body = JSON.stringify({
|
|
749
|
-
jsonrpc: "2.0",
|
|
750
781
|
error: {
|
|
751
782
|
code: -32e3,
|
|
752
783
|
message: "Method not allowed"
|
|
753
784
|
},
|
|
754
|
-
id: null
|
|
785
|
+
id: null,
|
|
786
|
+
jsonrpc: "2.0"
|
|
755
787
|
});
|
|
756
788
|
return new Response(body, { status: 405 });
|
|
757
789
|
}
|
|
758
790
|
};
|
|
759
791
|
}
|
|
760
792
|
};
|
|
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
793
|
export {
|
|
776
|
-
McpAgent
|
|
794
|
+
McpAgent,
|
|
795
|
+
SSEEdgeClientTransport,
|
|
796
|
+
StreamableHTTPEdgeClientTransport
|
|
777
797
|
};
|
|
778
798
|
//# sourceMappingURL=index.js.map
|