agents 0.0.0-8bc0470 → 0.0.0-8c2713f
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 +128 -22
- package/dist/ai-chat-agent.d.ts +35 -6
- package/dist/ai-chat-agent.js +149 -115
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +19 -5
- package/dist/ai-react.js +27 -29
- package/dist/ai-react.js.map +1 -1
- package/dist/{chunk-7VFQNJFK.js → chunk-HY7ZLHJB.js} +186 -50
- package/dist/chunk-HY7ZLHJB.js.map +1 -0
- package/dist/chunk-JXN5WZFQ.js +1287 -0
- package/dist/chunk-JXN5WZFQ.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/client-DgyzBU_8.d.ts +4601 -0
- package/dist/client.d.ts +16 -2
- package/dist/client.js +6 -126
- package/dist/client.js.map +1 -1
- package/dist/index-BCJclX6q.d.ts +615 -0
- package/dist/index.d.ts +35 -312
- package/dist/index.js +10 -3
- package/dist/mcp/client.d.ts +9 -783
- package/dist/mcp/client.js +1 -2
- package/dist/mcp/do-oauth-client-provider.d.ts +3 -3
- package/dist/mcp/do-oauth-client-provider.js +3 -103
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +48 -11
- package/dist/mcp/index.js +317 -178
- 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 -71
- package/src/index.ts +1097 -136
- package/dist/chunk-7VFQNJFK.js.map +0 -1
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-JR3NW4A7.js +0 -621
- package/dist/chunk-JR3NW4A7.js.map +0 -1
- /package/dist/{chunk-HMLY7DHA.js.map → observability/index.js.map} +0 -0
package/dist/mcp/index.js
CHANGED
|
@@ -1,59 +1,62 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Agent
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-7VFQNJFK.js";
|
|
3
|
+
} from "../chunk-JXN5WZFQ.js";
|
|
5
4
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
SSEEdgeClientTransport,
|
|
6
|
+
StreamableHTTPEdgeClientTransport
|
|
7
|
+
} from "../chunk-HY7ZLHJB.js";
|
|
8
|
+
import "../chunk-PVQZBKN7.js";
|
|
9
|
+
import "../chunk-KUH345EY.js";
|
|
11
10
|
|
|
12
11
|
// src/mcp/index.ts
|
|
13
12
|
import { DurableObject } from "cloudflare:workers";
|
|
14
13
|
import {
|
|
15
14
|
InitializeRequestSchema,
|
|
15
|
+
JSONRPCMessageSchema,
|
|
16
16
|
isJSONRPCError,
|
|
17
17
|
isJSONRPCNotification,
|
|
18
18
|
isJSONRPCRequest,
|
|
19
|
-
isJSONRPCResponse
|
|
20
|
-
|
|
19
|
+
isJSONRPCResponse
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
import {
|
|
22
|
+
ElicitRequestSchema
|
|
21
23
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
22
24
|
var MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024;
|
|
23
|
-
function corsHeaders(
|
|
25
|
+
function corsHeaders(_request, corsOptions = {}) {
|
|
24
26
|
const origin = "*";
|
|
25
27
|
return {
|
|
26
|
-
"Access-Control-Allow-
|
|
28
|
+
"Access-Control-Allow-Headers": corsOptions.headers || "Content-Type, mcp-session-id, mcp-protocol-version",
|
|
27
29
|
"Access-Control-Allow-Methods": corsOptions.methods || "GET, POST, OPTIONS",
|
|
28
|
-
"Access-Control-Allow-
|
|
29
|
-
"Access-Control-
|
|
30
|
-
"Access-Control-
|
|
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()
|
|
31
33
|
};
|
|
32
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
|
+
}
|
|
33
38
|
function handleCORS(request, corsOptions) {
|
|
34
39
|
if (request.method === "OPTIONS") {
|
|
35
40
|
return new Response(null, { headers: corsHeaders(request, corsOptions) });
|
|
36
41
|
}
|
|
37
42
|
return null;
|
|
38
43
|
}
|
|
39
|
-
var _getWebSocket, _started;
|
|
40
44
|
var McpSSETransport = class {
|
|
41
45
|
constructor(getWebSocket) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
__privateSet(this, _getWebSocket, getWebSocket);
|
|
46
|
+
this._started = false;
|
|
47
|
+
this._getWebSocket = getWebSocket;
|
|
45
48
|
}
|
|
46
49
|
async start() {
|
|
47
|
-
if (
|
|
50
|
+
if (this._started) {
|
|
48
51
|
throw new Error("Transport already started");
|
|
49
52
|
}
|
|
50
|
-
|
|
53
|
+
this._started = true;
|
|
51
54
|
}
|
|
52
55
|
async send(message) {
|
|
53
|
-
if (!
|
|
56
|
+
if (!this._started) {
|
|
54
57
|
throw new Error("Transport not started");
|
|
55
58
|
}
|
|
56
|
-
const websocket =
|
|
59
|
+
const websocket = this._getWebSocket();
|
|
57
60
|
if (!websocket) {
|
|
58
61
|
throw new Error("WebSocket not connected");
|
|
59
62
|
}
|
|
@@ -68,52 +71,40 @@ var McpSSETransport = class {
|
|
|
68
71
|
this.onclose?.();
|
|
69
72
|
}
|
|
70
73
|
};
|
|
71
|
-
_getWebSocket = new WeakMap();
|
|
72
|
-
_started = new WeakMap();
|
|
73
|
-
var _getWebSocketForGetRequest, _getWebSocketForMessageID, _notifyResponseIdSent, _started2;
|
|
74
74
|
var McpStreamableHttpTransport = class {
|
|
75
75
|
constructor(getWebSocketForMessageID, notifyResponseIdSent) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
__privateAdd(this, _getWebSocketForMessageID);
|
|
81
|
-
// Notify the server that a response has been sent for a given message id
|
|
82
|
-
// so that it may clean up it's mapping of message ids to connections
|
|
83
|
-
// once they are no longer needed
|
|
84
|
-
__privateAdd(this, _notifyResponseIdSent);
|
|
85
|
-
__privateAdd(this, _started2, false);
|
|
86
|
-
__privateSet(this, _getWebSocketForMessageID, getWebSocketForMessageID);
|
|
87
|
-
__privateSet(this, _notifyResponseIdSent, notifyResponseIdSent);
|
|
88
|
-
__privateSet(this, _getWebSocketForGetRequest, () => null);
|
|
76
|
+
this._started = false;
|
|
77
|
+
this._getWebSocketForMessageID = getWebSocketForMessageID;
|
|
78
|
+
this._notifyResponseIdSent = notifyResponseIdSent;
|
|
79
|
+
this._getWebSocketForGetRequest = () => null;
|
|
89
80
|
}
|
|
90
81
|
async start() {
|
|
91
|
-
if (
|
|
82
|
+
if (this._started) {
|
|
92
83
|
throw new Error("Transport already started");
|
|
93
84
|
}
|
|
94
|
-
|
|
85
|
+
this._started = true;
|
|
95
86
|
}
|
|
96
87
|
async send(message) {
|
|
97
|
-
if (!
|
|
88
|
+
if (!this._started) {
|
|
98
89
|
throw new Error("Transport not started");
|
|
99
90
|
}
|
|
100
91
|
let websocket = null;
|
|
101
92
|
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
|
|
102
|
-
websocket =
|
|
93
|
+
websocket = this._getWebSocketForMessageID(message.id.toString());
|
|
103
94
|
if (!websocket) {
|
|
104
95
|
throw new Error(
|
|
105
96
|
`Could not find WebSocket for message id: ${message.id}`
|
|
106
97
|
);
|
|
107
98
|
}
|
|
108
99
|
} else if (isJSONRPCRequest(message)) {
|
|
109
|
-
websocket =
|
|
100
|
+
websocket = this._getWebSocketForGetRequest();
|
|
110
101
|
} else if (isJSONRPCNotification(message)) {
|
|
111
102
|
websocket = null;
|
|
112
103
|
}
|
|
113
104
|
try {
|
|
114
105
|
websocket?.send(JSON.stringify(message));
|
|
115
106
|
if (isJSONRPCResponse(message)) {
|
|
116
|
-
|
|
107
|
+
this._notifyResponseIdSent(message.id.toString());
|
|
117
108
|
}
|
|
118
109
|
} catch (error) {
|
|
119
110
|
this.onerror?.(error);
|
|
@@ -124,28 +115,16 @@ var McpStreamableHttpTransport = class {
|
|
|
124
115
|
this.onclose?.();
|
|
125
116
|
}
|
|
126
117
|
};
|
|
127
|
-
|
|
128
|
-
_getWebSocketForMessageID = new WeakMap();
|
|
129
|
-
_notifyResponseIdSent = new WeakMap();
|
|
130
|
-
_started2 = new WeakMap();
|
|
131
|
-
var _status, _transport, _transportType, _requestIdToConnectionId, _agent, _McpAgent_instances, initialize_fn;
|
|
132
|
-
var _McpAgent = class _McpAgent extends DurableObject {
|
|
118
|
+
var McpAgent = class _McpAgent extends DurableObject {
|
|
133
119
|
constructor(ctx, env) {
|
|
134
120
|
var _a;
|
|
135
121
|
super(ctx, env);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
__privateAdd(this, _transportType, "unset");
|
|
140
|
-
__privateAdd(this, _requestIdToConnectionId, /* @__PURE__ */ new Map());
|
|
141
|
-
/**
|
|
142
|
-
* Since McpAgent's _aren't_ yet real "Agents", let's only expose a couple of the methods
|
|
143
|
-
* to the outer class: initialState/state/setState/onStateUpdate/sql
|
|
144
|
-
*/
|
|
145
|
-
__privateAdd(this, _agent);
|
|
122
|
+
this._status = "zero";
|
|
123
|
+
this._transportType = "unset";
|
|
124
|
+
this._requestIdToConnectionId = /* @__PURE__ */ new Map();
|
|
146
125
|
this.initRun = false;
|
|
147
126
|
const self = this;
|
|
148
|
-
|
|
127
|
+
this._agent = new (_a = class extends Agent {
|
|
149
128
|
onStateUpdate(state, source) {
|
|
150
129
|
return self.onStateUpdate(state, source);
|
|
151
130
|
}
|
|
@@ -154,26 +133,66 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
154
133
|
}
|
|
155
134
|
}, _a.options = {
|
|
156
135
|
hibernate: true
|
|
157
|
-
}, _a)(ctx, env)
|
|
136
|
+
}, _a)(ctx, env);
|
|
158
137
|
}
|
|
159
138
|
get mcp() {
|
|
160
|
-
return
|
|
139
|
+
return this._agent.mcp;
|
|
161
140
|
}
|
|
162
141
|
get state() {
|
|
163
|
-
return
|
|
142
|
+
return this._agent.state;
|
|
164
143
|
}
|
|
165
144
|
sql(strings, ...values) {
|
|
166
|
-
return
|
|
145
|
+
return this._agent.sql(strings, ...values);
|
|
167
146
|
}
|
|
168
147
|
setState(state) {
|
|
169
|
-
return
|
|
148
|
+
return this._agent.setState(state);
|
|
170
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
|
|
171
190
|
onStateUpdate(state, source) {
|
|
172
191
|
}
|
|
173
192
|
async onStart() {
|
|
174
193
|
var _a;
|
|
175
194
|
const self = this;
|
|
176
|
-
|
|
195
|
+
this._agent = new (_a = class extends Agent {
|
|
177
196
|
constructor() {
|
|
178
197
|
super(...arguments);
|
|
179
198
|
this.initialState = self.initialState;
|
|
@@ -186,33 +205,50 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
186
205
|
}
|
|
187
206
|
}, _a.options = {
|
|
188
207
|
hibernate: true
|
|
189
|
-
}, _a)(this.ctx, this.env)
|
|
208
|
+
}, _a)(this.ctx, this.env);
|
|
190
209
|
this.props = await this.ctx.storage.get("props");
|
|
191
|
-
|
|
210
|
+
this._transportType = await this.ctx.storage.get(
|
|
192
211
|
"transportType"
|
|
193
|
-
)
|
|
212
|
+
);
|
|
194
213
|
await this._init(this.props);
|
|
195
214
|
const server = await this.server;
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
await server.connect(
|
|
199
|
-
} else if (
|
|
200
|
-
|
|
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(
|
|
201
220
|
(id) => this.getWebSocketForResponseID(id),
|
|
202
|
-
(id) =>
|
|
203
|
-
)
|
|
204
|
-
await server.connect(
|
|
221
|
+
(id) => this._requestIdToConnectionId.delete(id)
|
|
222
|
+
);
|
|
223
|
+
await server.connect(this._transport);
|
|
205
224
|
}
|
|
206
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Handle errors that occur during initialization or operation.
|
|
228
|
+
* Override this method to provide custom error handling.
|
|
229
|
+
* @param error - The error that occurred
|
|
230
|
+
* @returns An error response object with status code and message
|
|
231
|
+
*/
|
|
232
|
+
onError(error) {
|
|
233
|
+
console.error("McpAgent error:", error);
|
|
234
|
+
return {
|
|
235
|
+
status: 500,
|
|
236
|
+
message: error.message || "An unexpected error occurred during initialization"
|
|
237
|
+
};
|
|
238
|
+
}
|
|
207
239
|
async _init(props) {
|
|
208
|
-
await this.
|
|
240
|
+
await this.updateProps(props);
|
|
209
241
|
if (!this.ctx.storage.get("transportType")) {
|
|
210
242
|
await this.ctx.storage.put("transportType", "unset");
|
|
211
243
|
}
|
|
212
|
-
this.props = props;
|
|
213
244
|
if (!this.initRun) {
|
|
214
245
|
this.initRun = true;
|
|
215
|
-
|
|
246
|
+
try {
|
|
247
|
+
await this.init();
|
|
248
|
+
} catch (error) {
|
|
249
|
+
const errorResponse = this.onError(error);
|
|
250
|
+
throw new Error(`Initialization failed: ${errorResponse.message}`);
|
|
251
|
+
}
|
|
216
252
|
}
|
|
217
253
|
}
|
|
218
254
|
async setInitialized() {
|
|
@@ -221,10 +257,21 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
221
257
|
async isInitialized() {
|
|
222
258
|
return await this.ctx.storage.get("initialized") === true;
|
|
223
259
|
}
|
|
260
|
+
async updateProps(props) {
|
|
261
|
+
await this.ctx.storage.put("props", props ?? {});
|
|
262
|
+
this.props = props;
|
|
263
|
+
}
|
|
264
|
+
async _initialize() {
|
|
265
|
+
await this.ctx.blockConcurrencyWhile(async () => {
|
|
266
|
+
this._status = "starting";
|
|
267
|
+
await this.onStart();
|
|
268
|
+
this._status = "started";
|
|
269
|
+
});
|
|
270
|
+
}
|
|
224
271
|
// Allow the worker to fetch a websocket connection to the agent
|
|
225
272
|
async fetch(request) {
|
|
226
|
-
if (
|
|
227
|
-
await
|
|
273
|
+
if (this._status !== "started") {
|
|
274
|
+
await this._initialize();
|
|
228
275
|
}
|
|
229
276
|
if (request.headers.get("Upgrade") !== "websocket") {
|
|
230
277
|
return new Response("Expected WebSocket Upgrade request", {
|
|
@@ -241,24 +288,24 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
241
288
|
return new Response("Websocket already connected", { status: 400 });
|
|
242
289
|
}
|
|
243
290
|
await this.ctx.storage.put("transportType", "sse");
|
|
244
|
-
|
|
245
|
-
if (!
|
|
246
|
-
|
|
247
|
-
await server.connect(
|
|
291
|
+
this._transportType = "sse";
|
|
292
|
+
if (!this._transport) {
|
|
293
|
+
this._transport = new McpSSETransport(() => this.getWebSocket());
|
|
294
|
+
await server.connect(this._transport);
|
|
248
295
|
}
|
|
249
|
-
return
|
|
296
|
+
return this._agent.fetch(request);
|
|
250
297
|
}
|
|
251
298
|
case "/streamable-http": {
|
|
252
|
-
if (!
|
|
253
|
-
|
|
299
|
+
if (!this._transport) {
|
|
300
|
+
this._transport = new McpStreamableHttpTransport(
|
|
254
301
|
(id) => this.getWebSocketForResponseID(id),
|
|
255
|
-
(id) =>
|
|
256
|
-
)
|
|
257
|
-
await server.connect(
|
|
302
|
+
(id) => this._requestIdToConnectionId.delete(id)
|
|
303
|
+
);
|
|
304
|
+
await server.connect(this._transport);
|
|
258
305
|
}
|
|
259
306
|
await this.ctx.storage.put("transportType", "streamable-http");
|
|
260
|
-
|
|
261
|
-
return
|
|
307
|
+
this._transportType = "streamable-http";
|
|
308
|
+
return this._agent.fetch(request);
|
|
262
309
|
}
|
|
263
310
|
default:
|
|
264
311
|
return new Response(
|
|
@@ -277,19 +324,19 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
277
324
|
return websockets[0];
|
|
278
325
|
}
|
|
279
326
|
getWebSocketForResponseID(id) {
|
|
280
|
-
const connectionId =
|
|
327
|
+
const connectionId = this._requestIdToConnectionId.get(id);
|
|
281
328
|
if (connectionId === void 0) {
|
|
282
329
|
return null;
|
|
283
330
|
}
|
|
284
|
-
return
|
|
331
|
+
return this._agent.getConnection(connectionId) ?? null;
|
|
285
332
|
}
|
|
286
333
|
// All messages received here. This is currently never called
|
|
287
334
|
async onMessage(connection, event) {
|
|
288
|
-
if (
|
|
335
|
+
if (this._transportType !== "streamable-http") {
|
|
289
336
|
const err = new Error(
|
|
290
337
|
"Internal Server Error: Expected streamable-http protocol"
|
|
291
338
|
);
|
|
292
|
-
|
|
339
|
+
this._transport?.onerror?.(err);
|
|
293
340
|
return;
|
|
294
341
|
}
|
|
295
342
|
let message;
|
|
@@ -297,59 +344,125 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
297
344
|
const data = typeof event === "string" ? event : new TextDecoder().decode(event);
|
|
298
345
|
message = JSONRPCMessageSchema.parse(JSON.parse(data));
|
|
299
346
|
} catch (error) {
|
|
300
|
-
|
|
347
|
+
this._transport?.onerror?.(error);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (await this._handleElicitationResponse(message)) {
|
|
301
351
|
return;
|
|
302
352
|
}
|
|
303
353
|
if (isJSONRPCRequest(message)) {
|
|
304
|
-
|
|
354
|
+
this._requestIdToConnectionId.set(message.id.toString(), connection.id);
|
|
355
|
+
}
|
|
356
|
+
this._transport?.onmessage?.(message);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Wait for elicitation response through storage polling
|
|
360
|
+
*/
|
|
361
|
+
async _waitForElicitationResponse(requestId) {
|
|
362
|
+
const startTime = Date.now();
|
|
363
|
+
const timeout = 6e4;
|
|
364
|
+
try {
|
|
365
|
+
while (Date.now() - startTime < timeout) {
|
|
366
|
+
const response = await this.ctx.storage.get(
|
|
367
|
+
`elicitation:response:${requestId}`
|
|
368
|
+
);
|
|
369
|
+
if (response) {
|
|
370
|
+
await this.ctx.storage.delete(`elicitation:${requestId}`);
|
|
371
|
+
await this.ctx.storage.delete(`elicitation:response:${requestId}`);
|
|
372
|
+
return response;
|
|
373
|
+
}
|
|
374
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
375
|
+
}
|
|
376
|
+
throw new Error("Elicitation request timed out");
|
|
377
|
+
} finally {
|
|
378
|
+
await this.ctx.storage.delete(`elicitation:${requestId}`);
|
|
379
|
+
await this.ctx.storage.delete(`elicitation:response:${requestId}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Handle elicitation responses */
|
|
384
|
+
async _handleElicitationResponse(message) {
|
|
385
|
+
if (isJSONRPCResponse(message) && message.result) {
|
|
386
|
+
const requestId = message.id?.toString();
|
|
387
|
+
if (!requestId || !requestId.startsWith("elicit_")) return false;
|
|
388
|
+
const pendingRequest = await this.ctx.storage.get(
|
|
389
|
+
`elicitation:${requestId}`
|
|
390
|
+
);
|
|
391
|
+
if (!pendingRequest) return false;
|
|
392
|
+
await this.ctx.storage.put(
|
|
393
|
+
`elicitation:response:${requestId}`,
|
|
394
|
+
message.result
|
|
395
|
+
);
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
if (isJSONRPCError(message)) {
|
|
399
|
+
const requestId = message.id?.toString();
|
|
400
|
+
if (!requestId || !requestId.startsWith("elicit_")) return false;
|
|
401
|
+
const pendingRequest = await this.ctx.storage.get(
|
|
402
|
+
`elicitation:${requestId}`
|
|
403
|
+
);
|
|
404
|
+
if (!pendingRequest) return false;
|
|
405
|
+
const errorResult = {
|
|
406
|
+
action: "cancel",
|
|
407
|
+
content: {
|
|
408
|
+
error: message.error.message || "Elicitation request failed"
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
await this.ctx.storage.put(
|
|
412
|
+
`elicitation:response:${requestId}`,
|
|
413
|
+
errorResult
|
|
414
|
+
);
|
|
415
|
+
return true;
|
|
305
416
|
}
|
|
306
|
-
|
|
417
|
+
return false;
|
|
307
418
|
}
|
|
308
419
|
// All messages received over SSE after the initial connection has been established
|
|
309
420
|
// will be passed here
|
|
310
|
-
async onSSEMcpMessage(
|
|
311
|
-
if (
|
|
312
|
-
await
|
|
421
|
+
async onSSEMcpMessage(_sessionId, messageBody) {
|
|
422
|
+
if (this._status !== "started") {
|
|
423
|
+
await this._initialize();
|
|
313
424
|
}
|
|
314
|
-
if (
|
|
425
|
+
if (this._transportType !== "sse") {
|
|
315
426
|
return new Error("Internal Server Error: Expected SSE protocol");
|
|
316
427
|
}
|
|
317
428
|
try {
|
|
318
|
-
const message = await request.json();
|
|
319
429
|
let parsedMessage;
|
|
320
430
|
try {
|
|
321
|
-
parsedMessage = JSONRPCMessageSchema.parse(
|
|
431
|
+
parsedMessage = JSONRPCMessageSchema.parse(messageBody);
|
|
322
432
|
} catch (error) {
|
|
323
|
-
|
|
433
|
+
this._transport?.onerror?.(error);
|
|
324
434
|
throw error;
|
|
325
435
|
}
|
|
326
|
-
|
|
436
|
+
if (await this._handleElicitationResponse(parsedMessage)) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
this._transport?.onmessage?.(parsedMessage);
|
|
327
440
|
return null;
|
|
328
441
|
} catch (error) {
|
|
329
442
|
console.error("Error forwarding message to SSE:", error);
|
|
330
|
-
|
|
443
|
+
this._transport?.onerror?.(error);
|
|
331
444
|
return error;
|
|
332
445
|
}
|
|
333
446
|
}
|
|
334
447
|
// Delegate all websocket events to the underlying agent
|
|
335
448
|
async webSocketMessage(ws, event) {
|
|
336
|
-
if (
|
|
337
|
-
await
|
|
449
|
+
if (this._status !== "started") {
|
|
450
|
+
await this._initialize();
|
|
338
451
|
}
|
|
339
|
-
return await
|
|
452
|
+
return await this._agent.webSocketMessage(ws, event);
|
|
340
453
|
}
|
|
341
454
|
// WebSocket event handlers for hibernation support
|
|
342
455
|
async webSocketError(ws, error) {
|
|
343
|
-
if (
|
|
344
|
-
await
|
|
456
|
+
if (this._status !== "started") {
|
|
457
|
+
await this._initialize();
|
|
345
458
|
}
|
|
346
|
-
return await
|
|
459
|
+
return await this._agent.webSocketError(ws, error);
|
|
347
460
|
}
|
|
348
461
|
async webSocketClose(ws, code, reason, wasClean) {
|
|
349
|
-
if (
|
|
350
|
-
await
|
|
462
|
+
if (this._status !== "started") {
|
|
463
|
+
await this._initialize();
|
|
351
464
|
}
|
|
352
|
-
return await
|
|
465
|
+
return await this._agent.webSocketClose(ws, code, reason, wasClean);
|
|
353
466
|
}
|
|
354
467
|
static mount(path, {
|
|
355
468
|
binding = "MCP_OBJECT",
|
|
@@ -379,7 +492,7 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
379
492
|
);
|
|
380
493
|
return new Response("Invalid binding", { status: 500 });
|
|
381
494
|
}
|
|
382
|
-
if (bindingValue
|
|
495
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
383
496
|
return new Response("Invalid binding", { status: 500 });
|
|
384
497
|
}
|
|
385
498
|
const namespace = bindingValue;
|
|
@@ -399,12 +512,26 @@ data: ${relativeUrlWithSession}
|
|
|
399
512
|
writer.write(encoder.encode(endpointMessage));
|
|
400
513
|
const id = namespace.idFromName(`sse:${sessionId}`);
|
|
401
514
|
const doStub = namespace.get(id);
|
|
402
|
-
|
|
515
|
+
try {
|
|
516
|
+
await doStub._init(ctx.props);
|
|
517
|
+
} catch (error) {
|
|
518
|
+
console.error("Failed to initialize McpAgent:", error);
|
|
519
|
+
await writer.close();
|
|
520
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
521
|
+
return new Response(`Initialization failed: ${errorMessage}`, {
|
|
522
|
+
status: 500
|
|
523
|
+
});
|
|
524
|
+
}
|
|
403
525
|
const upgradeUrl = new URL(request.url);
|
|
404
526
|
upgradeUrl.pathname = "/sse";
|
|
527
|
+
const existingHeaders = {};
|
|
528
|
+
request.headers.forEach((value, key) => {
|
|
529
|
+
existingHeaders[key] = value;
|
|
530
|
+
});
|
|
405
531
|
const response = await doStub.fetch(
|
|
406
532
|
new Request(upgradeUrl, {
|
|
407
533
|
headers: {
|
|
534
|
+
...existingHeaders,
|
|
408
535
|
Upgrade: "websocket",
|
|
409
536
|
// Required by PartyServer
|
|
410
537
|
"x-partykit-room": sessionId
|
|
@@ -440,10 +567,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
440
567
|
onMessage(event).catch(console.error);
|
|
441
568
|
});
|
|
442
569
|
ws.addEventListener("error", (error) => {
|
|
443
|
-
async function onError(
|
|
570
|
+
async function onError(_error) {
|
|
444
571
|
try {
|
|
445
572
|
await writer.close();
|
|
446
|
-
} catch (
|
|
573
|
+
} catch (_e) {
|
|
447
574
|
}
|
|
448
575
|
}
|
|
449
576
|
onError(error).catch(console.error);
|
|
@@ -460,9 +587,9 @@ data: ${JSON.stringify(result.data)}
|
|
|
460
587
|
});
|
|
461
588
|
return new Response(readable, {
|
|
462
589
|
headers: {
|
|
463
|
-
"Content-Type": "text/event-stream",
|
|
464
590
|
"Cache-Control": "no-cache",
|
|
465
591
|
Connection: "keep-alive",
|
|
592
|
+
"Content-Type": "text/event-stream",
|
|
466
593
|
...corsHeaders(request, corsOptions)
|
|
467
594
|
}
|
|
468
595
|
});
|
|
@@ -495,26 +622,28 @@ data: ${JSON.stringify(result.data)}
|
|
|
495
622
|
}
|
|
496
623
|
const id = namespace.idFromName(`sse:${sessionId}`);
|
|
497
624
|
const doStub = namespace.get(id);
|
|
498
|
-
const
|
|
625
|
+
const messageBody = await request.json();
|
|
626
|
+
await doStub.updateProps(ctx.props);
|
|
627
|
+
const error = await doStub.onSSEMcpMessage(sessionId, messageBody);
|
|
499
628
|
if (error) {
|
|
500
629
|
return new Response(error.message, {
|
|
501
|
-
status: 400,
|
|
502
630
|
headers: {
|
|
503
|
-
"Content-Type": "text/event-stream",
|
|
504
631
|
"Cache-Control": "no-cache",
|
|
505
632
|
Connection: "keep-alive",
|
|
633
|
+
"Content-Type": "text/event-stream",
|
|
506
634
|
...corsHeaders(request, corsOptions)
|
|
507
|
-
}
|
|
635
|
+
},
|
|
636
|
+
status: 400
|
|
508
637
|
});
|
|
509
638
|
}
|
|
510
639
|
return new Response("Accepted", {
|
|
511
|
-
status: 202,
|
|
512
640
|
headers: {
|
|
513
|
-
"Content-Type": "text/event-stream",
|
|
514
641
|
"Cache-Control": "no-cache",
|
|
515
642
|
Connection: "keep-alive",
|
|
643
|
+
"Content-Type": "text/event-stream",
|
|
516
644
|
...corsHeaders(request, corsOptions)
|
|
517
|
-
}
|
|
645
|
+
},
|
|
646
|
+
status: 202
|
|
518
647
|
});
|
|
519
648
|
}
|
|
520
649
|
return new Response("Not Found", { status: 404 });
|
|
@@ -544,7 +673,7 @@ data: ${JSON.stringify(result.data)}
|
|
|
544
673
|
);
|
|
545
674
|
return new Response("Invalid binding", { status: 500 });
|
|
546
675
|
}
|
|
547
|
-
if (bindingValue
|
|
676
|
+
if (!isDurableObjectNamespace(bindingValue)) {
|
|
548
677
|
return new Response("Invalid binding", { status: 500 });
|
|
549
678
|
}
|
|
550
679
|
const namespace = bindingValue;
|
|
@@ -552,24 +681,24 @@ data: ${JSON.stringify(result.data)}
|
|
|
552
681
|
const acceptHeader = request.headers.get("accept");
|
|
553
682
|
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
|
|
554
683
|
const body2 = JSON.stringify({
|
|
555
|
-
jsonrpc: "2.0",
|
|
556
684
|
error: {
|
|
557
685
|
code: -32e3,
|
|
558
686
|
message: "Not Acceptable: Client must accept both application/json and text/event-stream"
|
|
559
687
|
},
|
|
560
|
-
id: null
|
|
688
|
+
id: null,
|
|
689
|
+
jsonrpc: "2.0"
|
|
561
690
|
});
|
|
562
691
|
return new Response(body2, { status: 406 });
|
|
563
692
|
}
|
|
564
693
|
const ct = request.headers.get("content-type");
|
|
565
694
|
if (!ct || !ct.includes("application/json")) {
|
|
566
695
|
const body2 = JSON.stringify({
|
|
567
|
-
jsonrpc: "2.0",
|
|
568
696
|
error: {
|
|
569
697
|
code: -32e3,
|
|
570
698
|
message: "Unsupported Media Type: Content-Type must be application/json"
|
|
571
699
|
},
|
|
572
|
-
id: null
|
|
700
|
+
id: null,
|
|
701
|
+
jsonrpc: "2.0"
|
|
573
702
|
});
|
|
574
703
|
return new Response(body2, { status: 415 });
|
|
575
704
|
}
|
|
@@ -579,12 +708,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
579
708
|
);
|
|
580
709
|
if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {
|
|
581
710
|
const body2 = JSON.stringify({
|
|
582
|
-
jsonrpc: "2.0",
|
|
583
711
|
error: {
|
|
584
712
|
code: -32e3,
|
|
585
713
|
message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`
|
|
586
714
|
},
|
|
587
|
-
id: null
|
|
715
|
+
id: null,
|
|
716
|
+
jsonrpc: "2.0"
|
|
588
717
|
});
|
|
589
718
|
return new Response(body2, { status: 413 });
|
|
590
719
|
}
|
|
@@ -592,14 +721,14 @@ data: ${JSON.stringify(result.data)}
|
|
|
592
721
|
let rawMessage;
|
|
593
722
|
try {
|
|
594
723
|
rawMessage = await request.json();
|
|
595
|
-
} catch (
|
|
724
|
+
} catch (_error) {
|
|
596
725
|
const body2 = JSON.stringify({
|
|
597
|
-
jsonrpc: "2.0",
|
|
598
726
|
error: {
|
|
599
727
|
code: -32700,
|
|
600
728
|
message: "Parse error: Invalid JSON"
|
|
601
729
|
},
|
|
602
|
-
id: null
|
|
730
|
+
id: null,
|
|
731
|
+
jsonrpc: "2.0"
|
|
603
732
|
});
|
|
604
733
|
return new Response(body2, { status: 400 });
|
|
605
734
|
}
|
|
@@ -613,12 +742,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
613
742
|
for (const msg of arrayMessage) {
|
|
614
743
|
if (!JSONRPCMessageSchema.safeParse(msg).success) {
|
|
615
744
|
const body2 = JSON.stringify({
|
|
616
|
-
jsonrpc: "2.0",
|
|
617
745
|
error: {
|
|
618
746
|
code: -32700,
|
|
619
747
|
message: "Parse error: Invalid JSON-RPC message"
|
|
620
748
|
},
|
|
621
|
-
id: null
|
|
749
|
+
id: null,
|
|
750
|
+
jsonrpc: "2.0"
|
|
622
751
|
});
|
|
623
752
|
return new Response(body2, { status: 400 });
|
|
624
753
|
}
|
|
@@ -629,34 +758,34 @@ data: ${JSON.stringify(result.data)}
|
|
|
629
758
|
);
|
|
630
759
|
if (isInitializationRequest && sessionId) {
|
|
631
760
|
const body2 = JSON.stringify({
|
|
632
|
-
jsonrpc: "2.0",
|
|
633
761
|
error: {
|
|
634
762
|
code: -32600,
|
|
635
763
|
message: "Invalid Request: Initialization requests must not include a sessionId"
|
|
636
764
|
},
|
|
637
|
-
id: null
|
|
765
|
+
id: null,
|
|
766
|
+
jsonrpc: "2.0"
|
|
638
767
|
});
|
|
639
768
|
return new Response(body2, { status: 400 });
|
|
640
769
|
}
|
|
641
770
|
if (isInitializationRequest && messages.length > 1) {
|
|
642
771
|
const body2 = JSON.stringify({
|
|
643
|
-
jsonrpc: "2.0",
|
|
644
772
|
error: {
|
|
645
773
|
code: -32600,
|
|
646
774
|
message: "Invalid Request: Only one initialization request is allowed"
|
|
647
775
|
},
|
|
648
|
-
id: null
|
|
776
|
+
id: null,
|
|
777
|
+
jsonrpc: "2.0"
|
|
649
778
|
});
|
|
650
779
|
return new Response(body2, { status: 400 });
|
|
651
780
|
}
|
|
652
781
|
if (!isInitializationRequest && !sessionId) {
|
|
653
782
|
const body2 = JSON.stringify({
|
|
654
|
-
jsonrpc: "2.0",
|
|
655
783
|
error: {
|
|
656
784
|
code: -32e3,
|
|
657
785
|
message: "Bad Request: Mcp-Session-Id header is required"
|
|
658
786
|
},
|
|
659
|
-
id: null
|
|
787
|
+
id: null,
|
|
788
|
+
jsonrpc: "2.0"
|
|
660
789
|
});
|
|
661
790
|
return new Response(body2, { status: 400 });
|
|
662
791
|
}
|
|
@@ -665,27 +794,48 @@ data: ${JSON.stringify(result.data)}
|
|
|
665
794
|
const doStub = namespace.get(id);
|
|
666
795
|
const isInitialized = await doStub.isInitialized();
|
|
667
796
|
if (isInitializationRequest) {
|
|
668
|
-
|
|
669
|
-
|
|
797
|
+
try {
|
|
798
|
+
await doStub._init(ctx.props);
|
|
799
|
+
await doStub.setInitialized();
|
|
800
|
+
} catch (error) {
|
|
801
|
+
console.error("Failed to initialize McpAgent:", error);
|
|
802
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
803
|
+
const body2 = JSON.stringify({
|
|
804
|
+
error: {
|
|
805
|
+
code: -32001,
|
|
806
|
+
message: `Initialization failed: ${errorMessage}`
|
|
807
|
+
},
|
|
808
|
+
id: null,
|
|
809
|
+
jsonrpc: "2.0"
|
|
810
|
+
});
|
|
811
|
+
return new Response(body2, { status: 500 });
|
|
812
|
+
}
|
|
670
813
|
} else if (!isInitialized) {
|
|
671
814
|
const body2 = JSON.stringify({
|
|
672
|
-
jsonrpc: "2.0",
|
|
673
815
|
error: {
|
|
674
816
|
code: -32001,
|
|
675
817
|
message: "Session not found"
|
|
676
818
|
},
|
|
677
|
-
id: null
|
|
819
|
+
id: null,
|
|
820
|
+
jsonrpc: "2.0"
|
|
678
821
|
});
|
|
679
822
|
return new Response(body2, { status: 404 });
|
|
823
|
+
} else {
|
|
824
|
+
await doStub.updateProps(ctx.props);
|
|
680
825
|
}
|
|
681
826
|
const { readable, writable } = new TransformStream();
|
|
682
827
|
const writer = writable.getWriter();
|
|
683
828
|
const encoder = new TextEncoder();
|
|
684
829
|
const upgradeUrl = new URL(request.url);
|
|
685
830
|
upgradeUrl.pathname = "/streamable-http";
|
|
831
|
+
const existingHeaders = {};
|
|
832
|
+
request.headers.forEach((value, key) => {
|
|
833
|
+
existingHeaders[key] = value;
|
|
834
|
+
});
|
|
686
835
|
const response = await doStub.fetch(
|
|
687
836
|
new Request(upgradeUrl, {
|
|
688
837
|
headers: {
|
|
838
|
+
...existingHeaders,
|
|
689
839
|
Upgrade: "websocket",
|
|
690
840
|
// Required by PartyServer
|
|
691
841
|
"x-partykit-room": sessionId
|
|
@@ -697,12 +847,12 @@ data: ${JSON.stringify(result.data)}
|
|
|
697
847
|
console.error("Failed to establish WebSocket connection");
|
|
698
848
|
await writer.close();
|
|
699
849
|
const body2 = JSON.stringify({
|
|
700
|
-
jsonrpc: "2.0",
|
|
701
850
|
error: {
|
|
702
851
|
code: -32001,
|
|
703
852
|
message: "Failed to establish WebSocket connection"
|
|
704
853
|
},
|
|
705
|
-
id: null
|
|
854
|
+
id: null,
|
|
855
|
+
jsonrpc: "2.0"
|
|
706
856
|
});
|
|
707
857
|
return new Response(body2, { status: 500 });
|
|
708
858
|
}
|
|
@@ -735,10 +885,10 @@ data: ${JSON.stringify(result.data)}
|
|
|
735
885
|
onMessage(event).catch(console.error);
|
|
736
886
|
});
|
|
737
887
|
ws.addEventListener("error", (error) => {
|
|
738
|
-
async function onError(
|
|
888
|
+
async function onError(_error) {
|
|
739
889
|
try {
|
|
740
890
|
await writer.close();
|
|
741
|
-
} catch (
|
|
891
|
+
} catch (_e) {
|
|
742
892
|
}
|
|
743
893
|
}
|
|
744
894
|
onError(error).catch(console.error);
|
|
@@ -762,8 +912,8 @@ data: ${JSON.stringify(result.data)}
|
|
|
762
912
|
}
|
|
763
913
|
ws.close();
|
|
764
914
|
return new Response(null, {
|
|
765
|
-
|
|
766
|
-
|
|
915
|
+
headers: corsHeaders(request, corsOptions),
|
|
916
|
+
status: 202
|
|
767
917
|
});
|
|
768
918
|
}
|
|
769
919
|
for (const message of messages) {
|
|
@@ -774,9 +924,9 @@ data: ${JSON.stringify(result.data)}
|
|
|
774
924
|
}
|
|
775
925
|
return new Response(readable, {
|
|
776
926
|
headers: {
|
|
777
|
-
"Content-Type": "text/event-stream",
|
|
778
927
|
"Cache-Control": "no-cache",
|
|
779
928
|
Connection: "keep-alive",
|
|
929
|
+
"Content-Type": "text/event-stream",
|
|
780
930
|
"mcp-session-id": sessionId,
|
|
781
931
|
...corsHeaders(request, corsOptions)
|
|
782
932
|
},
|
|
@@ -784,33 +934,22 @@ data: ${JSON.stringify(result.data)}
|
|
|
784
934
|
});
|
|
785
935
|
}
|
|
786
936
|
const body = JSON.stringify({
|
|
787
|
-
jsonrpc: "2.0",
|
|
788
937
|
error: {
|
|
789
938
|
code: -32e3,
|
|
790
939
|
message: "Method not allowed"
|
|
791
940
|
},
|
|
792
|
-
id: null
|
|
941
|
+
id: null,
|
|
942
|
+
jsonrpc: "2.0"
|
|
793
943
|
});
|
|
794
944
|
return new Response(body, { status: 405 });
|
|
795
945
|
}
|
|
796
946
|
};
|
|
797
947
|
}
|
|
798
948
|
};
|
|
799
|
-
_status = new WeakMap();
|
|
800
|
-
_transport = new WeakMap();
|
|
801
|
-
_transportType = new WeakMap();
|
|
802
|
-
_requestIdToConnectionId = new WeakMap();
|
|
803
|
-
_agent = new WeakMap();
|
|
804
|
-
_McpAgent_instances = new WeakSet();
|
|
805
|
-
initialize_fn = async function() {
|
|
806
|
-
await this.ctx.blockConcurrencyWhile(async () => {
|
|
807
|
-
__privateSet(this, _status, "starting");
|
|
808
|
-
await this.onStart();
|
|
809
|
-
__privateSet(this, _status, "started");
|
|
810
|
-
});
|
|
811
|
-
};
|
|
812
|
-
var McpAgent = _McpAgent;
|
|
813
949
|
export {
|
|
814
|
-
|
|
950
|
+
ElicitRequestSchema,
|
|
951
|
+
McpAgent,
|
|
952
|
+
SSEEdgeClientTransport,
|
|
953
|
+
StreamableHTTPEdgeClientTransport
|
|
815
954
|
};
|
|
816
955
|
//# sourceMappingURL=index.js.map
|