agents 0.0.0-ecbd795 → 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/dist/ai-chat-agent.d.ts +2 -1
- package/dist/ai-chat-agent.js +348 -56
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +2 -1
- package/dist/ai-react.js +114 -102
- package/dist/ai-react.js.map +1 -1
- package/dist/{chunk-KK7D3KRW.js → chunk-254F4GDT.js} +92 -49
- package/dist/chunk-254F4GDT.js.map +1 -0
- package/dist/{chunk-THPMWGLS.js → chunk-3OT2NNEW.js} +394 -66
- package/dist/chunk-3OT2NNEW.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/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 +3 -3
- package/dist/mcp/client.d.ts +2 -1
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/do-oauth-client-provider.js +1 -1
- package/dist/mcp/index.d.ts +4 -17
- package/dist/mcp/index.js +3 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +8 -0
- package/dist/mcp/x402.js +10 -10
- package/dist/mcp/x402.js.map +1 -1
- package/dist/mcp-BH1fJeiU.d.ts +58 -0
- package/dist/observability/index.d.ts +12 -24
- package/dist/observability/index.js +3 -3
- package/dist/react.d.ts +10 -6
- package/dist/react.js +99 -2
- package/dist/react.js.map +1 -1
- package/package.json +13 -6
- package/src/index.ts +133 -55
- package/dist/chunk-KK7D3KRW.js.map +0 -1
- package/dist/chunk-THPMWGLS.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,8 +798,12 @@ var MCPClientManager = class {
|
|
|
496
798
|
}
|
|
497
799
|
return result;
|
|
498
800
|
},
|
|
801
|
+
// @ts-expect-error drift between ai and mcp types
|
|
499
802
|
inputSchema: jsonSchema(tool.inputSchema),
|
|
500
|
-
outputSchema: tool.outputSchema ?
|
|
803
|
+
outputSchema: tool.outputSchema ? (
|
|
804
|
+
// @ts-expect-error drift between ai and mcp types
|
|
805
|
+
jsonSchema(tool.outputSchema)
|
|
806
|
+
) : void 0
|
|
501
807
|
}
|
|
502
808
|
];
|
|
503
809
|
})
|
|
@@ -520,11 +826,18 @@ var MCPClientManager = class {
|
|
|
520
826
|
* Closes all connections to MCP servers
|
|
521
827
|
*/
|
|
522
828
|
async closeAllConnections() {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
829
|
+
const ids = Object.keys(this.mcpConnections);
|
|
830
|
+
await Promise.all(
|
|
831
|
+
ids.map(async (id) => {
|
|
832
|
+
await this.mcpConnections[id].client.close();
|
|
526
833
|
})
|
|
527
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
|
+
}
|
|
528
841
|
}
|
|
529
842
|
/**
|
|
530
843
|
* Closes a connection to an MCP server
|
|
@@ -536,6 +849,20 @@ var MCPClientManager = class {
|
|
|
536
849
|
}
|
|
537
850
|
await this.mcpConnections[id].client.close();
|
|
538
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
|
+
}
|
|
539
866
|
}
|
|
540
867
|
/**
|
|
541
868
|
* @returns namespaced list of prompts
|
|
@@ -605,9 +932,10 @@ function getNamespacedData(mcpClients, type) {
|
|
|
605
932
|
}
|
|
606
933
|
|
|
607
934
|
export {
|
|
935
|
+
DisposableStore,
|
|
608
936
|
SSEEdgeClientTransport,
|
|
609
937
|
StreamableHTTPEdgeClientTransport,
|
|
610
938
|
MCPClientManager,
|
|
611
939
|
getNamespacedData
|
|
612
940
|
};
|
|
613
|
-
//# sourceMappingURL=chunk-
|
|
941
|
+
//# sourceMappingURL=chunk-3OT2NNEW.js.map
|