agents 0.0.0-90db5ba → 0.0.0-928211f
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 +49 -4
- package/dist/ai-chat-agent.js +167 -67
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +20 -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-2DJ6XAU6.js +1270 -0
- package/dist/chunk-2DJ6XAU6.js.map +1 -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-XJR75HO7.js +548 -0
- package/dist/chunk-XJR75HO7.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-CLW1aEBr.d.ts +615 -0
- package/dist/index.d.ts +39 -300
- package/dist/index.js +14 -6
- package/dist/mcp/client.d.ts +326 -30
- 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 +74 -12
- package/dist/mcp/index.js +369 -216
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +14 -0
- package/dist/observability/index.js +10 -0
- package/dist/react.d.ts +87 -5
- package/dist/react.js +20 -8
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +10 -10
- 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 -57
- package/src/index.ts +1122 -139
- 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,62 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Agent
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-2DJ6XAU6.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
SSEEdgeClientTransport,
|
|
6
|
+
StreamableHTTPEdgeClientTransport
|
|
7
|
+
} from "../chunk-XJR75HO7.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
|
-
|
|
19
|
+
isJSONRPCResponse
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
import {
|
|
22
|
+
ElicitRequestSchema
|
|
20
23
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
24
|
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-
|
|
25
|
+
function corsHeaders(_request, corsOptions = {}) {
|
|
26
|
+
const origin = "*";
|
|
27
|
+
return {
|
|
28
|
+
"Access-Control-Allow-Headers": corsOptions.headers || "Content-Type, mcp-session-id, mcp-protocol-version",
|
|
29
|
+
"Access-Control-Allow-Methods": corsOptions.methods || "GET, POST, OPTIONS",
|
|
30
|
+
"Access-Control-Allow-Origin": corsOptions.origin || origin,
|
|
31
|
+
"Access-Control-Expose-Headers": corsOptions.exposeHeaders || "mcp-session-id",
|
|
32
|
+
"Access-Control-Max-Age": (corsOptions.maxAge || 86400).toString()
|
|
29
33
|
};
|
|
34
|
+
}
|
|
35
|
+
function isDurableObjectNamespace(namespace) {
|
|
36
|
+
return typeof namespace === "object" && namespace !== null && "newUniqueId" in namespace && typeof namespace.newUniqueId === "function" && "idFromName" in namespace && typeof namespace.idFromName === "function";
|
|
37
|
+
}
|
|
38
|
+
function handleCORS(request, corsOptions) {
|
|
30
39
|
if (request.method === "OPTIONS") {
|
|
31
|
-
return new Response(null, { headers: corsHeaders });
|
|
40
|
+
return new Response(null, { headers: corsHeaders(request, corsOptions) });
|
|
32
41
|
}
|
|
33
42
|
return null;
|
|
34
43
|
}
|
|
35
|
-
var _getWebSocket, _started;
|
|
36
44
|
var McpSSETransport = class {
|
|
37
45
|
constructor(getWebSocket) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
__privateSet(this, _getWebSocket, getWebSocket);
|
|
46
|
+
this._started = false;
|
|
47
|
+
this._getWebSocket = getWebSocket;
|
|
41
48
|
}
|
|
42
49
|
async start() {
|
|
43
|
-
if (
|
|
50
|
+
if (this._started) {
|
|
44
51
|
throw new Error("Transport already started");
|
|
45
52
|
}
|
|
46
|
-
|
|
53
|
+
this._started = true;
|
|
47
54
|
}
|
|
48
55
|
async send(message) {
|
|
49
|
-
if (!
|
|
56
|
+
if (!this._started) {
|
|
50
57
|
throw new Error("Transport not started");
|
|
51
58
|
}
|
|
52
|
-
const websocket =
|
|
59
|
+
const websocket = this._getWebSocket();
|
|
53
60
|
if (!websocket) {
|
|
54
61
|
throw new Error("WebSocket not connected");
|
|
55
62
|
}
|
|
@@ -64,52 +71,40 @@ var McpSSETransport = class {
|
|
|
64
71
|
this.onclose?.();
|
|
65
72
|
}
|
|
66
73
|
};
|
|
67
|
-
_getWebSocket = new WeakMap();
|
|
68
|
-
_started = new WeakMap();
|
|
69
|
-
var _getWebSocketForGetRequest, _getWebSocketForMessageID, _notifyResponseIdSent, _started2;
|
|
70
74
|
var McpStreamableHttpTransport = class {
|
|
71
75
|
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);
|
|
76
|
+
this._started = false;
|
|
77
|
+
this._getWebSocketForMessageID = getWebSocketForMessageID;
|
|
78
|
+
this._notifyResponseIdSent = notifyResponseIdSent;
|
|
79
|
+
this._getWebSocketForGetRequest = () => null;
|
|
85
80
|
}
|
|
86
81
|
async start() {
|
|
87
|
-
if (
|
|
82
|
+
if (this._started) {
|
|
88
83
|
throw new Error("Transport already started");
|
|
89
84
|
}
|
|
90
|
-
|
|
85
|
+
this._started = true;
|
|
91
86
|
}
|
|
92
87
|
async send(message) {
|
|
93
|
-
if (!
|
|
88
|
+
if (!this._started) {
|
|
94
89
|
throw new Error("Transport not started");
|
|
95
90
|
}
|
|
96
91
|
let websocket = null;
|
|
97
92
|
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
|
|
98
|
-
websocket =
|
|
93
|
+
websocket = this._getWebSocketForMessageID(message.id.toString());
|
|
99
94
|
if (!websocket) {
|
|
100
95
|
throw new Error(
|
|
101
96
|
`Could not find WebSocket for message id: ${message.id}`
|
|
102
97
|
);
|
|
103
98
|
}
|
|
104
99
|
} else if (isJSONRPCRequest(message)) {
|
|
105
|
-
websocket =
|
|
100
|
+
websocket = this._getWebSocketForGetRequest();
|
|
106
101
|
} else if (isJSONRPCNotification(message)) {
|
|
107
102
|
websocket = null;
|
|
108
103
|
}
|
|
109
104
|
try {
|
|
110
105
|
websocket?.send(JSON.stringify(message));
|
|
111
106
|
if (isJSONRPCResponse(message)) {
|
|
112
|
-
|
|
107
|
+
this._notifyResponseIdSent(message.id.toString());
|
|
113
108
|
}
|
|
114
109
|
} catch (error) {
|
|
115
110
|
this.onerror?.(error);
|
|
@@ -120,28 +115,16 @@ var McpStreamableHttpTransport = class {
|
|
|
120
115
|
this.onclose?.();
|
|
121
116
|
}
|
|
122
117
|
};
|
|
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 {
|
|
118
|
+
var McpAgent = class _McpAgent extends DurableObject {
|
|
129
119
|
constructor(ctx, env) {
|
|
130
120
|
var _a;
|
|
131
121
|
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);
|
|
122
|
+
this._status = "zero";
|
|
123
|
+
this._transportType = "unset";
|
|
124
|
+
this._requestIdToConnectionId = /* @__PURE__ */ new Map();
|
|
142
125
|
this.initRun = false;
|
|
143
126
|
const self = this;
|
|
144
|
-
|
|
127
|
+
this._agent = new (_a = class extends Agent {
|
|
145
128
|
onStateUpdate(state, source) {
|
|
146
129
|
return self.onStateUpdate(state, source);
|
|
147
130
|
}
|
|
@@ -150,23 +133,66 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
150
133
|
}
|
|
151
134
|
}, _a.options = {
|
|
152
135
|
hibernate: true
|
|
153
|
-
}, _a)(ctx, env)
|
|
136
|
+
}, _a)(ctx, env);
|
|
137
|
+
}
|
|
138
|
+
get mcp() {
|
|
139
|
+
return this._agent.mcp;
|
|
154
140
|
}
|
|
155
141
|
get state() {
|
|
156
|
-
return
|
|
142
|
+
return this._agent.state;
|
|
157
143
|
}
|
|
158
144
|
sql(strings, ...values) {
|
|
159
|
-
return
|
|
145
|
+
return this._agent.sql(strings, ...values);
|
|
160
146
|
}
|
|
161
147
|
setState(state) {
|
|
162
|
-
return
|
|
148
|
+
return this._agent.setState(state);
|
|
163
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Elicit user input with a message and schema
|
|
152
|
+
*/
|
|
153
|
+
async elicitInput(params) {
|
|
154
|
+
const requestId = `elicit_${Math.random().toString(36).substring(2, 11)}`;
|
|
155
|
+
await this.ctx.storage.put(`elicitation:${requestId}`, {
|
|
156
|
+
message: params.message,
|
|
157
|
+
requestedSchema: params.requestedSchema,
|
|
158
|
+
timestamp: Date.now()
|
|
159
|
+
});
|
|
160
|
+
const elicitRequest = {
|
|
161
|
+
jsonrpc: "2.0",
|
|
162
|
+
id: requestId,
|
|
163
|
+
method: "elicitation/create",
|
|
164
|
+
params: {
|
|
165
|
+
message: params.message,
|
|
166
|
+
requestedSchema: params.requestedSchema
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
if (this._transport) {
|
|
170
|
+
await this._transport.send(elicitRequest);
|
|
171
|
+
} else {
|
|
172
|
+
const connections = this._agent?.getConnections();
|
|
173
|
+
if (!connections || Array.from(connections).length === 0) {
|
|
174
|
+
await this.ctx.storage.delete(`elicitation:${requestId}`);
|
|
175
|
+
throw new Error("No active connections available for elicitation");
|
|
176
|
+
}
|
|
177
|
+
const connectionList = Array.from(connections);
|
|
178
|
+
for (const connection of connectionList) {
|
|
179
|
+
try {
|
|
180
|
+
connection.send(JSON.stringify(elicitRequest));
|
|
181
|
+
} catch (error) {
|
|
182
|
+
console.error("Failed to send elicitation request:", error);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return this._waitForElicitationResponse(requestId);
|
|
187
|
+
}
|
|
188
|
+
// we leave the variables as unused for autocomplete purposes
|
|
189
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: overriden later
|
|
164
190
|
onStateUpdate(state, source) {
|
|
165
191
|
}
|
|
166
192
|
async onStart() {
|
|
167
193
|
var _a;
|
|
168
194
|
const self = this;
|
|
169
|
-
|
|
195
|
+
this._agent = new (_a = class extends Agent {
|
|
170
196
|
constructor() {
|
|
171
197
|
super(...arguments);
|
|
172
198
|
this.initialState = self.initialState;
|
|
@@ -179,39 +205,52 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
179
205
|
}
|
|
180
206
|
}, _a.options = {
|
|
181
207
|
hibernate: true
|
|
182
|
-
}, _a)(this.ctx, this.env)
|
|
208
|
+
}, _a)(this.ctx, this.env);
|
|
183
209
|
this.props = await this.ctx.storage.get("props");
|
|
184
|
-
|
|
210
|
+
this._transportType = await this.ctx.storage.get(
|
|
185
211
|
"transportType"
|
|
186
|
-
)
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
212
|
+
);
|
|
213
|
+
await this._init(this.props);
|
|
214
|
+
const server = await this.server;
|
|
215
|
+
if (this._transportType === "sse") {
|
|
216
|
+
this._transport = new McpSSETransport(() => this.getWebSocket());
|
|
217
|
+
await server.connect(this._transport);
|
|
218
|
+
} else if (this._transportType === "streamable-http") {
|
|
219
|
+
this._transport = new McpStreamableHttpTransport(
|
|
193
220
|
(id) => this.getWebSocketForResponseID(id),
|
|
194
|
-
(id) =>
|
|
195
|
-
)
|
|
196
|
-
await
|
|
221
|
+
(id) => this._requestIdToConnectionId.delete(id)
|
|
222
|
+
);
|
|
223
|
+
await server.connect(this._transport);
|
|
197
224
|
}
|
|
198
225
|
}
|
|
199
226
|
async _init(props) {
|
|
200
227
|
await this.ctx.storage.put("props", props ?? {});
|
|
201
|
-
|
|
228
|
+
if (!this.ctx.storage.get("transportType")) {
|
|
229
|
+
await this.ctx.storage.put("transportType", "unset");
|
|
230
|
+
}
|
|
202
231
|
this.props = props;
|
|
203
232
|
if (!this.initRun) {
|
|
204
233
|
this.initRun = true;
|
|
205
234
|
await this.init();
|
|
206
235
|
}
|
|
207
236
|
}
|
|
208
|
-
|
|
209
|
-
|
|
237
|
+
async setInitialized() {
|
|
238
|
+
await this.ctx.storage.put("initialized", true);
|
|
239
|
+
}
|
|
240
|
+
async isInitialized() {
|
|
241
|
+
return await this.ctx.storage.get("initialized") === true;
|
|
242
|
+
}
|
|
243
|
+
async _initialize() {
|
|
244
|
+
await this.ctx.blockConcurrencyWhile(async () => {
|
|
245
|
+
this._status = "starting";
|
|
246
|
+
await this.onStart();
|
|
247
|
+
this._status = "started";
|
|
248
|
+
});
|
|
210
249
|
}
|
|
211
250
|
// Allow the worker to fetch a websocket connection to the agent
|
|
212
251
|
async fetch(request) {
|
|
213
|
-
if (
|
|
214
|
-
await
|
|
252
|
+
if (this._status !== "started") {
|
|
253
|
+
await this._initialize();
|
|
215
254
|
}
|
|
216
255
|
if (request.headers.get("Upgrade") !== "websocket") {
|
|
217
256
|
return new Response("Expected WebSocket Upgrade request", {
|
|
@@ -220,6 +259,7 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
220
259
|
}
|
|
221
260
|
const url = new URL(request.url);
|
|
222
261
|
const path = url.pathname;
|
|
262
|
+
const server = await this.server;
|
|
223
263
|
switch (path) {
|
|
224
264
|
case "/sse": {
|
|
225
265
|
const websockets = this.ctx.getWebSockets();
|
|
@@ -227,24 +267,24 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
227
267
|
return new Response("Websocket already connected", { status: 400 });
|
|
228
268
|
}
|
|
229
269
|
await this.ctx.storage.put("transportType", "sse");
|
|
230
|
-
|
|
231
|
-
if (!
|
|
232
|
-
|
|
233
|
-
await
|
|
270
|
+
this._transportType = "sse";
|
|
271
|
+
if (!this._transport) {
|
|
272
|
+
this._transport = new McpSSETransport(() => this.getWebSocket());
|
|
273
|
+
await server.connect(this._transport);
|
|
234
274
|
}
|
|
235
|
-
return
|
|
275
|
+
return this._agent.fetch(request);
|
|
236
276
|
}
|
|
237
277
|
case "/streamable-http": {
|
|
238
|
-
if (!
|
|
239
|
-
|
|
278
|
+
if (!this._transport) {
|
|
279
|
+
this._transport = new McpStreamableHttpTransport(
|
|
240
280
|
(id) => this.getWebSocketForResponseID(id),
|
|
241
|
-
(id) =>
|
|
242
|
-
)
|
|
243
|
-
await
|
|
281
|
+
(id) => this._requestIdToConnectionId.delete(id)
|
|
282
|
+
);
|
|
283
|
+
await server.connect(this._transport);
|
|
244
284
|
}
|
|
245
285
|
await this.ctx.storage.put("transportType", "streamable-http");
|
|
246
|
-
|
|
247
|
-
return
|
|
286
|
+
this._transportType = "streamable-http";
|
|
287
|
+
return this._agent.fetch(request);
|
|
248
288
|
}
|
|
249
289
|
default:
|
|
250
290
|
return new Response(
|
|
@@ -263,19 +303,19 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
263
303
|
return websockets[0];
|
|
264
304
|
}
|
|
265
305
|
getWebSocketForResponseID(id) {
|
|
266
|
-
const connectionId =
|
|
306
|
+
const connectionId = this._requestIdToConnectionId.get(id);
|
|
267
307
|
if (connectionId === void 0) {
|
|
268
308
|
return null;
|
|
269
309
|
}
|
|
270
|
-
return
|
|
310
|
+
return this._agent.getConnection(connectionId) ?? null;
|
|
271
311
|
}
|
|
272
312
|
// All messages received here. This is currently never called
|
|
273
313
|
async onMessage(connection, event) {
|
|
274
|
-
if (
|
|
314
|
+
if (this._transportType !== "streamable-http") {
|
|
275
315
|
const err = new Error(
|
|
276
316
|
"Internal Server Error: Expected streamable-http protocol"
|
|
277
317
|
);
|
|
278
|
-
|
|
318
|
+
this._transport?.onerror?.(err);
|
|
279
319
|
return;
|
|
280
320
|
}
|
|
281
321
|
let message;
|
|
@@ -283,21 +323,85 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
283
323
|
const data = typeof event === "string" ? event : new TextDecoder().decode(event);
|
|
284
324
|
message = JSONRPCMessageSchema.parse(JSON.parse(data));
|
|
285
325
|
} catch (error) {
|
|
286
|
-
|
|
326
|
+
this._transport?.onerror?.(error);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (await this._handleElicitationResponse(message)) {
|
|
287
330
|
return;
|
|
288
331
|
}
|
|
289
332
|
if (isJSONRPCRequest(message)) {
|
|
290
|
-
|
|
333
|
+
this._requestIdToConnectionId.set(message.id.toString(), connection.id);
|
|
291
334
|
}
|
|
292
|
-
|
|
335
|
+
this._transport?.onmessage?.(message);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Wait for elicitation response through storage polling
|
|
339
|
+
*/
|
|
340
|
+
async _waitForElicitationResponse(requestId) {
|
|
341
|
+
const startTime = Date.now();
|
|
342
|
+
const timeout = 6e4;
|
|
343
|
+
try {
|
|
344
|
+
while (Date.now() - startTime < timeout) {
|
|
345
|
+
const response = await this.ctx.storage.get(
|
|
346
|
+
`elicitation:response:${requestId}`
|
|
347
|
+
);
|
|
348
|
+
if (response) {
|
|
349
|
+
await this.ctx.storage.delete(`elicitation:${requestId}`);
|
|
350
|
+
await this.ctx.storage.delete(`elicitation:response:${requestId}`);
|
|
351
|
+
return response;
|
|
352
|
+
}
|
|
353
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
354
|
+
}
|
|
355
|
+
throw new Error("Elicitation request timed out");
|
|
356
|
+
} finally {
|
|
357
|
+
await this.ctx.storage.delete(`elicitation:${requestId}`);
|
|
358
|
+
await this.ctx.storage.delete(`elicitation:response:${requestId}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Handle elicitation responses */
|
|
363
|
+
async _handleElicitationResponse(message) {
|
|
364
|
+
if (isJSONRPCResponse(message) && message.result) {
|
|
365
|
+
const requestId = message.id?.toString();
|
|
366
|
+
if (!requestId || !requestId.startsWith("elicit_")) return false;
|
|
367
|
+
const pendingRequest = await this.ctx.storage.get(
|
|
368
|
+
`elicitation:${requestId}`
|
|
369
|
+
);
|
|
370
|
+
if (!pendingRequest) return false;
|
|
371
|
+
await this.ctx.storage.put(
|
|
372
|
+
`elicitation:response:${requestId}`,
|
|
373
|
+
message.result
|
|
374
|
+
);
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
if (isJSONRPCError(message)) {
|
|
378
|
+
const requestId = message.id?.toString();
|
|
379
|
+
if (!requestId || !requestId.startsWith("elicit_")) return false;
|
|
380
|
+
const pendingRequest = await this.ctx.storage.get(
|
|
381
|
+
`elicitation:${requestId}`
|
|
382
|
+
);
|
|
383
|
+
if (!pendingRequest) return false;
|
|
384
|
+
const errorResult = {
|
|
385
|
+
action: "cancel",
|
|
386
|
+
content: {
|
|
387
|
+
error: message.error.message || "Elicitation request failed"
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
await this.ctx.storage.put(
|
|
391
|
+
`elicitation:response:${requestId}`,
|
|
392
|
+
errorResult
|
|
393
|
+
);
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
return false;
|
|
293
397
|
}
|
|
294
398
|
// All messages received over SSE after the initial connection has been established
|
|
295
399
|
// will be passed here
|
|
296
|
-
async onSSEMcpMessage(
|
|
297
|
-
if (
|
|
298
|
-
await
|
|
400
|
+
async onSSEMcpMessage(_sessionId, request) {
|
|
401
|
+
if (this._status !== "started") {
|
|
402
|
+
await this._initialize();
|
|
299
403
|
}
|
|
300
|
-
if (
|
|
404
|
+
if (this._transportType !== "sse") {
|
|
301
405
|
return new Error("Internal Server Error: Expected SSE protocol");
|
|
302
406
|
}
|
|
303
407
|
try {
|
|
@@ -306,35 +410,39 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
306
410
|
try {
|
|
307
411
|
parsedMessage = JSONRPCMessageSchema.parse(message);
|
|
308
412
|
} catch (error) {
|
|
309
|
-
|
|
413
|
+
this._transport?.onerror?.(error);
|
|
310
414
|
throw error;
|
|
311
415
|
}
|
|
312
|
-
|
|
416
|
+
if (await this._handleElicitationResponse(parsedMessage)) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
this._transport?.onmessage?.(parsedMessage);
|
|
313
420
|
return null;
|
|
314
421
|
} catch (error) {
|
|
315
|
-
|
|
422
|
+
console.error("Error forwarding message to SSE:", error);
|
|
423
|
+
this._transport?.onerror?.(error);
|
|
316
424
|
return error;
|
|
317
425
|
}
|
|
318
426
|
}
|
|
319
427
|
// Delegate all websocket events to the underlying agent
|
|
320
428
|
async webSocketMessage(ws, event) {
|
|
321
|
-
if (
|
|
322
|
-
await
|
|
429
|
+
if (this._status !== "started") {
|
|
430
|
+
await this._initialize();
|
|
323
431
|
}
|
|
324
|
-
return await
|
|
432
|
+
return await this._agent.webSocketMessage(ws, event);
|
|
325
433
|
}
|
|
326
434
|
// WebSocket event handlers for hibernation support
|
|
327
435
|
async webSocketError(ws, error) {
|
|
328
|
-
if (
|
|
329
|
-
await
|
|
436
|
+
if (this._status !== "started") {
|
|
437
|
+
await this._initialize();
|
|
330
438
|
}
|
|
331
|
-
return await
|
|
439
|
+
return await this._agent.webSocketError(ws, error);
|
|
332
440
|
}
|
|
333
441
|
async webSocketClose(ws, code, reason, wasClean) {
|
|
334
|
-
if (
|
|
335
|
-
await
|
|
442
|
+
if (this._status !== "started") {
|
|
443
|
+
await this._initialize();
|
|
336
444
|
}
|
|
337
|
-
return await
|
|
445
|
+
return await this._agent.webSocketClose(ws, code, reason, wasClean);
|
|
338
446
|
}
|
|
339
447
|
static mount(path, {
|
|
340
448
|
binding = "MCP_OBJECT",
|
|
@@ -353,18 +461,32 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
353
461
|
const basePattern = new URLPattern({ pathname });
|
|
354
462
|
const messagePattern = new URLPattern({ pathname: `${pathname}/message` });
|
|
355
463
|
return {
|
|
356
|
-
|
|
464
|
+
async fetch(request, env, ctx) {
|
|
357
465
|
const corsResponse = handleCORS(request, corsOptions);
|
|
358
466
|
if (corsResponse) return corsResponse;
|
|
359
467
|
const url = new URL(request.url);
|
|
360
|
-
const
|
|
468
|
+
const bindingValue = env[binding];
|
|
469
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
470
|
+
console.error(
|
|
471
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
472
|
+
);
|
|
473
|
+
return new Response("Invalid binding", { status: 500 });
|
|
474
|
+
}
|
|
475
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
476
|
+
return new Response("Invalid binding", { status: 500 });
|
|
477
|
+
}
|
|
478
|
+
const namespace = bindingValue;
|
|
361
479
|
if (request.method === "GET" && basePattern.test(url)) {
|
|
362
480
|
const sessionId = url.searchParams.get("sessionId") || namespace.newUniqueId().toString();
|
|
363
481
|
const { readable, writable } = new TransformStream();
|
|
364
482
|
const writer = writable.getWriter();
|
|
365
483
|
const encoder = new TextEncoder();
|
|
484
|
+
const endpointUrl = new URL(request.url);
|
|
485
|
+
endpointUrl.pathname = encodeURI(`${pathname}/message`);
|
|
486
|
+
endpointUrl.searchParams.set("sessionId", sessionId);
|
|
487
|
+
const relativeUrlWithSession = endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;
|
|
366
488
|
const endpointMessage = `event: endpoint
|
|
367
|
-
data: ${
|
|
489
|
+
data: ${relativeUrlWithSession}
|
|
368
490
|
|
|
369
491
|
`;
|
|
370
492
|
writer.write(encoder.encode(endpointMessage));
|
|
@@ -373,9 +495,14 @@ data: ${encodeURI(`${pathname}/message`)}?sessionId=${sessionId}
|
|
|
373
495
|
await doStub._init(ctx.props);
|
|
374
496
|
const upgradeUrl = new URL(request.url);
|
|
375
497
|
upgradeUrl.pathname = "/sse";
|
|
498
|
+
const existingHeaders = {};
|
|
499
|
+
request.headers.forEach((value, key) => {
|
|
500
|
+
existingHeaders[key] = value;
|
|
501
|
+
});
|
|
376
502
|
const response = await doStub.fetch(
|
|
377
503
|
new Request(upgradeUrl, {
|
|
378
504
|
headers: {
|
|
505
|
+
...existingHeaders,
|
|
379
506
|
Upgrade: "websocket",
|
|
380
507
|
// Required by PartyServer
|
|
381
508
|
"x-partykit-room": sessionId
|
|
@@ -392,40 +519,49 @@ data: ${encodeURI(`${pathname}/message`)}?sessionId=${sessionId}
|
|
|
392
519
|
}
|
|
393
520
|
ws.accept();
|
|
394
521
|
ws.addEventListener("message", (event) => {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
522
|
+
async function onMessage(event2) {
|
|
523
|
+
try {
|
|
524
|
+
const message = JSON.parse(event2.data);
|
|
525
|
+
const result = JSONRPCMessageSchema.safeParse(message);
|
|
526
|
+
if (!result.success) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const messageText = `event: message
|
|
402
530
|
data: ${JSON.stringify(result.data)}
|
|
403
531
|
|
|
404
532
|
`;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
533
|
+
await writer.write(encoder.encode(messageText));
|
|
534
|
+
} catch (error) {
|
|
535
|
+
console.error("Error forwarding message to SSE:", error);
|
|
536
|
+
}
|
|
408
537
|
}
|
|
538
|
+
onMessage(event).catch(console.error);
|
|
409
539
|
});
|
|
410
540
|
ws.addEventListener("error", (error) => {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
541
|
+
async function onError(_error) {
|
|
542
|
+
try {
|
|
543
|
+
await writer.close();
|
|
544
|
+
} catch (_e) {
|
|
545
|
+
}
|
|
414
546
|
}
|
|
547
|
+
onError(error).catch(console.error);
|
|
415
548
|
});
|
|
416
549
|
ws.addEventListener("close", () => {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
550
|
+
async function onClose() {
|
|
551
|
+
try {
|
|
552
|
+
await writer.close();
|
|
553
|
+
} catch (error) {
|
|
554
|
+
console.error("Error closing SSE connection:", error);
|
|
555
|
+
}
|
|
421
556
|
}
|
|
557
|
+
onClose().catch(console.error);
|
|
422
558
|
});
|
|
423
559
|
return new Response(readable, {
|
|
424
560
|
headers: {
|
|
425
|
-
"Content-Type": "text/event-stream",
|
|
426
561
|
"Cache-Control": "no-cache",
|
|
427
562
|
Connection: "keep-alive",
|
|
428
|
-
"
|
|
563
|
+
"Content-Type": "text/event-stream",
|
|
564
|
+
...corsHeaders(request, corsOptions)
|
|
429
565
|
}
|
|
430
566
|
});
|
|
431
567
|
}
|
|
@@ -460,23 +596,23 @@ data: ${JSON.stringify(result.data)}
|
|
|
460
596
|
const error = await doStub.onSSEMcpMessage(sessionId, request);
|
|
461
597
|
if (error) {
|
|
462
598
|
return new Response(error.message, {
|
|
463
|
-
status: 400,
|
|
464
599
|
headers: {
|
|
465
|
-
"Content-Type": "text/event-stream",
|
|
466
600
|
"Cache-Control": "no-cache",
|
|
467
601
|
Connection: "keep-alive",
|
|
468
|
-
"
|
|
469
|
-
|
|
602
|
+
"Content-Type": "text/event-stream",
|
|
603
|
+
...corsHeaders(request, corsOptions)
|
|
604
|
+
},
|
|
605
|
+
status: 400
|
|
470
606
|
});
|
|
471
607
|
}
|
|
472
608
|
return new Response("Accepted", {
|
|
473
|
-
status: 202,
|
|
474
609
|
headers: {
|
|
475
|
-
"Content-Type": "text/event-stream",
|
|
476
610
|
"Cache-Control": "no-cache",
|
|
477
611
|
Connection: "keep-alive",
|
|
478
|
-
"
|
|
479
|
-
|
|
612
|
+
"Content-Type": "text/event-stream",
|
|
613
|
+
...corsHeaders(request, corsOptions)
|
|
614
|
+
},
|
|
615
|
+
status: 202
|
|
480
616
|
});
|
|
481
617
|
}
|
|
482
618
|
return new Response("Not Found", { status: 404 });
|
|
@@ -493,35 +629,45 @@ data: ${JSON.stringify(result.data)}
|
|
|
493
629
|
}
|
|
494
630
|
const basePattern = new URLPattern({ pathname });
|
|
495
631
|
return {
|
|
496
|
-
|
|
632
|
+
async fetch(request, env, ctx) {
|
|
497
633
|
const corsResponse = handleCORS(request, corsOptions);
|
|
498
634
|
if (corsResponse) {
|
|
499
635
|
return corsResponse;
|
|
500
636
|
}
|
|
501
637
|
const url = new URL(request.url);
|
|
502
|
-
const
|
|
638
|
+
const bindingValue = env[binding];
|
|
639
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
640
|
+
console.error(
|
|
641
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
642
|
+
);
|
|
643
|
+
return new Response("Invalid binding", { status: 500 });
|
|
644
|
+
}
|
|
645
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
646
|
+
return new Response("Invalid binding", { status: 500 });
|
|
647
|
+
}
|
|
648
|
+
const namespace = bindingValue;
|
|
503
649
|
if (request.method === "POST" && basePattern.test(url)) {
|
|
504
650
|
const acceptHeader = request.headers.get("accept");
|
|
505
651
|
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
|
|
506
652
|
const body2 = JSON.stringify({
|
|
507
|
-
jsonrpc: "2.0",
|
|
508
653
|
error: {
|
|
509
654
|
code: -32e3,
|
|
510
655
|
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
511
656
|
},
|
|
512
|
-
id: null
|
|
657
|
+
id: null,
|
|
658
|
+
jsonrpc: "2.0"
|
|
513
659
|
});
|
|
514
660
|
return new Response(body2, { status: 406 });
|
|
515
661
|
}
|
|
516
662
|
const ct = request.headers.get("content-type");
|
|
517
663
|
if (!ct || !ct.includes("application/json")) {
|
|
518
664
|
const body2 = JSON.stringify({
|
|
519
|
-
jsonrpc: "2.0",
|
|
520
665
|
error: {
|
|
521
666
|
code: -32e3,
|
|
522
667
|
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
523
668
|
},
|
|
524
|
-
id: null
|
|
669
|
+
id: null,
|
|
670
|
+
jsonrpc: "2.0"
|
|
525
671
|
});
|
|
526
672
|
return new Response(body2, { status: 415 });
|
|
527
673
|
}
|
|
@@ -531,12 +677,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
531
677
|
);
|
|
532
678
|
if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {
|
|
533
679
|
const body2 = JSON.stringify({
|
|
534
|
-
jsonrpc: "2.0",
|
|
535
680
|
error: {
|
|
536
681
|
code: -32e3,
|
|
537
682
|
message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`
|
|
538
683
|
},
|
|
539
|
-
id: null
|
|
684
|
+
id: null,
|
|
685
|
+
jsonrpc: "2.0"
|
|
540
686
|
});
|
|
541
687
|
return new Response(body2, { status: 413 });
|
|
542
688
|
}
|
|
@@ -544,14 +690,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
544
690
|
let rawMessage;
|
|
545
691
|
try {
|
|
546
692
|
rawMessage = await request.json();
|
|
547
|
-
} catch (
|
|
693
|
+
} catch (_error) {
|
|
548
694
|
const body2 = JSON.stringify({
|
|
549
|
-
jsonrpc: "2.0",
|
|
550
695
|
error: {
|
|
551
696
|
code: -32700,
|
|
552
697
|
message: "Parse error: Invalid JSON"
|
|
553
698
|
},
|
|
554
|
-
id: null
|
|
699
|
+
id: null,
|
|
700
|
+
jsonrpc: "2.0"
|
|
555
701
|
});
|
|
556
702
|
return new Response(body2, { status: 400 });
|
|
557
703
|
}
|
|
@@ -565,12 +711,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
565
711
|
for (const msg of arrayMessage) {
|
|
566
712
|
if (!JSONRPCMessageSchema.safeParse(msg).success) {
|
|
567
713
|
const body2 = JSON.stringify({
|
|
568
|
-
jsonrpc: "2.0",
|
|
569
714
|
error: {
|
|
570
715
|
code: -32700,
|
|
571
716
|
message: "Parse error: Invalid JSON-RPC message"
|
|
572
717
|
},
|
|
573
|
-
id: null
|
|
718
|
+
id: null,
|
|
719
|
+
jsonrpc: "2.0"
|
|
574
720
|
});
|
|
575
721
|
return new Response(body2, { status: 400 });
|
|
576
722
|
}
|
|
@@ -581,34 +727,34 @@ data: ${JSON.stringify(result.data)}
|
|
|
581
727
|
);
|
|
582
728
|
if (isInitializationRequest && sessionId) {
|
|
583
729
|
const body2 = JSON.stringify({
|
|
584
|
-
jsonrpc: "2.0",
|
|
585
730
|
error: {
|
|
586
731
|
code: -32600,
|
|
587
732
|
message: "Invalid Request: Initialization requests must not include a sessionId"
|
|
588
733
|
},
|
|
589
|
-
id: null
|
|
734
|
+
id: null,
|
|
735
|
+
jsonrpc: "2.0"
|
|
590
736
|
});
|
|
591
737
|
return new Response(body2, { status: 400 });
|
|
592
738
|
}
|
|
593
739
|
if (isInitializationRequest && messages.length > 1) {
|
|
594
740
|
const body2 = JSON.stringify({
|
|
595
|
-
jsonrpc: "2.0",
|
|
596
741
|
error: {
|
|
597
742
|
code: -32600,
|
|
598
743
|
message: "Invalid Request: Only one initialization request is allowed"
|
|
599
744
|
},
|
|
600
|
-
id: null
|
|
745
|
+
id: null,
|
|
746
|
+
jsonrpc: "2.0"
|
|
601
747
|
});
|
|
602
748
|
return new Response(body2, { status: 400 });
|
|
603
749
|
}
|
|
604
750
|
if (!isInitializationRequest && !sessionId) {
|
|
605
751
|
const body2 = JSON.stringify({
|
|
606
|
-
jsonrpc: "2.0",
|
|
607
752
|
error: {
|
|
608
753
|
code: -32e3,
|
|
609
754
|
message: "Bad Request: Mcp-Session-Id header is required"
|
|
610
755
|
},
|
|
611
|
-
id: null
|
|
756
|
+
id: null,
|
|
757
|
+
jsonrpc: "2.0"
|
|
612
758
|
});
|
|
613
759
|
return new Response(body2, { status: 400 });
|
|
614
760
|
}
|
|
@@ -618,14 +764,15 @@ data: ${JSON.stringify(result.data)}
|
|
|
618
764
|
const isInitialized = await doStub.isInitialized();
|
|
619
765
|
if (isInitializationRequest) {
|
|
620
766
|
await doStub._init(ctx.props);
|
|
767
|
+
await doStub.setInitialized();
|
|
621
768
|
} else if (!isInitialized) {
|
|
622
769
|
const body2 = JSON.stringify({
|
|
623
|
-
jsonrpc: "2.0",
|
|
624
770
|
error: {
|
|
625
771
|
code: -32001,
|
|
626
772
|
message: "Session not found"
|
|
627
773
|
},
|
|
628
|
-
id: null
|
|
774
|
+
id: null,
|
|
775
|
+
jsonrpc: "2.0"
|
|
629
776
|
});
|
|
630
777
|
return new Response(body2, { status: 404 });
|
|
631
778
|
}
|
|
@@ -634,9 +781,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
634
781
|
const encoder = new TextEncoder();
|
|
635
782
|
const upgradeUrl = new URL(request.url);
|
|
636
783
|
upgradeUrl.pathname = "/streamable-http";
|
|
784
|
+
const existingHeaders = {};
|
|
785
|
+
request.headers.forEach((value, key) => {
|
|
786
|
+
existingHeaders[key] = value;
|
|
787
|
+
});
|
|
637
788
|
const response = await doStub.fetch(
|
|
638
789
|
new Request(upgradeUrl, {
|
|
639
790
|
headers: {
|
|
791
|
+
...existingHeaders,
|
|
640
792
|
Upgrade: "websocket",
|
|
641
793
|
// Required by PartyServer
|
|
642
794
|
"x-partykit-room": sessionId
|
|
@@ -648,52 +800,61 @@ data: ${JSON.stringify(result.data)}
|
|
|
648
800
|
console.error("Failed to establish WebSocket connection");
|
|
649
801
|
await writer.close();
|
|
650
802
|
const body2 = JSON.stringify({
|
|
651
|
-
jsonrpc: "2.0",
|
|
652
803
|
error: {
|
|
653
804
|
code: -32001,
|
|
654
805
|
message: "Failed to establish WebSocket connection"
|
|
655
806
|
},
|
|
656
|
-
id: null
|
|
807
|
+
id: null,
|
|
808
|
+
jsonrpc: "2.0"
|
|
657
809
|
});
|
|
658
810
|
return new Response(body2, { status: 500 });
|
|
659
811
|
}
|
|
660
812
|
const requestIds = /* @__PURE__ */ new Set();
|
|
661
813
|
ws.accept();
|
|
662
814
|
ws.addEventListener("message", (event) => {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
815
|
+
async function onMessage(event2) {
|
|
816
|
+
try {
|
|
817
|
+
const data = typeof event2.data === "string" ? event2.data : new TextDecoder().decode(event2.data);
|
|
818
|
+
const message = JSON.parse(data);
|
|
819
|
+
const result = JSONRPCMessageSchema.safeParse(message);
|
|
820
|
+
if (!result.success) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (isJSONRPCResponse(result.data) || isJSONRPCError(result.data)) {
|
|
824
|
+
requestIds.delete(result.data.id);
|
|
825
|
+
}
|
|
826
|
+
const messageText = `event: message
|
|
674
827
|
data: ${JSON.stringify(result.data)}
|
|
675
828
|
|
|
676
829
|
`;
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
830
|
+
await writer.write(encoder.encode(messageText));
|
|
831
|
+
if (requestIds.size === 0) {
|
|
832
|
+
ws.close();
|
|
833
|
+
}
|
|
834
|
+
} catch (error) {
|
|
835
|
+
console.error("Error forwarding message to SSE:", error);
|
|
680
836
|
}
|
|
681
|
-
} catch (error) {
|
|
682
|
-
console.error("Error forwarding message to SSE:", error);
|
|
683
837
|
}
|
|
838
|
+
onMessage(event).catch(console.error);
|
|
684
839
|
});
|
|
685
840
|
ws.addEventListener("error", (error) => {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
841
|
+
async function onError(_error) {
|
|
842
|
+
try {
|
|
843
|
+
await writer.close();
|
|
844
|
+
} catch (_e) {
|
|
845
|
+
}
|
|
689
846
|
}
|
|
847
|
+
onError(error).catch(console.error);
|
|
690
848
|
});
|
|
691
849
|
ws.addEventListener("close", () => {
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
850
|
+
async function onClose() {
|
|
851
|
+
try {
|
|
852
|
+
await writer.close();
|
|
853
|
+
} catch (error) {
|
|
854
|
+
console.error("Error closing SSE connection:", error);
|
|
855
|
+
}
|
|
696
856
|
}
|
|
857
|
+
onClose().catch(console.error);
|
|
697
858
|
});
|
|
698
859
|
const hasOnlyNotificationsOrResponses = messages.every(
|
|
699
860
|
(msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(msg)
|
|
@@ -703,7 +864,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
703
864
|
ws.send(JSON.stringify(message));
|
|
704
865
|
}
|
|
705
866
|
ws.close();
|
|
706
|
-
return new Response(null, {
|
|
867
|
+
return new Response(null, {
|
|
868
|
+
headers: corsHeaders(request, corsOptions),
|
|
869
|
+
status: 202
|
|
870
|
+
});
|
|
707
871
|
}
|
|
708
872
|
for (const message of messages) {
|
|
709
873
|
if (isJSONRPCRequest(message)) {
|
|
@@ -713,43 +877,32 @@ data: ${JSON.stringify(result.data)}
|
|
|
713
877
|
}
|
|
714
878
|
return new Response(readable, {
|
|
715
879
|
headers: {
|
|
716
|
-
"Content-Type": "text/event-stream",
|
|
717
880
|
"Cache-Control": "no-cache",
|
|
718
881
|
Connection: "keep-alive",
|
|
882
|
+
"Content-Type": "text/event-stream",
|
|
719
883
|
"mcp-session-id": sessionId,
|
|
720
|
-
|
|
884
|
+
...corsHeaders(request, corsOptions)
|
|
721
885
|
},
|
|
722
886
|
status: 200
|
|
723
887
|
});
|
|
724
888
|
}
|
|
725
889
|
const body = JSON.stringify({
|
|
726
|
-
jsonrpc: "2.0",
|
|
727
890
|
error: {
|
|
728
891
|
code: -32e3,
|
|
729
892
|
message: "Method not allowed"
|
|
730
893
|
},
|
|
731
|
-
id: null
|
|
894
|
+
id: null,
|
|
895
|
+
jsonrpc: "2.0"
|
|
732
896
|
});
|
|
733
897
|
return new Response(body, { status: 405 });
|
|
734
898
|
}
|
|
735
899
|
};
|
|
736
900
|
}
|
|
737
901
|
};
|
|
738
|
-
_status = new WeakMap();
|
|
739
|
-
_transport = new WeakMap();
|
|
740
|
-
_transportType = new WeakMap();
|
|
741
|
-
_requestIdToConnectionId = new WeakMap();
|
|
742
|
-
_agent = new WeakMap();
|
|
743
|
-
_McpAgent_instances = new WeakSet();
|
|
744
|
-
initialize_fn = async function() {
|
|
745
|
-
await this.ctx.blockConcurrencyWhile(async () => {
|
|
746
|
-
__privateSet(this, _status, "starting");
|
|
747
|
-
await this.onStart();
|
|
748
|
-
__privateSet(this, _status, "started");
|
|
749
|
-
});
|
|
750
|
-
};
|
|
751
|
-
var McpAgent = _McpAgent;
|
|
752
902
|
export {
|
|
753
|
-
|
|
903
|
+
ElicitRequestSchema,
|
|
904
|
+
McpAgent,
|
|
905
|
+
SSEEdgeClientTransport,
|
|
906
|
+
StreamableHTTPEdgeClientTransport
|
|
754
907
|
};
|
|
755
908
|
//# sourceMappingURL=index.js.map
|