agents 0.0.0-bfc9c75 → 0.0.0-bfe9e3d
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/_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 +350 -57
- 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-YDUDMOL6.js → chunk-254F4GDT.js} +97 -50
- package/dist/chunk-254F4GDT.js.map +1 -0
- package/dist/{chunk-MH46VMM4.js → chunk-3OT2NNEW.js} +396 -67
- 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-LL2AFX7V.js → chunk-Z44WASMA.js} +7 -2
- package/dist/{chunk-LL2AFX7V.js.map → chunk-Z44WASMA.js.map} +1 -1
- package/dist/{client-CvaJdLQA.d.ts → client-DVoPb3-C.d.ts} +131 -26
- 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 +25 -32
- package/dist/index.js +5 -4
- package/dist/mcp/client.d.ts +2 -1
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.js +2 -1
- package/dist/mcp/index.d.ts +13 -31
- package/dist/mcp/index.js +233 -163
- 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.js +2 -0
- 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 +19 -6
- package/src/index.ts +141 -57
- package/dist/chunk-AVYJQSLW.js.map +0 -1
- package/dist/chunk-MH46VMM4.js.map +0 -1
- package/dist/chunk-YDUDMOL6.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 {
|
|
@@ -367,6 +562,11 @@ var MCPClientManager = class {
|
|
|
367
562
|
this.mcpConnections = {};
|
|
368
563
|
this._callbackUrls = [];
|
|
369
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;
|
|
370
570
|
}
|
|
371
571
|
/**
|
|
372
572
|
* Connect to and register an MCP server
|
|
@@ -376,31 +576,64 @@ var MCPClientManager = class {
|
|
|
376
576
|
* @param capabilities Client capabilities (i.e. if the client supports roots/sampling)
|
|
377
577
|
*/
|
|
378
578
|
async connect(url, options = {}) {
|
|
379
|
-
const id = options.reconnect?.id ??
|
|
380
|
-
if (
|
|
381
|
-
console.warn(
|
|
382
|
-
"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers"
|
|
383
|
-
);
|
|
384
|
-
} else {
|
|
579
|
+
const id = options.reconnect?.id ?? nanoid2(8);
|
|
580
|
+
if (options.transport?.authProvider) {
|
|
385
581
|
options.transport.authProvider.serverId = id;
|
|
386
582
|
if (options.reconnect?.oauthClientId) {
|
|
387
583
|
options.transport.authProvider.clientId = options.reconnect?.oauthClientId;
|
|
388
584
|
}
|
|
389
585
|
}
|
|
390
|
-
this.mcpConnections[id]
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
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;
|
|
399
633
|
}
|
|
400
|
-
|
|
401
|
-
await this.mcpConnections[id].init(options.reconnect?.oauthCode);
|
|
634
|
+
}
|
|
402
635
|
const authUrl = options.transport?.authProvider?.authUrl;
|
|
403
|
-
if (authUrl && options.transport?.authProvider?.redirectUrl) {
|
|
636
|
+
if (this.mcpConnections[id].connectionState === "authenticating" && authUrl && options.transport?.authProvider?.redirectUrl) {
|
|
404
637
|
this._callbackUrls.push(
|
|
405
638
|
options.transport.authProvider.redirectUrl.toString()
|
|
406
639
|
);
|
|
@@ -455,19 +688,88 @@ var MCPClientManager = class {
|
|
|
455
688
|
}
|
|
456
689
|
conn.options.transport.authProvider.clientId = clientId;
|
|
457
690
|
conn.options.transport.authProvider.serverId = serverId;
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
+
};
|
|
469
704
|
}
|
|
470
|
-
|
|
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;
|
|
471
773
|
}
|
|
472
774
|
/**
|
|
473
775
|
* @returns namespaced list of tools
|
|
@@ -496,7 +798,12 @@ var MCPClientManager = class {
|
|
|
496
798
|
}
|
|
497
799
|
return result;
|
|
498
800
|
},
|
|
499
|
-
|
|
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
|
|
500
807
|
}
|
|
501
808
|
];
|
|
502
809
|
})
|
|
@@ -519,11 +826,18 @@ var MCPClientManager = class {
|
|
|
519
826
|
* Closes all connections to MCP servers
|
|
520
827
|
*/
|
|
521
828
|
async closeAllConnections() {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
829
|
+
const ids = Object.keys(this.mcpConnections);
|
|
830
|
+
await Promise.all(
|
|
831
|
+
ids.map(async (id) => {
|
|
832
|
+
await this.mcpConnections[id].client.close();
|
|
525
833
|
})
|
|
526
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
|
+
}
|
|
527
841
|
}
|
|
528
842
|
/**
|
|
529
843
|
* Closes a connection to an MCP server
|
|
@@ -535,6 +849,20 @@ var MCPClientManager = class {
|
|
|
535
849
|
}
|
|
536
850
|
await this.mcpConnections[id].client.close();
|
|
537
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
|
+
}
|
|
538
866
|
}
|
|
539
867
|
/**
|
|
540
868
|
* @returns namespaced list of prompts
|
|
@@ -557,7 +885,7 @@ var MCPClientManager = class {
|
|
|
557
885
|
/**
|
|
558
886
|
* Namespaced version of callTool
|
|
559
887
|
*/
|
|
560
|
-
callTool(params, resultSchema, options) {
|
|
888
|
+
async callTool(params, resultSchema, options) {
|
|
561
889
|
const unqualifiedName = params.name.replace(`${params.serverId}.`, "");
|
|
562
890
|
return this.mcpConnections[params.serverId].client.callTool(
|
|
563
891
|
{
|
|
@@ -604,9 +932,10 @@ function getNamespacedData(mcpClients, type) {
|
|
|
604
932
|
}
|
|
605
933
|
|
|
606
934
|
export {
|
|
935
|
+
DisposableStore,
|
|
607
936
|
SSEEdgeClientTransport,
|
|
608
937
|
StreamableHTTPEdgeClientTransport,
|
|
609
938
|
MCPClientManager,
|
|
610
939
|
getNamespacedData
|
|
611
940
|
};
|
|
612
|
-
//# sourceMappingURL=chunk-
|
|
941
|
+
//# sourceMappingURL=chunk-3OT2NNEW.js.map
|