agents 0.0.0-ecf8926 → 0.0.0-ed3f94d
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 +126 -4
- package/dist/_esm-LV5FJ3HK.js +3922 -0
- package/dist/_esm-LV5FJ3HK.js.map +1 -0
- package/dist/ai-chat-agent.d.ts +2 -1
- package/dist/ai-chat-agent.js +391 -76
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.js +1 -0
- package/dist/ai-react.d.ts +8 -1
- package/dist/ai-react.js +157 -111
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +1 -0
- package/dist/ai-types.js +2 -1
- package/dist/ccip-CMBYN64O.js +15 -0
- package/dist/ccip-CMBYN64O.js.map +1 -0
- package/dist/{chunk-EGCWEPQL.js → chunk-254F4GDT.js} +151 -98
- package/dist/chunk-254F4GDT.js.map +1 -0
- package/dist/{chunk-DS7BJNPH.js → chunk-3OT2NNEW.js} +411 -68
- package/dist/chunk-3OT2NNEW.js.map +1 -0
- package/dist/chunk-5Y6BEZDY.js +276 -0
- package/dist/chunk-5Y6BEZDY.js.map +1 -0
- package/dist/{chunk-AVYJQSLW.js → chunk-BER7KXUJ.js} +2 -1
- package/dist/chunk-BER7KXUJ.js.map +1 -0
- package/dist/chunk-JJBFIGUC.js +5202 -0
- package/dist/chunk-JJBFIGUC.js.map +1 -0
- package/dist/chunk-PR4QN5HX.js +43 -0
- package/dist/chunk-PR4QN5HX.js.map +1 -0
- package/dist/chunk-TYAY6AU6.js +159 -0
- package/dist/chunk-TYAY6AU6.js.map +1 -0
- package/dist/{chunk-PVQZBKN7.js → chunk-Z44WASMA.js} +11 -3
- package/dist/chunk-Z44WASMA.js.map +1 -0
- package/dist/{client-BAqDHqAV.d.ts → client-DVoPb3-C.d.ts} +549 -30
- package/dist/client.js +2 -1
- package/dist/codemode/ai.d.ts +25 -0
- package/dist/codemode/ai.js +5112 -0
- package/dist/codemode/ai.js.map +1 -0
- package/dist/index.d.ts +44 -35
- package/dist/index.js +7 -4
- package/dist/mcp/client.d.ts +2 -1
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -0
- package/dist/mcp/do-oauth-client-provider.js +2 -1
- package/dist/mcp/index.d.ts +50 -83
- package/dist/mcp/index.js +903 -760
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +39 -0
- package/dist/mcp/x402.js +3195 -0
- package/dist/mcp/x402.js.map +1 -0
- package/dist/mcp-BH1fJeiU.d.ts +58 -0
- package/dist/observability/index.d.ts +12 -24
- package/dist/observability/index.js +5 -4
- package/dist/react.d.ts +10 -6
- package/dist/react.js +101 -3
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +76 -2
- package/dist/schedule.js +17 -2
- package/dist/schedule.js.map +1 -1
- package/dist/secp256k1-M22GZP2U.js +2193 -0
- package/dist/secp256k1-M22GZP2U.js.map +1 -0
- package/package.json +22 -7
- package/src/index.ts +226 -116
- package/dist/chunk-AVYJQSLW.js.map +0 -1
- package/dist/chunk-DS7BJNPH.js.map +0 -1
- package/dist/chunk-EGCWEPQL.js.map +0 -1
- package/dist/chunk-PVQZBKN7.js.map +0 -1
|
@@ -1,15 +1,72 @@
|
|
|
1
1
|
// src/mcp/client.ts
|
|
2
2
|
import { jsonSchema } from "ai";
|
|
3
|
-
import { nanoid } from "nanoid";
|
|
3
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
4
|
+
|
|
5
|
+
// src/core/events.ts
|
|
6
|
+
function toDisposable(fn) {
|
|
7
|
+
return { dispose: fn };
|
|
8
|
+
}
|
|
9
|
+
var DisposableStore = class {
|
|
10
|
+
constructor() {
|
|
11
|
+
this._items = [];
|
|
12
|
+
}
|
|
13
|
+
add(d) {
|
|
14
|
+
this._items.push(d);
|
|
15
|
+
return d;
|
|
16
|
+
}
|
|
17
|
+
dispose() {
|
|
18
|
+
while (this._items.length) {
|
|
19
|
+
try {
|
|
20
|
+
this._items.pop().dispose();
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var Emitter = class {
|
|
27
|
+
constructor() {
|
|
28
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
29
|
+
this.event = (listener) => {
|
|
30
|
+
this._listeners.add(listener);
|
|
31
|
+
return toDisposable(() => this._listeners.delete(listener));
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
fire(data) {
|
|
35
|
+
for (const listener of [...this._listeners]) {
|
|
36
|
+
try {
|
|
37
|
+
listener(data);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
console.error("Emitter listener error:", err);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
dispose() {
|
|
44
|
+
this._listeners.clear();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
4
47
|
|
|
5
48
|
// src/mcp/client-connection.ts
|
|
6
49
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7
50
|
import {
|
|
51
|
+
ElicitRequestSchema,
|
|
8
52
|
PromptListChangedNotificationSchema,
|
|
9
53
|
ResourceListChangedNotificationSchema,
|
|
10
|
-
ToolListChangedNotificationSchema
|
|
11
|
-
ElicitRequestSchema
|
|
54
|
+
ToolListChangedNotificationSchema
|
|
12
55
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
56
|
+
import { nanoid } from "nanoid";
|
|
57
|
+
|
|
58
|
+
// src/mcp/errors.ts
|
|
59
|
+
function toErrorMessage(error) {
|
|
60
|
+
return error instanceof Error ? error.message : String(error);
|
|
61
|
+
}
|
|
62
|
+
function isUnauthorized(error) {
|
|
63
|
+
const msg = toErrorMessage(error);
|
|
64
|
+
return msg.includes("Unauthorized") || msg.includes("401");
|
|
65
|
+
}
|
|
66
|
+
function isTransportNotImplemented(error) {
|
|
67
|
+
const msg = toErrorMessage(error);
|
|
68
|
+
return msg.includes("404") || msg.includes("405") || msg.includes("Not Implemented") || msg.includes("not implemented");
|
|
69
|
+
}
|
|
13
70
|
|
|
14
71
|
// src/mcp/sse-edge.ts
|
|
15
72
|
import {
|
|
@@ -118,6 +175,8 @@ var MCPClientConnection = class {
|
|
|
118
175
|
this.prompts = [];
|
|
119
176
|
this.resources = [];
|
|
120
177
|
this.resourceTemplates = [];
|
|
178
|
+
this._onObservabilityEvent = new Emitter();
|
|
179
|
+
this.onObservabilityEvent = this._onObservabilityEvent.event;
|
|
121
180
|
const clientOptions = {
|
|
122
181
|
...options.client,
|
|
123
182
|
capabilities: {
|
|
@@ -130,23 +189,112 @@ var MCPClientConnection = class {
|
|
|
130
189
|
/**
|
|
131
190
|
* Initialize a client connection
|
|
132
191
|
*
|
|
133
|
-
* @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized
|
|
134
192
|
* @returns
|
|
135
193
|
*/
|
|
136
|
-
async init(
|
|
194
|
+
async init() {
|
|
195
|
+
const transportType = this.options.transport.type;
|
|
196
|
+
if (!transportType) {
|
|
197
|
+
throw new Error("Transport type must be specified");
|
|
198
|
+
}
|
|
137
199
|
try {
|
|
138
|
-
|
|
139
|
-
await this.tryConnect(transportType, code);
|
|
200
|
+
await this.tryConnect(transportType);
|
|
140
201
|
} catch (e) {
|
|
141
|
-
if (e
|
|
202
|
+
if (isUnauthorized(e)) {
|
|
142
203
|
this.connectionState = "authenticating";
|
|
143
204
|
return;
|
|
144
205
|
}
|
|
206
|
+
this._onObservabilityEvent.fire({
|
|
207
|
+
type: "mcp:client:connect",
|
|
208
|
+
displayMessage: `Connection initialization failed for ${this.url.toString()}`,
|
|
209
|
+
payload: {
|
|
210
|
+
url: this.url.toString(),
|
|
211
|
+
transport: transportType,
|
|
212
|
+
state: this.connectionState,
|
|
213
|
+
error: toErrorMessage(e)
|
|
214
|
+
},
|
|
215
|
+
timestamp: Date.now(),
|
|
216
|
+
id: nanoid()
|
|
217
|
+
});
|
|
145
218
|
this.connectionState = "failed";
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
await this.discoverAndRegister();
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Finish OAuth by probing transports based on configured type.
|
|
225
|
+
* - Explicit: finish on that transport
|
|
226
|
+
* - Auto: try streamable-http, then sse on 404/405/Not Implemented
|
|
227
|
+
*/
|
|
228
|
+
async finishAuthProbe(code) {
|
|
229
|
+
if (!this.options.transport.authProvider) {
|
|
230
|
+
throw new Error("No auth provider configured");
|
|
231
|
+
}
|
|
232
|
+
const configuredType = this.options.transport.type;
|
|
233
|
+
if (!configuredType) {
|
|
234
|
+
throw new Error("Transport type must be specified");
|
|
235
|
+
}
|
|
236
|
+
const finishAuth = async (base) => {
|
|
237
|
+
const transport = this.getTransport(base);
|
|
238
|
+
await transport.finishAuth(code);
|
|
239
|
+
};
|
|
240
|
+
if (configuredType === "sse" || configuredType === "streamable-http") {
|
|
241
|
+
await finishAuth(configuredType);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
await finishAuth("streamable-http");
|
|
246
|
+
} catch (e) {
|
|
247
|
+
if (isTransportNotImplemented(e)) {
|
|
248
|
+
await finishAuth("sse");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
146
251
|
throw e;
|
|
147
252
|
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Complete OAuth authorization
|
|
256
|
+
*/
|
|
257
|
+
async completeAuthorization(code) {
|
|
258
|
+
if (this.connectionState !== "authenticating") {
|
|
259
|
+
throw new Error(
|
|
260
|
+
"Connection must be in authenticating state to complete authorization"
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
await this.finishAuthProbe(code);
|
|
265
|
+
this.connectionState = "connecting";
|
|
266
|
+
} catch (error) {
|
|
267
|
+
this.connectionState = "failed";
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Establish connection after successful authorization
|
|
273
|
+
*/
|
|
274
|
+
async establishConnection() {
|
|
275
|
+
if (this.connectionState !== "connecting") {
|
|
276
|
+
throw new Error(
|
|
277
|
+
"Connection must be in connecting state to establish connection"
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
const transportType = this.options.transport.type;
|
|
282
|
+
if (!transportType) {
|
|
283
|
+
throw new Error("Transport type must be specified");
|
|
284
|
+
}
|
|
285
|
+
await this.tryConnect(transportType);
|
|
286
|
+
await this.discoverAndRegister();
|
|
287
|
+
} catch (error) {
|
|
288
|
+
this.connectionState = "failed";
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Discover server capabilities and register tools, resources, prompts, and templates
|
|
294
|
+
*/
|
|
295
|
+
async discoverAndRegister() {
|
|
148
296
|
this.connectionState = "discovering";
|
|
149
|
-
this.serverCapabilities =
|
|
297
|
+
this.serverCapabilities = this.client.getServerCapabilities();
|
|
150
298
|
if (!this.serverCapabilities) {
|
|
151
299
|
throw new Error("The MCP Server failed to return server capabilities");
|
|
152
300
|
}
|
|
@@ -172,7 +320,18 @@ var MCPClientConnection = class {
|
|
|
172
320
|
];
|
|
173
321
|
for (const { name, result } of operations) {
|
|
174
322
|
if (result.status === "rejected") {
|
|
175
|
-
|
|
323
|
+
const url = this.url.toString();
|
|
324
|
+
this._onObservabilityEvent.fire({
|
|
325
|
+
type: "mcp:client:discover",
|
|
326
|
+
displayMessage: `Failed to discover ${name} for ${url}`,
|
|
327
|
+
payload: {
|
|
328
|
+
url,
|
|
329
|
+
capability: name,
|
|
330
|
+
error: result.reason
|
|
331
|
+
},
|
|
332
|
+
timestamp: Date.now(),
|
|
333
|
+
id: nanoid()
|
|
334
|
+
});
|
|
176
335
|
}
|
|
177
336
|
}
|
|
178
337
|
this.instructions = instructionsResult.status === "fulfilled" ? instructionsResult.value : void 0;
|
|
@@ -239,7 +398,7 @@ var MCPClientConnection = class {
|
|
|
239
398
|
do {
|
|
240
399
|
toolsResult = await this.client.listTools({
|
|
241
400
|
cursor: toolsResult.nextCursor
|
|
242
|
-
}).catch(
|
|
401
|
+
}).catch(this._capabilityErrorHandler({ tools: [] }, "tools/list"));
|
|
243
402
|
toolsAgg = toolsAgg.concat(toolsResult.tools);
|
|
244
403
|
} while (toolsResult.nextCursor);
|
|
245
404
|
return toolsAgg;
|
|
@@ -250,7 +409,9 @@ var MCPClientConnection = class {
|
|
|
250
409
|
do {
|
|
251
410
|
resourcesResult = await this.client.listResources({
|
|
252
411
|
cursor: resourcesResult.nextCursor
|
|
253
|
-
}).catch(
|
|
412
|
+
}).catch(
|
|
413
|
+
this._capabilityErrorHandler({ resources: [] }, "resources/list")
|
|
414
|
+
);
|
|
254
415
|
resourcesAgg = resourcesAgg.concat(resourcesResult.resources);
|
|
255
416
|
} while (resourcesResult.nextCursor);
|
|
256
417
|
return resourcesAgg;
|
|
@@ -261,7 +422,7 @@ var MCPClientConnection = class {
|
|
|
261
422
|
do {
|
|
262
423
|
promptsResult = await this.client.listPrompts({
|
|
263
424
|
cursor: promptsResult.nextCursor
|
|
264
|
-
}).catch(
|
|
425
|
+
}).catch(this._capabilityErrorHandler({ prompts: [] }, "prompts/list"));
|
|
265
426
|
promptsAgg = promptsAgg.concat(promptsResult.prompts);
|
|
266
427
|
} while (promptsResult.nextCursor);
|
|
267
428
|
return promptsAgg;
|
|
@@ -275,7 +436,7 @@ var MCPClientConnection = class {
|
|
|
275
436
|
templatesResult = await this.client.listResourceTemplates({
|
|
276
437
|
cursor: templatesResult.nextCursor
|
|
277
438
|
}).catch(
|
|
278
|
-
|
|
439
|
+
this._capabilityErrorHandler(
|
|
279
440
|
{ resourceTemplates: [] },
|
|
280
441
|
"resources/templates/list"
|
|
281
442
|
)
|
|
@@ -314,21 +475,46 @@ var MCPClientConnection = class {
|
|
|
314
475
|
throw new Error(`Unsupported transport type: ${transportType}`);
|
|
315
476
|
}
|
|
316
477
|
}
|
|
317
|
-
async tryConnect(transportType
|
|
478
|
+
async tryConnect(transportType) {
|
|
318
479
|
const transports = transportType === "auto" ? ["streamable-http", "sse"] : [transportType];
|
|
319
480
|
for (const currentTransportType of transports) {
|
|
320
481
|
const isLastTransport = currentTransportType === transports[transports.length - 1];
|
|
321
482
|
const hasFallback = transportType === "auto" && currentTransportType === "streamable-http" && !isLastTransport;
|
|
322
|
-
const transport =
|
|
323
|
-
if (code) {
|
|
324
|
-
await transport.finishAuth(code);
|
|
325
|
-
}
|
|
483
|
+
const transport = this.getTransport(currentTransportType);
|
|
326
484
|
try {
|
|
327
485
|
await this.client.connect(transport);
|
|
486
|
+
this.lastConnectedTransport = currentTransportType;
|
|
487
|
+
const url = this.url.toString();
|
|
488
|
+
this._onObservabilityEvent.fire({
|
|
489
|
+
type: "mcp:client:connect",
|
|
490
|
+
displayMessage: `Connected successfully using ${currentTransportType} transport for ${url}`,
|
|
491
|
+
payload: {
|
|
492
|
+
url,
|
|
493
|
+
transport: currentTransportType,
|
|
494
|
+
state: this.connectionState
|
|
495
|
+
},
|
|
496
|
+
timestamp: Date.now(),
|
|
497
|
+
id: nanoid()
|
|
498
|
+
});
|
|
328
499
|
break;
|
|
329
500
|
} catch (e) {
|
|
330
501
|
const error = e instanceof Error ? e : new Error(String(e));
|
|
331
|
-
if (
|
|
502
|
+
if (isUnauthorized(error)) {
|
|
503
|
+
throw e;
|
|
504
|
+
}
|
|
505
|
+
if (hasFallback && isTransportNotImplemented(error)) {
|
|
506
|
+
const url = this.url.toString();
|
|
507
|
+
this._onObservabilityEvent.fire({
|
|
508
|
+
type: "mcp:client:connect",
|
|
509
|
+
displayMessage: `${currentTransportType} transport not available, trying ${transports[transports.indexOf(currentTransportType) + 1]} for ${url}`,
|
|
510
|
+
payload: {
|
|
511
|
+
url,
|
|
512
|
+
transport: currentTransportType,
|
|
513
|
+
state: this.connectionState
|
|
514
|
+
},
|
|
515
|
+
timestamp: Date.now(),
|
|
516
|
+
id: nanoid()
|
|
517
|
+
});
|
|
332
518
|
continue;
|
|
333
519
|
}
|
|
334
520
|
throw e;
|
|
@@ -341,18 +527,27 @@ var MCPClientConnection = class {
|
|
|
341
527
|
}
|
|
342
528
|
);
|
|
343
529
|
}
|
|
530
|
+
_capabilityErrorHandler(empty, method) {
|
|
531
|
+
return (e) => {
|
|
532
|
+
if (e.code === -32601) {
|
|
533
|
+
const url = this.url.toString();
|
|
534
|
+
this._onObservabilityEvent.fire({
|
|
535
|
+
type: "mcp:client:discover",
|
|
536
|
+
displayMessage: `The server advertised support for the capability ${method.split("/")[0]}, but returned "Method not found" for '${method}' for ${url}`,
|
|
537
|
+
payload: {
|
|
538
|
+
url,
|
|
539
|
+
capability: method.split("/")[0],
|
|
540
|
+
error: toErrorMessage(e)
|
|
541
|
+
},
|
|
542
|
+
timestamp: Date.now(),
|
|
543
|
+
id: nanoid()
|
|
544
|
+
});
|
|
545
|
+
return empty;
|
|
546
|
+
}
|
|
547
|
+
throw e;
|
|
548
|
+
};
|
|
549
|
+
}
|
|
344
550
|
};
|
|
345
|
-
function capabilityErrorHandler(empty, method) {
|
|
346
|
-
return (e) => {
|
|
347
|
-
if (e.code === -32601) {
|
|
348
|
-
console.error(
|
|
349
|
-
`The server advertised support for the capability ${method.split("/")[0]}, but returned "Method not found" for '${method}'.`
|
|
350
|
-
);
|
|
351
|
-
return empty;
|
|
352
|
-
}
|
|
353
|
-
throw e;
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
551
|
|
|
357
552
|
// src/mcp/client.ts
|
|
358
553
|
var MCPClientManager = class {
|
|
@@ -366,6 +561,12 @@ var MCPClientManager = class {
|
|
|
366
561
|
this._version = _version;
|
|
367
562
|
this.mcpConnections = {};
|
|
368
563
|
this._callbackUrls = [];
|
|
564
|
+
this._didWarnAboutUnstableGetAITools = false;
|
|
565
|
+
this._connectionDisposables = /* @__PURE__ */ new Map();
|
|
566
|
+
this._onObservabilityEvent = new Emitter();
|
|
567
|
+
this.onObservabilityEvent = this._onObservabilityEvent.event;
|
|
568
|
+
this._onConnected = new Emitter();
|
|
569
|
+
this.onConnected = this._onConnected.event;
|
|
369
570
|
}
|
|
370
571
|
/**
|
|
371
572
|
* Connect to and register an MCP server
|
|
@@ -375,31 +576,64 @@ var MCPClientManager = class {
|
|
|
375
576
|
* @param capabilities Client capabilities (i.e. if the client supports roots/sampling)
|
|
376
577
|
*/
|
|
377
578
|
async connect(url, options = {}) {
|
|
378
|
-
const id = options.reconnect?.id ??
|
|
379
|
-
if (
|
|
380
|
-
console.warn(
|
|
381
|
-
"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers"
|
|
382
|
-
);
|
|
383
|
-
} else {
|
|
579
|
+
const id = options.reconnect?.id ?? nanoid2(8);
|
|
580
|
+
if (options.transport?.authProvider) {
|
|
384
581
|
options.transport.authProvider.serverId = id;
|
|
385
582
|
if (options.reconnect?.oauthClientId) {
|
|
386
583
|
options.transport.authProvider.clientId = options.reconnect?.oauthClientId;
|
|
387
584
|
}
|
|
388
585
|
}
|
|
389
|
-
this.mcpConnections[id]
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
586
|
+
if (!options.reconnect?.oauthCode || !this.mcpConnections[id]) {
|
|
587
|
+
const normalizedTransport = {
|
|
588
|
+
...options.transport,
|
|
589
|
+
type: options.transport?.type ?? "auto"
|
|
590
|
+
};
|
|
591
|
+
this.mcpConnections[id] = new MCPClientConnection(
|
|
592
|
+
new URL(url),
|
|
593
|
+
{
|
|
594
|
+
name: this._name,
|
|
595
|
+
version: this._version
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
client: options.client ?? {},
|
|
599
|
+
transport: normalizedTransport
|
|
600
|
+
}
|
|
601
|
+
);
|
|
602
|
+
const store = new DisposableStore();
|
|
603
|
+
const existing = this._connectionDisposables.get(id);
|
|
604
|
+
if (existing) existing.dispose();
|
|
605
|
+
this._connectionDisposables.set(id, store);
|
|
606
|
+
store.add(
|
|
607
|
+
this.mcpConnections[id].onObservabilityEvent((event) => {
|
|
608
|
+
this._onObservabilityEvent.fire(event);
|
|
609
|
+
})
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
await this.mcpConnections[id].init();
|
|
613
|
+
if (options.reconnect?.oauthCode) {
|
|
614
|
+
try {
|
|
615
|
+
await this.mcpConnections[id].completeAuthorization(
|
|
616
|
+
options.reconnect.oauthCode
|
|
617
|
+
);
|
|
618
|
+
await this.mcpConnections[id].establishConnection();
|
|
619
|
+
} catch (error) {
|
|
620
|
+
this._onObservabilityEvent.fire({
|
|
621
|
+
type: "mcp:client:connect",
|
|
622
|
+
displayMessage: `Failed to complete OAuth reconnection for ${id} for ${url}`,
|
|
623
|
+
payload: {
|
|
624
|
+
url,
|
|
625
|
+
transport: options.transport?.type ?? "auto",
|
|
626
|
+
state: this.mcpConnections[id].connectionState,
|
|
627
|
+
error: toErrorMessage(error)
|
|
628
|
+
},
|
|
629
|
+
timestamp: Date.now(),
|
|
630
|
+
id
|
|
631
|
+
});
|
|
632
|
+
throw error;
|
|
398
633
|
}
|
|
399
|
-
|
|
400
|
-
await this.mcpConnections[id].init(options.reconnect?.oauthCode);
|
|
634
|
+
}
|
|
401
635
|
const authUrl = options.transport?.authProvider?.authUrl;
|
|
402
|
-
if (authUrl && options.transport?.authProvider?.redirectUrl) {
|
|
636
|
+
if (this.mcpConnections[id].connectionState === "authenticating" && authUrl && options.transport?.authProvider?.redirectUrl) {
|
|
403
637
|
this._callbackUrls.push(
|
|
404
638
|
options.transport.authProvider.redirectUrl.toString()
|
|
405
639
|
);
|
|
@@ -454,19 +688,88 @@ var MCPClientManager = class {
|
|
|
454
688
|
}
|
|
455
689
|
conn.options.transport.authProvider.clientId = clientId;
|
|
456
690
|
conn.options.transport.authProvider.serverId = serverId;
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
691
|
+
try {
|
|
692
|
+
await conn.completeAuthorization(code);
|
|
693
|
+
return {
|
|
694
|
+
serverId,
|
|
695
|
+
authSuccess: true
|
|
696
|
+
};
|
|
697
|
+
} catch (error) {
|
|
698
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
699
|
+
return {
|
|
700
|
+
serverId,
|
|
701
|
+
authSuccess: false,
|
|
702
|
+
authError: errorMessage
|
|
703
|
+
};
|
|
468
704
|
}
|
|
469
|
-
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Establish connection in the background after OAuth completion
|
|
708
|
+
* This method is called asynchronously and doesn't block the OAuth callback response
|
|
709
|
+
* @param serverId The server ID to establish connection for
|
|
710
|
+
*/
|
|
711
|
+
async establishConnection(serverId) {
|
|
712
|
+
const conn = this.mcpConnections[serverId];
|
|
713
|
+
if (!conn) {
|
|
714
|
+
this._onObservabilityEvent.fire({
|
|
715
|
+
type: "mcp:client:preconnect",
|
|
716
|
+
displayMessage: `Connection not found for serverId: ${serverId}`,
|
|
717
|
+
payload: { serverId },
|
|
718
|
+
timestamp: Date.now(),
|
|
719
|
+
id: nanoid2()
|
|
720
|
+
});
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
try {
|
|
724
|
+
await conn.establishConnection();
|
|
725
|
+
this._onConnected.fire(serverId);
|
|
726
|
+
} catch (error) {
|
|
727
|
+
const url = conn.url.toString();
|
|
728
|
+
this._onObservabilityEvent.fire({
|
|
729
|
+
type: "mcp:client:connect",
|
|
730
|
+
displayMessage: `Failed to establish connection to server ${serverId} with url ${url}`,
|
|
731
|
+
payload: {
|
|
732
|
+
url,
|
|
733
|
+
transport: conn.options.transport.type ?? "auto",
|
|
734
|
+
state: conn.connectionState,
|
|
735
|
+
error: toErrorMessage(error)
|
|
736
|
+
},
|
|
737
|
+
timestamp: Date.now(),
|
|
738
|
+
id: nanoid2()
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Register a callback URL for OAuth handling
|
|
744
|
+
* @param url The callback URL to register
|
|
745
|
+
*/
|
|
746
|
+
registerCallbackUrl(url) {
|
|
747
|
+
if (!this._callbackUrls.includes(url)) {
|
|
748
|
+
this._callbackUrls.push(url);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Unregister a callback URL
|
|
753
|
+
* @param serverId The server ID whose callback URL should be removed
|
|
754
|
+
*/
|
|
755
|
+
unregisterCallbackUrl(serverId) {
|
|
756
|
+
this._callbackUrls = this._callbackUrls.filter(
|
|
757
|
+
(url) => !url.endsWith(`/${serverId}`)
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Configure OAuth callback handling
|
|
762
|
+
* @param config OAuth callback configuration
|
|
763
|
+
*/
|
|
764
|
+
configureOAuthCallback(config) {
|
|
765
|
+
this._oauthCallbackConfig = config;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Get the current OAuth callback configuration
|
|
769
|
+
* @returns The current OAuth callback configuration
|
|
770
|
+
*/
|
|
771
|
+
getOAuthCallbackConfig() {
|
|
772
|
+
return this._oauthCallbackConfig;
|
|
470
773
|
}
|
|
471
774
|
/**
|
|
472
775
|
* @returns namespaced list of tools
|
|
@@ -477,7 +780,7 @@ var MCPClientManager = class {
|
|
|
477
780
|
/**
|
|
478
781
|
* @returns a set of tools that you can use with the AI SDK
|
|
479
782
|
*/
|
|
480
|
-
|
|
783
|
+
getAITools() {
|
|
481
784
|
return Object.fromEntries(
|
|
482
785
|
getNamespacedData(this.mcpConnections, "tools").map((tool) => {
|
|
483
786
|
return [
|
|
@@ -495,21 +798,46 @@ var MCPClientManager = class {
|
|
|
495
798
|
}
|
|
496
799
|
return result;
|
|
497
800
|
},
|
|
498
|
-
|
|
801
|
+
// @ts-expect-error drift between ai and mcp types
|
|
802
|
+
inputSchema: jsonSchema(tool.inputSchema),
|
|
803
|
+
outputSchema: tool.outputSchema ? (
|
|
804
|
+
// @ts-expect-error drift between ai and mcp types
|
|
805
|
+
jsonSchema(tool.outputSchema)
|
|
806
|
+
) : void 0
|
|
499
807
|
}
|
|
500
808
|
];
|
|
501
809
|
})
|
|
502
810
|
);
|
|
503
811
|
}
|
|
812
|
+
/**
|
|
813
|
+
* @deprecated this has been renamed to getAITools(), and unstable_getAITools will be removed in the next major version
|
|
814
|
+
* @returns a set of tools that you can use with the AI SDK
|
|
815
|
+
*/
|
|
816
|
+
unstable_getAITools() {
|
|
817
|
+
if (!this._didWarnAboutUnstableGetAITools) {
|
|
818
|
+
this._didWarnAboutUnstableGetAITools = true;
|
|
819
|
+
console.warn(
|
|
820
|
+
"unstable_getAITools is deprecated, use getAITools instead. unstable_getAITools will be removed in the next major version."
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
return this.getAITools();
|
|
824
|
+
}
|
|
504
825
|
/**
|
|
505
826
|
* Closes all connections to MCP servers
|
|
506
827
|
*/
|
|
507
828
|
async closeAllConnections() {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
829
|
+
const ids = Object.keys(this.mcpConnections);
|
|
830
|
+
await Promise.all(
|
|
831
|
+
ids.map(async (id) => {
|
|
832
|
+
await this.mcpConnections[id].client.close();
|
|
511
833
|
})
|
|
512
834
|
);
|
|
835
|
+
for (const id of ids) {
|
|
836
|
+
const store = this._connectionDisposables.get(id);
|
|
837
|
+
if (store) store.dispose();
|
|
838
|
+
this._connectionDisposables.delete(id);
|
|
839
|
+
delete this.mcpConnections[id];
|
|
840
|
+
}
|
|
513
841
|
}
|
|
514
842
|
/**
|
|
515
843
|
* Closes a connection to an MCP server
|
|
@@ -521,6 +849,20 @@ var MCPClientManager = class {
|
|
|
521
849
|
}
|
|
522
850
|
await this.mcpConnections[id].client.close();
|
|
523
851
|
delete this.mcpConnections[id];
|
|
852
|
+
const store = this._connectionDisposables.get(id);
|
|
853
|
+
if (store) store.dispose();
|
|
854
|
+
this._connectionDisposables.delete(id);
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Dispose the manager and all resources.
|
|
858
|
+
*/
|
|
859
|
+
async dispose() {
|
|
860
|
+
try {
|
|
861
|
+
await this.closeAllConnections();
|
|
862
|
+
} finally {
|
|
863
|
+
this._onConnected.dispose();
|
|
864
|
+
this._onObservabilityEvent.dispose();
|
|
865
|
+
}
|
|
524
866
|
}
|
|
525
867
|
/**
|
|
526
868
|
* @returns namespaced list of prompts
|
|
@@ -543,7 +885,7 @@ var MCPClientManager = class {
|
|
|
543
885
|
/**
|
|
544
886
|
* Namespaced version of callTool
|
|
545
887
|
*/
|
|
546
|
-
callTool(params, resultSchema, options) {
|
|
888
|
+
async callTool(params, resultSchema, options) {
|
|
547
889
|
const unqualifiedName = params.name.replace(`${params.serverId}.`, "");
|
|
548
890
|
return this.mcpConnections[params.serverId].client.callTool(
|
|
549
891
|
{
|
|
@@ -590,9 +932,10 @@ function getNamespacedData(mcpClients, type) {
|
|
|
590
932
|
}
|
|
591
933
|
|
|
592
934
|
export {
|
|
935
|
+
DisposableStore,
|
|
593
936
|
SSEEdgeClientTransport,
|
|
594
937
|
StreamableHTTPEdgeClientTransport,
|
|
595
938
|
MCPClientManager,
|
|
596
939
|
getNamespacedData
|
|
597
940
|
};
|
|
598
|
-
//# sourceMappingURL=chunk-
|
|
941
|
+
//# sourceMappingURL=chunk-3OT2NNEW.js.map
|