agents 0.0.0-74a8c74 → 0.0.0-7b22285
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-agent.d.ts +0 -1
- package/dist/ai-chat-agent.js +60 -63
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.js +18 -9
- package/dist/ai-react.js.map +1 -1
- package/dist/chunk-HMLY7DHA.js +16 -0
- package/dist/chunk-HMLY7DHA.js.map +1 -0
- package/dist/{chunk-SZEXGW6W.js → chunk-XG52S6YY.js} +151 -140
- package/dist/chunk-XG52S6YY.js.map +1 -0
- package/dist/client.js +43 -43
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +0 -6
- package/dist/index.js +2 -3
- package/dist/mcp/client.d.ts +110 -22
- package/dist/mcp/client.js +193 -571
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +41 -0
- package/dist/mcp/do-oauth-client-provider.js +107 -0
- package/dist/mcp/do-oauth-client-provider.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -4
- package/dist/mcp/index.js +268 -54
- package/dist/mcp/index.js.map +1 -1
- package/dist/react.js +36 -27
- package/dist/react.js.map +1 -1
- package/dist/schedule.js +2 -0
- package/dist/schedule.js.map +1 -1
- package/package.json +7 -4
- package/src/index.ts +0 -7
- package/dist/chunk-EZ76ZGDB.js +0 -1721
- package/dist/chunk-EZ76ZGDB.js.map +0 -1
- package/dist/chunk-SZEXGW6W.js.map +0 -1
package/dist/mcp/client.js
CHANGED
|
@@ -1,577 +1,93 @@
|
|
|
1
|
-
import
|
|
2
|
-
CallToolResultSchema,
|
|
3
|
-
CancelledNotificationSchema,
|
|
4
|
-
CompleteResultSchema,
|
|
5
|
-
EmptyResultSchema,
|
|
6
|
-
ErrorCode,
|
|
7
|
-
GetPromptResultSchema,
|
|
8
|
-
InitializeResultSchema,
|
|
9
|
-
LATEST_PROTOCOL_VERSION,
|
|
10
|
-
ListPromptsResultSchema,
|
|
11
|
-
ListResourceTemplatesResultSchema,
|
|
12
|
-
ListResourcesResultSchema,
|
|
13
|
-
ListToolsResultSchema,
|
|
14
|
-
McpError,
|
|
15
|
-
PingRequestSchema,
|
|
16
|
-
ProgressNotificationSchema,
|
|
17
|
-
PromptListChangedNotificationSchema,
|
|
18
|
-
ReadResourceResultSchema,
|
|
19
|
-
ResourceListChangedNotificationSchema,
|
|
20
|
-
SSEEdgeClientTransport,
|
|
21
|
-
SUPPORTED_PROTOCOL_VERSIONS,
|
|
22
|
-
ToolListChangedNotificationSchema
|
|
23
|
-
} from "../chunk-EZ76ZGDB.js";
|
|
1
|
+
import "../chunk-HMLY7DHA.js";
|
|
24
2
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this._requestMessageId = 0;
|
|
31
|
-
this._requestHandlers = /* @__PURE__ */ new Map();
|
|
32
|
-
this._requestHandlerAbortControllers = /* @__PURE__ */ new Map();
|
|
33
|
-
this._notificationHandlers = /* @__PURE__ */ new Map();
|
|
34
|
-
this._responseHandlers = /* @__PURE__ */ new Map();
|
|
35
|
-
this._progressHandlers = /* @__PURE__ */ new Map();
|
|
36
|
-
this._timeoutInfo = /* @__PURE__ */ new Map();
|
|
37
|
-
this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
|
|
38
|
-
const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
|
|
39
|
-
controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
|
|
40
|
-
});
|
|
41
|
-
this.setNotificationHandler(ProgressNotificationSchema, (notification) => {
|
|
42
|
-
this._onprogress(notification);
|
|
43
|
-
});
|
|
44
|
-
this.setRequestHandler(
|
|
45
|
-
PingRequestSchema,
|
|
46
|
-
// Automatic pong by default.
|
|
47
|
-
(_request) => ({})
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
_setupTimeout(messageId, timeout, maxTotalTimeout, onTimeout) {
|
|
51
|
-
this._timeoutInfo.set(messageId, {
|
|
52
|
-
timeoutId: setTimeout(onTimeout, timeout),
|
|
53
|
-
startTime: Date.now(),
|
|
54
|
-
timeout,
|
|
55
|
-
maxTotalTimeout,
|
|
56
|
-
onTimeout
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
_resetTimeout(messageId) {
|
|
60
|
-
const info = this._timeoutInfo.get(messageId);
|
|
61
|
-
if (!info)
|
|
62
|
-
return false;
|
|
63
|
-
const totalElapsed = Date.now() - info.startTime;
|
|
64
|
-
if (info.maxTotalTimeout && totalElapsed >= info.maxTotalTimeout) {
|
|
65
|
-
this._timeoutInfo.delete(messageId);
|
|
66
|
-
throw new McpError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", { maxTotalTimeout: info.maxTotalTimeout, totalElapsed });
|
|
67
|
-
}
|
|
68
|
-
clearTimeout(info.timeoutId);
|
|
69
|
-
info.timeoutId = setTimeout(info.onTimeout, info.timeout);
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
_cleanupTimeout(messageId) {
|
|
73
|
-
const info = this._timeoutInfo.get(messageId);
|
|
74
|
-
if (info) {
|
|
75
|
-
clearTimeout(info.timeoutId);
|
|
76
|
-
this._timeoutInfo.delete(messageId);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
3
|
+
// src/mcp/sse-edge.ts
|
|
4
|
+
import {
|
|
5
|
+
SSEClientTransport
|
|
6
|
+
} from "@modelcontextprotocol/sdk/client/sse.js";
|
|
7
|
+
var SSEEdgeClientTransport = class extends SSEClientTransport {
|
|
79
8
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
|
|
9
|
+
* Creates a new EdgeSSEClientTransport, which overrides fetch to be compatible with the CF workers environment
|
|
83
10
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this._transport.onmessage = (message) => {
|
|
93
|
-
if (!("method" in message)) {
|
|
94
|
-
this._onresponse(message);
|
|
95
|
-
} else if ("id" in message) {
|
|
96
|
-
this._onrequest(message);
|
|
97
|
-
} else {
|
|
98
|
-
this._onnotification(message);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
await this._transport.start();
|
|
102
|
-
}
|
|
103
|
-
_onclose() {
|
|
104
|
-
var _a;
|
|
105
|
-
const responseHandlers = this._responseHandlers;
|
|
106
|
-
this._responseHandlers = /* @__PURE__ */ new Map();
|
|
107
|
-
this._progressHandlers.clear();
|
|
108
|
-
this._transport = void 0;
|
|
109
|
-
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
110
|
-
const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
|
|
111
|
-
for (const handler of responseHandlers.values()) {
|
|
112
|
-
handler(error);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
_onerror(error) {
|
|
116
|
-
var _a;
|
|
117
|
-
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
118
|
-
}
|
|
119
|
-
_onnotification(notification) {
|
|
120
|
-
var _a;
|
|
121
|
-
const handler = (_a = this._notificationHandlers.get(notification.method)) !== null && _a !== void 0 ? _a : this.fallbackNotificationHandler;
|
|
122
|
-
if (handler === void 0) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
Promise.resolve().then(() => handler(notification)).catch((error) => this._onerror(new Error(`Uncaught error in notification handler: ${error}`)));
|
|
126
|
-
}
|
|
127
|
-
_onrequest(request) {
|
|
128
|
-
var _a, _b, _c;
|
|
129
|
-
const handler = (_a = this._requestHandlers.get(request.method)) !== null && _a !== void 0 ? _a : this.fallbackRequestHandler;
|
|
130
|
-
if (handler === void 0) {
|
|
131
|
-
(_b = this._transport) === null || _b === void 0 ? void 0 : _b.send({
|
|
132
|
-
jsonrpc: "2.0",
|
|
133
|
-
id: request.id,
|
|
134
|
-
error: {
|
|
135
|
-
code: ErrorCode.MethodNotFound,
|
|
136
|
-
message: "Method not found"
|
|
11
|
+
constructor(url, options) {
|
|
12
|
+
const fetchOverride = async (fetchUrl, fetchInit = {}) => {
|
|
13
|
+
const headers = await this.authHeaders();
|
|
14
|
+
const workerOptions = {
|
|
15
|
+
...fetchInit,
|
|
16
|
+
headers: {
|
|
17
|
+
...fetchInit?.headers,
|
|
18
|
+
...headers
|
|
137
19
|
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const abortController = new AbortController();
|
|
142
|
-
this._requestHandlerAbortControllers.set(request.id, abortController);
|
|
143
|
-
const extra = {
|
|
144
|
-
signal: abortController.signal,
|
|
145
|
-
sessionId: (_c = this._transport) === null || _c === void 0 ? void 0 : _c.sessionId
|
|
20
|
+
};
|
|
21
|
+
delete workerOptions.mode;
|
|
22
|
+
return fetch(fetchUrl, workerOptions);
|
|
146
23
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
return (_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send({
|
|
153
|
-
result,
|
|
154
|
-
jsonrpc: "2.0",
|
|
155
|
-
id: request.id
|
|
156
|
-
});
|
|
157
|
-
}, (error) => {
|
|
158
|
-
var _a2, _b2;
|
|
159
|
-
if (abortController.signal.aborted) {
|
|
160
|
-
return;
|
|
24
|
+
super(url, {
|
|
25
|
+
...options,
|
|
26
|
+
eventSourceInit: {
|
|
27
|
+
fetch: fetchOverride
|
|
161
28
|
}
|
|
162
|
-
return (_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send({
|
|
163
|
-
jsonrpc: "2.0",
|
|
164
|
-
id: request.id,
|
|
165
|
-
error: {
|
|
166
|
-
code: Number.isSafeInteger(error["code"]) ? error["code"] : ErrorCode.InternalError,
|
|
167
|
-
message: (_b2 = error.message) !== null && _b2 !== void 0 ? _b2 : "Internal error"
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
}).catch((error) => this._onerror(new Error(`Failed to send response: ${error}`))).finally(() => {
|
|
171
|
-
this._requestHandlerAbortControllers.delete(request.id);
|
|
172
29
|
});
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
const responseHandler = this._responseHandlers.get(messageId);
|
|
183
|
-
if (this._timeoutInfo.has(messageId) && responseHandler) {
|
|
184
|
-
try {
|
|
185
|
-
this._resetTimeout(messageId);
|
|
186
|
-
} catch (error) {
|
|
187
|
-
responseHandler(error);
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
handler(params);
|
|
192
|
-
}
|
|
193
|
-
_onresponse(response) {
|
|
194
|
-
const messageId = Number(response.id);
|
|
195
|
-
const handler = this._responseHandlers.get(messageId);
|
|
196
|
-
if (handler === void 0) {
|
|
197
|
-
this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(response)}`));
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
this._responseHandlers.delete(messageId);
|
|
201
|
-
this._progressHandlers.delete(messageId);
|
|
202
|
-
this._cleanupTimeout(messageId);
|
|
203
|
-
if ("result" in response) {
|
|
204
|
-
handler(response);
|
|
205
|
-
} else {
|
|
206
|
-
const error = new McpError(response.error.code, response.error.message, response.error.data);
|
|
207
|
-
handler(error);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
get transport() {
|
|
211
|
-
return this._transport;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Closes the connection.
|
|
215
|
-
*/
|
|
216
|
-
async close() {
|
|
217
|
-
var _a;
|
|
218
|
-
await ((_a = this._transport) === null || _a === void 0 ? void 0 : _a.close());
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Sends a request and wait for a response.
|
|
222
|
-
*
|
|
223
|
-
* Do not use this method to emit notifications! Use notification() instead.
|
|
224
|
-
*/
|
|
225
|
-
request(request, resultSchema, options) {
|
|
226
|
-
return new Promise((resolve, reject) => {
|
|
227
|
-
var _a, _b, _c, _d;
|
|
228
|
-
if (!this._transport) {
|
|
229
|
-
reject(new Error("Not connected"));
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.enforceStrictCapabilities) === true) {
|
|
233
|
-
this.assertCapabilityForMethod(request.method);
|
|
234
|
-
}
|
|
235
|
-
(_b = options === null || options === void 0 ? void 0 : options.signal) === null || _b === void 0 ? void 0 : _b.throwIfAborted();
|
|
236
|
-
const messageId = this._requestMessageId++;
|
|
237
|
-
const jsonrpcRequest = {
|
|
238
|
-
...request,
|
|
239
|
-
jsonrpc: "2.0",
|
|
240
|
-
id: messageId
|
|
241
|
-
};
|
|
242
|
-
if (options === null || options === void 0 ? void 0 : options.onprogress) {
|
|
243
|
-
this._progressHandlers.set(messageId, options.onprogress);
|
|
244
|
-
jsonrpcRequest.params = {
|
|
245
|
-
...request.params,
|
|
246
|
-
_meta: { progressToken: messageId }
|
|
30
|
+
this.authProvider = options.authProvider;
|
|
31
|
+
}
|
|
32
|
+
async authHeaders() {
|
|
33
|
+
if (this.authProvider) {
|
|
34
|
+
const tokens = await this.authProvider.tokens();
|
|
35
|
+
if (tokens) {
|
|
36
|
+
return {
|
|
37
|
+
Authorization: `Bearer ${tokens.access_token}`
|
|
247
38
|
};
|
|
248
39
|
}
|
|
249
|
-
const cancel = (reason) => {
|
|
250
|
-
var _a2;
|
|
251
|
-
this._responseHandlers.delete(messageId);
|
|
252
|
-
this._progressHandlers.delete(messageId);
|
|
253
|
-
this._cleanupTimeout(messageId);
|
|
254
|
-
(_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send({
|
|
255
|
-
jsonrpc: "2.0",
|
|
256
|
-
method: "notifications/cancelled",
|
|
257
|
-
params: {
|
|
258
|
-
requestId: messageId,
|
|
259
|
-
reason: String(reason)
|
|
260
|
-
}
|
|
261
|
-
}).catch((error) => this._onerror(new Error(`Failed to send cancellation: ${error}`)));
|
|
262
|
-
reject(reason);
|
|
263
|
-
};
|
|
264
|
-
this._responseHandlers.set(messageId, (response) => {
|
|
265
|
-
var _a2;
|
|
266
|
-
if ((_a2 = options === null || options === void 0 ? void 0 : options.signal) === null || _a2 === void 0 ? void 0 : _a2.aborted) {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (response instanceof Error) {
|
|
270
|
-
return reject(response);
|
|
271
|
-
}
|
|
272
|
-
try {
|
|
273
|
-
const result = resultSchema.parse(response.result);
|
|
274
|
-
resolve(result);
|
|
275
|
-
} catch (error) {
|
|
276
|
-
reject(error);
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
(_c = options === null || options === void 0 ? void 0 : options.signal) === null || _c === void 0 ? void 0 : _c.addEventListener("abort", () => {
|
|
280
|
-
var _a2;
|
|
281
|
-
cancel((_a2 = options === null || options === void 0 ? void 0 : options.signal) === null || _a2 === void 0 ? void 0 : _a2.reason);
|
|
282
|
-
});
|
|
283
|
-
const timeout = (_d = options === null || options === void 0 ? void 0 : options.timeout) !== null && _d !== void 0 ? _d : DEFAULT_REQUEST_TIMEOUT_MSEC;
|
|
284
|
-
const timeoutHandler = () => cancel(new McpError(ErrorCode.RequestTimeout, "Request timed out", { timeout }));
|
|
285
|
-
this._setupTimeout(messageId, timeout, options === null || options === void 0 ? void 0 : options.maxTotalTimeout, timeoutHandler);
|
|
286
|
-
this._transport.send(jsonrpcRequest).catch((error) => {
|
|
287
|
-
this._cleanupTimeout(messageId);
|
|
288
|
-
reject(error);
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Emits a notification, which is a one-way message that does not expect a response.
|
|
294
|
-
*/
|
|
295
|
-
async notification(notification) {
|
|
296
|
-
if (!this._transport) {
|
|
297
|
-
throw new Error("Not connected");
|
|
298
40
|
}
|
|
299
|
-
this.assertNotificationCapability(notification.method);
|
|
300
|
-
const jsonrpcNotification = {
|
|
301
|
-
...notification,
|
|
302
|
-
jsonrpc: "2.0"
|
|
303
|
-
};
|
|
304
|
-
await this._transport.send(jsonrpcNotification);
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Registers a handler to invoke when this protocol object receives a request with the given method.
|
|
308
|
-
*
|
|
309
|
-
* Note that this will replace any previous request handler for the same method.
|
|
310
|
-
*/
|
|
311
|
-
setRequestHandler(requestSchema, handler) {
|
|
312
|
-
const method = requestSchema.shape.method.value;
|
|
313
|
-
this.assertRequestHandlerCapability(method);
|
|
314
|
-
this._requestHandlers.set(method, (request, extra) => Promise.resolve(handler(requestSchema.parse(request), extra)));
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Removes the request handler for the given method.
|
|
318
|
-
*/
|
|
319
|
-
removeRequestHandler(method) {
|
|
320
|
-
this._requestHandlers.delete(method);
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
|
|
324
|
-
*/
|
|
325
|
-
assertCanSetRequestHandler(method) {
|
|
326
|
-
if (this._requestHandlers.has(method)) {
|
|
327
|
-
throw new Error(`A request handler for ${method} already exists, which would be overridden`);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Registers a handler to invoke when this protocol object receives a notification with the given method.
|
|
332
|
-
*
|
|
333
|
-
* Note that this will replace any previous notification handler for the same method.
|
|
334
|
-
*/
|
|
335
|
-
setNotificationHandler(notificationSchema, handler) {
|
|
336
|
-
this._notificationHandlers.set(notificationSchema.shape.method.value, (notification) => Promise.resolve(handler(notificationSchema.parse(notification))));
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Removes the notification handler for the given method.
|
|
340
|
-
*/
|
|
341
|
-
removeNotificationHandler(method) {
|
|
342
|
-
this._notificationHandlers.delete(method);
|
|
343
41
|
}
|
|
344
42
|
};
|
|
345
|
-
function mergeCapabilities(base, additional) {
|
|
346
|
-
return Object.entries(additional).reduce((acc, [key, value]) => {
|
|
347
|
-
if (value && typeof value === "object") {
|
|
348
|
-
acc[key] = acc[key] ? { ...acc[key], ...value } : value;
|
|
349
|
-
} else {
|
|
350
|
-
acc[key] = value;
|
|
351
|
-
}
|
|
352
|
-
return acc;
|
|
353
|
-
}, { ...base });
|
|
354
|
-
}
|
|
355
43
|
|
|
356
|
-
//
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
this.
|
|
44
|
+
// src/mcp/client-connection.ts
|
|
45
|
+
import {
|
|
46
|
+
ToolListChangedNotificationSchema,
|
|
47
|
+
ResourceListChangedNotificationSchema,
|
|
48
|
+
PromptListChangedNotificationSchema
|
|
49
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
50
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
51
|
+
var MCPClientConnection = class {
|
|
52
|
+
constructor(url, info, options = { transport: {}, client: {}, capabilities: {} }) {
|
|
53
|
+
this.url = url;
|
|
54
|
+
this.options = options;
|
|
55
|
+
this.connectionState = "connecting";
|
|
56
|
+
this.tools = [];
|
|
57
|
+
this.prompts = [];
|
|
58
|
+
this.resources = [];
|
|
59
|
+
this.resourceTemplates = [];
|
|
60
|
+
this.client = new Client(info, options.client);
|
|
61
|
+
this.client.registerCapabilities(options.capabilities);
|
|
366
62
|
}
|
|
367
63
|
/**
|
|
368
|
-
*
|
|
64
|
+
* Initialize a client connection
|
|
369
65
|
*
|
|
370
|
-
*
|
|
66
|
+
* @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized
|
|
67
|
+
* @returns
|
|
371
68
|
*/
|
|
372
|
-
|
|
373
|
-
if (this.transport) {
|
|
374
|
-
throw new Error("Cannot register capabilities after connecting to transport");
|
|
375
|
-
}
|
|
376
|
-
this._capabilities = mergeCapabilities(this._capabilities, capabilities);
|
|
377
|
-
}
|
|
378
|
-
assertCapability(capability, method) {
|
|
379
|
-
var _a;
|
|
380
|
-
if (!((_a = this._serverCapabilities) === null || _a === void 0 ? void 0 : _a[capability])) {
|
|
381
|
-
throw new Error(`Server does not support ${capability} (required for ${method})`);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
async connect(transport) {
|
|
385
|
-
await super.connect(transport);
|
|
69
|
+
async init(code, clientId) {
|
|
386
70
|
try {
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
}, InitializeResultSchema);
|
|
395
|
-
if (result === void 0) {
|
|
396
|
-
throw new Error(`Server sent invalid initialize result: ${result}`);
|
|
71
|
+
const transport = new SSEEdgeClientTransport(
|
|
72
|
+
this.url,
|
|
73
|
+
this.options.transport
|
|
74
|
+
);
|
|
75
|
+
if (code) {
|
|
76
|
+
await transport.finishAuth(code);
|
|
397
77
|
}
|
|
398
|
-
|
|
399
|
-
|
|
78
|
+
await this.client.connect(transport);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
if (e.toString().includes("Unauthorized")) {
|
|
81
|
+
this.connectionState = "authenticating";
|
|
82
|
+
return;
|
|
400
83
|
}
|
|
401
|
-
this.
|
|
402
|
-
|
|
403
|
-
this._instructions = result.instructions;
|
|
404
|
-
await this.notification({
|
|
405
|
-
method: "notifications/initialized"
|
|
406
|
-
});
|
|
407
|
-
} catch (error) {
|
|
408
|
-
void this.close();
|
|
409
|
-
throw error;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* After initialization has completed, this will be populated with the server's reported capabilities.
|
|
414
|
-
*/
|
|
415
|
-
getServerCapabilities() {
|
|
416
|
-
return this._serverCapabilities;
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* After initialization has completed, this will be populated with information about the server's name and version.
|
|
420
|
-
*/
|
|
421
|
-
getServerVersion() {
|
|
422
|
-
return this._serverVersion;
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* After initialization has completed, this may be populated with information about the server's instructions.
|
|
426
|
-
*/
|
|
427
|
-
getInstructions() {
|
|
428
|
-
return this._instructions;
|
|
429
|
-
}
|
|
430
|
-
assertCapabilityForMethod(method) {
|
|
431
|
-
var _a, _b, _c, _d, _e;
|
|
432
|
-
switch (method) {
|
|
433
|
-
case "logging/setLevel":
|
|
434
|
-
if (!((_a = this._serverCapabilities) === null || _a === void 0 ? void 0 : _a.logging)) {
|
|
435
|
-
throw new Error(`Server does not support logging (required for ${method})`);
|
|
436
|
-
}
|
|
437
|
-
break;
|
|
438
|
-
case "prompts/get":
|
|
439
|
-
case "prompts/list":
|
|
440
|
-
if (!((_b = this._serverCapabilities) === null || _b === void 0 ? void 0 : _b.prompts)) {
|
|
441
|
-
throw new Error(`Server does not support prompts (required for ${method})`);
|
|
442
|
-
}
|
|
443
|
-
break;
|
|
444
|
-
case "resources/list":
|
|
445
|
-
case "resources/templates/list":
|
|
446
|
-
case "resources/read":
|
|
447
|
-
case "resources/subscribe":
|
|
448
|
-
case "resources/unsubscribe":
|
|
449
|
-
if (!((_c = this._serverCapabilities) === null || _c === void 0 ? void 0 : _c.resources)) {
|
|
450
|
-
throw new Error(`Server does not support resources (required for ${method})`);
|
|
451
|
-
}
|
|
452
|
-
if (method === "resources/subscribe" && !this._serverCapabilities.resources.subscribe) {
|
|
453
|
-
throw new Error(`Server does not support resource subscriptions (required for ${method})`);
|
|
454
|
-
}
|
|
455
|
-
break;
|
|
456
|
-
case "tools/call":
|
|
457
|
-
case "tools/list":
|
|
458
|
-
if (!((_d = this._serverCapabilities) === null || _d === void 0 ? void 0 : _d.tools)) {
|
|
459
|
-
throw new Error(`Server does not support tools (required for ${method})`);
|
|
460
|
-
}
|
|
461
|
-
break;
|
|
462
|
-
case "completion/complete":
|
|
463
|
-
if (!((_e = this._serverCapabilities) === null || _e === void 0 ? void 0 : _e.prompts)) {
|
|
464
|
-
throw new Error(`Server does not support prompts (required for ${method})`);
|
|
465
|
-
}
|
|
466
|
-
break;
|
|
467
|
-
case "initialize":
|
|
468
|
-
break;
|
|
469
|
-
case "ping":
|
|
470
|
-
break;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
assertNotificationCapability(method) {
|
|
474
|
-
var _a;
|
|
475
|
-
switch (method) {
|
|
476
|
-
case "notifications/roots/list_changed":
|
|
477
|
-
if (!((_a = this._capabilities.roots) === null || _a === void 0 ? void 0 : _a.listChanged)) {
|
|
478
|
-
throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
|
|
479
|
-
}
|
|
480
|
-
break;
|
|
481
|
-
case "notifications/initialized":
|
|
482
|
-
break;
|
|
483
|
-
case "notifications/cancelled":
|
|
484
|
-
break;
|
|
485
|
-
case "notifications/progress":
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
assertRequestHandlerCapability(method) {
|
|
490
|
-
switch (method) {
|
|
491
|
-
case "sampling/createMessage":
|
|
492
|
-
if (!this._capabilities.sampling) {
|
|
493
|
-
throw new Error(`Client does not support sampling capability (required for ${method})`);
|
|
494
|
-
}
|
|
495
|
-
break;
|
|
496
|
-
case "roots/list":
|
|
497
|
-
if (!this._capabilities.roots) {
|
|
498
|
-
throw new Error(`Client does not support roots capability (required for ${method})`);
|
|
499
|
-
}
|
|
500
|
-
break;
|
|
501
|
-
case "ping":
|
|
502
|
-
break;
|
|
84
|
+
this.connectionState = "failed";
|
|
85
|
+
throw e;
|
|
503
86
|
}
|
|
504
|
-
|
|
505
|
-
async ping(options) {
|
|
506
|
-
return this.request({ method: "ping" }, EmptyResultSchema, options);
|
|
507
|
-
}
|
|
508
|
-
async complete(params, options) {
|
|
509
|
-
return this.request({ method: "completion/complete", params }, CompleteResultSchema, options);
|
|
510
|
-
}
|
|
511
|
-
async setLoggingLevel(level, options) {
|
|
512
|
-
return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema, options);
|
|
513
|
-
}
|
|
514
|
-
async getPrompt(params, options) {
|
|
515
|
-
return this.request({ method: "prompts/get", params }, GetPromptResultSchema, options);
|
|
516
|
-
}
|
|
517
|
-
async listPrompts(params, options) {
|
|
518
|
-
return this.request({ method: "prompts/list", params }, ListPromptsResultSchema, options);
|
|
519
|
-
}
|
|
520
|
-
async listResources(params, options) {
|
|
521
|
-
return this.request({ method: "resources/list", params }, ListResourcesResultSchema, options);
|
|
522
|
-
}
|
|
523
|
-
async listResourceTemplates(params, options) {
|
|
524
|
-
return this.request({ method: "resources/templates/list", params }, ListResourceTemplatesResultSchema, options);
|
|
525
|
-
}
|
|
526
|
-
async readResource(params, options) {
|
|
527
|
-
return this.request({ method: "resources/read", params }, ReadResourceResultSchema, options);
|
|
528
|
-
}
|
|
529
|
-
async subscribeResource(params, options) {
|
|
530
|
-
return this.request({ method: "resources/subscribe", params }, EmptyResultSchema, options);
|
|
531
|
-
}
|
|
532
|
-
async unsubscribeResource(params, options) {
|
|
533
|
-
return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema, options);
|
|
534
|
-
}
|
|
535
|
-
async callTool(params, resultSchema = CallToolResultSchema, options) {
|
|
536
|
-
return this.request({ method: "tools/call", params }, resultSchema, options);
|
|
537
|
-
}
|
|
538
|
-
async listTools(params, options) {
|
|
539
|
-
return this.request({ method: "tools/list", params }, ListToolsResultSchema, options);
|
|
540
|
-
}
|
|
541
|
-
async sendRootsListChanged() {
|
|
542
|
-
return this.notification({ method: "notifications/roots/list_changed" });
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
// src/mcp/client-connection.ts
|
|
547
|
-
var MCPClientConnection = class {
|
|
548
|
-
constructor(url, info, opts = { transport: {}, client: {}, capabilities: {} }) {
|
|
549
|
-
this.info = info;
|
|
550
|
-
this.transport = new SSEEdgeClientTransport(url, opts.transport);
|
|
551
|
-
this.client = new Client(info, opts.client);
|
|
552
|
-
this.client.registerCapabilities(opts.capabilities);
|
|
553
|
-
this.connected = false;
|
|
554
|
-
this.tools = [];
|
|
555
|
-
this.prompts = [];
|
|
556
|
-
this.resources = [];
|
|
557
|
-
this.resourceTemplates = [];
|
|
558
|
-
}
|
|
559
|
-
client;
|
|
560
|
-
transport;
|
|
561
|
-
connected;
|
|
562
|
-
instructions;
|
|
563
|
-
tools;
|
|
564
|
-
prompts;
|
|
565
|
-
resources;
|
|
566
|
-
resourceTemplates;
|
|
567
|
-
serverCapabilities;
|
|
568
|
-
async init() {
|
|
569
|
-
await this.client.connect(this.transport);
|
|
87
|
+
this.connectionState = "discovering";
|
|
570
88
|
this.serverCapabilities = await this.client.getServerCapabilities();
|
|
571
89
|
if (!this.serverCapabilities) {
|
|
572
|
-
throw new Error(
|
|
573
|
-
`The MCP Server ${this.info.name} failed to return server capabilities`
|
|
574
|
-
);
|
|
90
|
+
throw new Error("The MCP Server failed to return server capabilities");
|
|
575
91
|
}
|
|
576
92
|
const [instructions, tools, resources, prompts, resourceTemplates] = await Promise.all([
|
|
577
93
|
this.client.getInstructions(),
|
|
@@ -585,6 +101,7 @@ var MCPClientConnection = class {
|
|
|
585
101
|
this.resources = resources;
|
|
586
102
|
this.prompts = prompts;
|
|
587
103
|
this.resourceTemplates = resourceTemplates;
|
|
104
|
+
this.connectionState = "ready";
|
|
588
105
|
}
|
|
589
106
|
/**
|
|
590
107
|
* Notification handler registration
|
|
@@ -643,7 +160,7 @@ var MCPClientConnection = class {
|
|
|
643
160
|
do {
|
|
644
161
|
toolsResult = await this.client.listTools({
|
|
645
162
|
cursor: toolsResult.nextCursor
|
|
646
|
-
});
|
|
163
|
+
}).catch(capabilityErrorHandler({ tools: [] }, "tools/list"));
|
|
647
164
|
toolsAgg = toolsAgg.concat(toolsResult.tools);
|
|
648
165
|
} while (toolsResult.nextCursor);
|
|
649
166
|
return toolsAgg;
|
|
@@ -654,7 +171,7 @@ var MCPClientConnection = class {
|
|
|
654
171
|
do {
|
|
655
172
|
resourcesResult = await this.client.listResources({
|
|
656
173
|
cursor: resourcesResult.nextCursor
|
|
657
|
-
});
|
|
174
|
+
}).catch(capabilityErrorHandler({ resources: [] }, "resources/list"));
|
|
658
175
|
resourcesAgg = resourcesAgg.concat(resourcesResult.resources);
|
|
659
176
|
} while (resourcesResult.nextCursor);
|
|
660
177
|
return resourcesAgg;
|
|
@@ -665,7 +182,7 @@ var MCPClientConnection = class {
|
|
|
665
182
|
do {
|
|
666
183
|
promptsResult = await this.client.listPrompts({
|
|
667
184
|
cursor: promptsResult.nextCursor
|
|
668
|
-
});
|
|
185
|
+
}).catch(capabilityErrorHandler({ prompts: [] }, "prompts/list"));
|
|
669
186
|
promptsAgg = promptsAgg.concat(promptsResult.prompts);
|
|
670
187
|
} while (promptsResult.nextCursor);
|
|
671
188
|
return promptsAgg;
|
|
@@ -678,16 +195,42 @@ var MCPClientConnection = class {
|
|
|
678
195
|
do {
|
|
679
196
|
templatesResult = await this.client.listResourceTemplates({
|
|
680
197
|
cursor: templatesResult.nextCursor
|
|
681
|
-
})
|
|
198
|
+
}).catch(
|
|
199
|
+
capabilityErrorHandler(
|
|
200
|
+
{ resourceTemplates: [] },
|
|
201
|
+
"resources/templates/list"
|
|
202
|
+
)
|
|
203
|
+
);
|
|
682
204
|
templatesAgg = templatesAgg.concat(templatesResult.resourceTemplates);
|
|
683
205
|
} while (templatesResult.nextCursor);
|
|
684
206
|
return templatesAgg;
|
|
685
207
|
}
|
|
686
208
|
};
|
|
209
|
+
function capabilityErrorHandler(empty, method) {
|
|
210
|
+
return (e) => {
|
|
211
|
+
if (e.code === -32601) {
|
|
212
|
+
console.error(
|
|
213
|
+
`The server advertised support for the capability ${method.split("/")[0]}, but returned "Method not found" for '${method}'.`
|
|
214
|
+
);
|
|
215
|
+
return empty;
|
|
216
|
+
}
|
|
217
|
+
throw e;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
687
220
|
|
|
688
221
|
// src/mcp/client.ts
|
|
689
222
|
var MCPClientManager = class {
|
|
690
|
-
|
|
223
|
+
/**
|
|
224
|
+
* @param name Name of the MCP client
|
|
225
|
+
* @param version Version of the MCP Client
|
|
226
|
+
* @param auth Auth paramters if being used to create a DurableObjectOAuthClientProvider
|
|
227
|
+
*/
|
|
228
|
+
constructor(name, version) {
|
|
229
|
+
this.name = name;
|
|
230
|
+
this.version = version;
|
|
231
|
+
this.mcpConnections = {};
|
|
232
|
+
this.callbackUrls = [];
|
|
233
|
+
}
|
|
691
234
|
/**
|
|
692
235
|
* Connect to and register an MCP server
|
|
693
236
|
*
|
|
@@ -695,14 +238,96 @@ var MCPClientManager = class {
|
|
|
695
238
|
* @param clientConfig Client config
|
|
696
239
|
* @param capabilities Client capabilities (i.e. if the client supports roots/sampling)
|
|
697
240
|
*/
|
|
698
|
-
async
|
|
699
|
-
|
|
241
|
+
async connect(url, options = {}) {
|
|
242
|
+
const id = options.reconnect?.id ?? crypto.randomUUID();
|
|
243
|
+
if (!options.transport?.authProvider) {
|
|
244
|
+
console.warn(
|
|
245
|
+
"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers"
|
|
246
|
+
);
|
|
247
|
+
} else {
|
|
248
|
+
options.transport.authProvider.serverId = id;
|
|
249
|
+
}
|
|
250
|
+
this.mcpConnections[id] = new MCPClientConnection(
|
|
251
|
+
new URL(url),
|
|
252
|
+
{
|
|
253
|
+
name: this.name,
|
|
254
|
+
version: this.version
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
transport: options.transport ?? {},
|
|
258
|
+
client: options.client ?? {},
|
|
259
|
+
capabilities: options.client ?? {}
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
await this.mcpConnections[id].init(
|
|
263
|
+
options.reconnect?.oauthCode,
|
|
264
|
+
options.reconnect?.oauthClientId
|
|
265
|
+
);
|
|
266
|
+
const authUrl = options.transport?.authProvider?.authUrl;
|
|
267
|
+
if (authUrl && options.transport?.authProvider?.redirectUrl) {
|
|
268
|
+
this.callbackUrls.push(
|
|
269
|
+
options.transport.authProvider.redirectUrl.toString()
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
id,
|
|
274
|
+
authUrl
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
isCallbackRequest(req) {
|
|
278
|
+
return req.method === "GET" && !!this.callbackUrls.find((url) => {
|
|
279
|
+
return req.url.startsWith(url);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
async handleCallbackRequest(req) {
|
|
283
|
+
const url = new URL(req.url);
|
|
284
|
+
const urlMatch = this.callbackUrls.find((url2) => {
|
|
285
|
+
return req.url.startsWith(url2);
|
|
286
|
+
});
|
|
287
|
+
if (!urlMatch) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`No callback URI match found for the request url: ${req.url}. Was the request matched with \`isCallbackRequest()\`?`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
const code = url.searchParams.get("code");
|
|
293
|
+
const clientId = url.searchParams.get("state");
|
|
294
|
+
const urlParams = urlMatch.split("/");
|
|
295
|
+
const serverId = urlParams[urlParams.length - 1];
|
|
296
|
+
if (!code) {
|
|
297
|
+
throw new Error("Unauthorized: no code provided");
|
|
298
|
+
}
|
|
299
|
+
if (!clientId) {
|
|
300
|
+
throw new Error("Unauthorized: no state provided");
|
|
301
|
+
}
|
|
302
|
+
if (this.mcpConnections[serverId] === void 0) {
|
|
303
|
+
throw new Error(`Could not find serverId: ${serverId}`);
|
|
304
|
+
}
|
|
305
|
+
if (this.mcpConnections[serverId].connectionState !== "authenticating") {
|
|
700
306
|
throw new Error(
|
|
701
|
-
|
|
307
|
+
"Failed to authenticate: the client isn't in the `authenticating` state"
|
|
702
308
|
);
|
|
703
309
|
}
|
|
704
|
-
this.mcpConnections[
|
|
705
|
-
|
|
310
|
+
const conn = this.mcpConnections[serverId];
|
|
311
|
+
if (!conn.options.transport.authProvider) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
"Trying to finalize authentication for a server connection without an authProvider"
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
conn.options.transport.authProvider.clientId = clientId;
|
|
317
|
+
conn.options.transport.authProvider.serverId = serverId;
|
|
318
|
+
const serverUrl = conn.url.toString();
|
|
319
|
+
await this.connect(serverUrl, {
|
|
320
|
+
reconnect: {
|
|
321
|
+
id: serverId,
|
|
322
|
+
oauthClientId: clientId,
|
|
323
|
+
oauthCode: code
|
|
324
|
+
},
|
|
325
|
+
...conn.options
|
|
326
|
+
});
|
|
327
|
+
if (this.mcpConnections[serverId].connectionState === "authenticating") {
|
|
328
|
+
throw new Error("Failed to authenticate: client failed to initialize");
|
|
329
|
+
}
|
|
330
|
+
return { serverId };
|
|
706
331
|
}
|
|
707
332
|
/**
|
|
708
333
|
* @returns namespaced list of tools
|
|
@@ -732,8 +357,8 @@ var MCPClientManager = class {
|
|
|
732
357
|
* Namespaced version of callTool
|
|
733
358
|
*/
|
|
734
359
|
callTool(params, resultSchema, options) {
|
|
735
|
-
const unqualifiedName = params.name.replace(`${params.
|
|
736
|
-
return this.mcpConnections[params.
|
|
360
|
+
const unqualifiedName = params.name.replace(`${params.serverId}.`, "");
|
|
361
|
+
return this.mcpConnections[params.serverId].client.callTool(
|
|
737
362
|
{
|
|
738
363
|
...params,
|
|
739
364
|
name: unqualifiedName
|
|
@@ -746,7 +371,7 @@ var MCPClientManager = class {
|
|
|
746
371
|
* Namespaced version of readResource
|
|
747
372
|
*/
|
|
748
373
|
readResource(params, options) {
|
|
749
|
-
return this.mcpConnections[params.
|
|
374
|
+
return this.mcpConnections[params.serverId].client.readResource(
|
|
750
375
|
params,
|
|
751
376
|
options
|
|
752
377
|
);
|
|
@@ -755,7 +380,7 @@ var MCPClientManager = class {
|
|
|
755
380
|
* Namespaced version of getPrompt
|
|
756
381
|
*/
|
|
757
382
|
getPrompt(params, options) {
|
|
758
|
-
return this.mcpConnections[params.
|
|
383
|
+
return this.mcpConnections[params.serverId].client.getPrompt(
|
|
759
384
|
params,
|
|
760
385
|
options
|
|
761
386
|
);
|
|
@@ -765,15 +390,12 @@ function getNamespacedData(mcpClients, type) {
|
|
|
765
390
|
const sets = Object.entries(mcpClients).map(([name, conn]) => {
|
|
766
391
|
return { name, data: conn[type] };
|
|
767
392
|
});
|
|
768
|
-
const namespacedData = sets.flatMap(({ name:
|
|
393
|
+
const namespacedData = sets.flatMap(({ name: serverId, data }) => {
|
|
769
394
|
return data.map((item) => {
|
|
770
395
|
return {
|
|
771
396
|
...item,
|
|
772
|
-
// we add a
|
|
773
|
-
|
|
774
|
-
serverName: `${serverName}`,
|
|
775
|
-
// qualified name
|
|
776
|
-
name: `${serverName}.${item.name}`
|
|
397
|
+
// we add a serverId so we can easily pull it out and send the tool call to the right server
|
|
398
|
+
serverId
|
|
777
399
|
};
|
|
778
400
|
});
|
|
779
401
|
});
|