mcp-use 1.10.5 → 1.11.0-canary.10
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 +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-IY632ZQS.js → chunk-3GB7G5X7.js} +2 -2
- package/dist/{chunk-E42PSMPK.js → chunk-5QAXQTDL.js} +1 -1
- package/dist/{chunk-C7WHRUWQ.js → chunk-BEGEDH6P.js} +196 -496
- package/dist/{chunk-MO5FM5B2.js → chunk-BLGIG2QD.js} +443 -969
- package/dist/{chunk-XG7SR6G4.js → chunk-CBJTHTR4.js} +3 -8
- package/dist/{chunk-34R6SIER.js → chunk-FRUZDWXH.js} +1 -1
- package/dist/chunk-GUB5GQDD.js +101 -0
- package/dist/chunk-GXNAXUDI.js +0 -0
- package/dist/{chunk-CPG2WZUL.js → chunk-JRGQRPTN.js} +1 -1
- package/dist/chunk-MFSO5PUW.js +1049 -0
- package/dist/{chunk-UD5FSFEZ.js → chunk-NXFHUS7A.js} +171 -11
- package/dist/chunk-ULFNVP5Z.js +12 -0
- package/dist/chunk-UWWLWLS2.js +62 -0
- package/dist/chunk-VTEYN43V.js +1055 -0
- package/dist/{chunk-YOHGE3NK.js → chunk-XPTKLSBC.js} +16 -2
- package/dist/index.cjs +5065 -4608
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -1068
- package/dist/{langfuse-N5Y5BSXK.js → langfuse-74RGPTAH.js} +2 -2
- package/dist/notifications-FLGIFS56.js +9 -0
- package/dist/src/adapters/base.d.ts +44 -0
- package/dist/src/adapters/base.d.ts.map +1 -1
- package/dist/src/adapters/index.cjs +1346 -0
- package/dist/src/adapters/index.js +11 -0
- package/dist/src/adapters/langchain_adapter.d.ts +12 -1
- package/dist/src/adapters/langchain_adapter.d.ts.map +1 -1
- package/dist/src/agents/index.cjs +3141 -159
- package/dist/src/agents/index.d.ts +2 -0
- package/dist/src/agents/index.d.ts.map +1 -1
- package/dist/src/agents/index.js +10 -6
- package/dist/src/agents/mcp_agent.d.ts +59 -37
- package/dist/src/agents/mcp_agent.d.ts.map +1 -1
- package/dist/src/agents/remote.d.ts +25 -0
- package/dist/src/agents/remote.d.ts.map +1 -1
- package/dist/src/agents/types.d.ts +76 -0
- package/dist/src/agents/types.d.ts.map +1 -1
- package/dist/src/agents/utils/index.d.ts +1 -0
- package/dist/src/agents/utils/index.d.ts.map +1 -1
- package/dist/src/agents/utils/llm_provider.d.ts +53 -0
- package/dist/src/agents/utils/llm_provider.d.ts.map +1 -0
- package/dist/src/browser.cjs +1856 -423
- package/dist/src/browser.d.ts +1 -2
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +26 -15
- package/dist/src/client/base.d.ts +1 -0
- package/dist/src/client/base.d.ts.map +1 -1
- package/dist/src/client/browser.d.ts +2 -2
- package/dist/src/client/browser.d.ts.map +1 -1
- package/dist/src/client/prompts.cjs +1 -1
- package/dist/src/client/prompts.js +5 -4
- package/dist/src/client.cjs +3787 -0
- package/dist/src/client.js +20 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/connectors/base.d.ts +8 -0
- package/dist/src/connectors/base.d.ts.map +1 -1
- package/dist/src/connectors/index.d.ts +0 -1
- package/dist/src/connectors/index.d.ts.map +1 -1
- package/dist/src/managers/server_manager.d.ts.map +1 -1
- package/dist/src/managers/tools/connect_mcp_server.d.ts.map +1 -1
- package/dist/src/react/index.cjs +259 -298
- package/dist/src/react/index.js +6 -5
- package/dist/src/react/types.d.ts +42 -4
- package/dist/src/react/types.d.ts.map +1 -1
- package/dist/src/react/useMcp.d.ts.map +1 -1
- package/dist/src/react/useWidget.d.ts +11 -7
- package/dist/src/react/useWidget.d.ts.map +1 -1
- package/dist/src/react/widget-types.d.ts +6 -2
- package/dist/src/react/widget-types.d.ts.map +1 -1
- package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
- package/dist/src/server/index.cjs +1379 -208
- package/dist/src/server/index.d.ts +2 -0
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +1353 -249
- package/dist/src/server/mcp-server.d.ts +5 -1
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/notifications/index.d.ts +1 -1
- package/dist/src/server/notifications/index.d.ts.map +1 -1
- package/dist/src/server/notifications/notification-registration.d.ts +51 -0
- package/dist/src/server/notifications/notification-registration.d.ts.map +1 -1
- package/dist/src/server/sessions/index.d.ts +3 -1
- package/dist/src/server/sessions/index.d.ts.map +1 -1
- package/dist/src/server/sessions/session-manager.d.ts +36 -19
- package/dist/src/server/sessions/session-manager.d.ts.map +1 -1
- package/dist/src/server/sessions/stores/filesystem.d.ts +121 -0
- package/dist/src/server/sessions/stores/filesystem.d.ts.map +1 -0
- package/dist/src/server/sessions/stores/index.d.ts +94 -0
- package/dist/src/server/sessions/stores/index.d.ts.map +1 -0
- package/dist/src/server/sessions/stores/memory.d.ts +82 -0
- package/dist/src/server/sessions/stores/memory.d.ts.map +1 -0
- package/dist/src/server/sessions/stores/redis.d.ts +164 -0
- package/dist/src/server/sessions/stores/redis.d.ts.map +1 -0
- package/dist/src/server/sessions/streams/index.d.ts +77 -0
- package/dist/src/server/sessions/streams/index.d.ts.map +1 -0
- package/dist/src/server/sessions/streams/memory.d.ts +76 -0
- package/dist/src/server/sessions/streams/memory.d.ts.map +1 -0
- package/dist/src/server/sessions/streams/redis.d.ts +146 -0
- package/dist/src/server/sessions/streams/redis.d.ts.map +1 -0
- package/dist/src/server/types/common.d.ts +120 -17
- package/dist/src/server/types/common.d.ts.map +1 -1
- package/dist/src/server/types/resource.d.ts +16 -0
- package/dist/src/server/types/resource.d.ts.map +1 -1
- package/dist/src/server/types/widget.d.ts +21 -2
- package/dist/src/server/types/widget.d.ts.map +1 -1
- package/dist/src/server/utils/response-helpers.d.ts +12 -6
- package/dist/src/server/utils/response-helpers.d.ts.map +1 -1
- package/dist/src/server/widgets/index.d.ts +1 -1
- package/dist/src/server/widgets/index.d.ts.map +1 -1
- package/dist/src/server/widgets/mount-widgets-dev.d.ts.map +1 -1
- package/dist/src/server/widgets/setup-widget-routes.d.ts.map +1 -1
- package/dist/src/server/widgets/ui-resource-registration.d.ts.map +1 -1
- package/dist/src/server/widgets/widget-helpers.d.ts +22 -0
- package/dist/src/server/widgets/widget-helpers.d.ts.map +1 -1
- package/dist/src/server/widgets/widget-types.d.ts +2 -0
- package/dist/src/server/widgets/widget-types.d.ts.map +1 -1
- package/dist/src/session.d.ts +16 -2
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/task_managers/index.d.ts +10 -1
- package/dist/src/task_managers/index.d.ts.map +1 -1
- package/dist/src/task_managers/sse.d.ts +34 -1
- package/dist/src/task_managers/sse.d.ts.map +1 -1
- package/dist/src/task_managers/streamable_http.d.ts +8 -2
- package/dist/src/task_managers/streamable_http.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/{tool-execution-helpers-XTDKRH6N.js → tool-execution-helpers-N7R7YGAW.js} +3 -3
- package/dist/tsup.config.d.ts.map +1 -1
- package/package.json +47 -14
- package/dist/src/connectors/websocket.d.ts +0 -38
- package/dist/src/connectors/websocket.d.ts.map +0 -1
- package/dist/src/task_managers/websocket.d.ts +0 -18
- package/dist/src/task_managers/websocket.d.ts.map +0 -1
- /package/dist/{chunk-EW4MJSHA.js → chunk-LGDFGYRL.js} +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BaseConnector
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XPTKLSBC.js";
|
|
4
4
|
import {
|
|
5
|
-
Tel
|
|
6
|
-
|
|
7
|
-
getPackageVersion
|
|
8
|
-
} from "./chunk-IY632ZQS.js";
|
|
5
|
+
Tel
|
|
6
|
+
} from "./chunk-3GB7G5X7.js";
|
|
9
7
|
import {
|
|
10
8
|
logger
|
|
11
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FRUZDWXH.js";
|
|
12
10
|
import {
|
|
13
11
|
__name
|
|
14
12
|
} from "./chunk-3GQAWCBQ.js";
|
|
@@ -98,6 +96,22 @@ var MCPSession = class {
|
|
|
98
96
|
get tools() {
|
|
99
97
|
return this.connector.tools;
|
|
100
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* List all available tools from the MCP server.
|
|
101
|
+
* This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
|
|
102
|
+
*
|
|
103
|
+
* @param options - Optional request options
|
|
104
|
+
* @returns Array of available tools
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const tools = await session.listTools();
|
|
109
|
+
* console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
async listTools(options) {
|
|
113
|
+
return this.connector.listTools(options);
|
|
114
|
+
}
|
|
101
115
|
/**
|
|
102
116
|
* Get the server capabilities advertised during initialization.
|
|
103
117
|
*
|
|
@@ -118,7 +132,7 @@ var MCPSession = class {
|
|
|
118
132
|
* Call a tool on the server.
|
|
119
133
|
*
|
|
120
134
|
* @param name - Name of the tool to call
|
|
121
|
-
* @param args - Arguments to pass to the tool
|
|
135
|
+
* @param args - Arguments to pass to the tool (defaults to empty object)
|
|
122
136
|
* @param options - Optional request options (timeout, progress handlers, etc.)
|
|
123
137
|
* @returns Result from the tool execution
|
|
124
138
|
*
|
|
@@ -128,7 +142,7 @@ var MCPSession = class {
|
|
|
128
142
|
* console.log(`Result: ${result.content[0].text}`);
|
|
129
143
|
* ```
|
|
130
144
|
*/
|
|
131
|
-
async callTool(name, args, options) {
|
|
145
|
+
async callTool(name, args = {}, options) {
|
|
132
146
|
return this.connector.callTool(name, args, options);
|
|
133
147
|
}
|
|
134
148
|
/**
|
|
@@ -270,6 +284,134 @@ var MCPSession = class {
|
|
|
270
284
|
}
|
|
271
285
|
};
|
|
272
286
|
|
|
287
|
+
// src/client/base.ts
|
|
288
|
+
var BaseMCPClient = class {
|
|
289
|
+
static {
|
|
290
|
+
__name(this, "BaseMCPClient");
|
|
291
|
+
}
|
|
292
|
+
config = {};
|
|
293
|
+
sessions = {};
|
|
294
|
+
activeSessions = [];
|
|
295
|
+
constructor(config) {
|
|
296
|
+
if (config) {
|
|
297
|
+
this.config = config;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
static fromDict(_cfg) {
|
|
301
|
+
throw new Error("fromDict must be implemented by concrete class");
|
|
302
|
+
}
|
|
303
|
+
addServer(name, serverConfig) {
|
|
304
|
+
this.config.mcpServers = this.config.mcpServers || {};
|
|
305
|
+
this.config.mcpServers[name] = serverConfig;
|
|
306
|
+
Tel.getInstance().trackClientAddServer(name, serverConfig);
|
|
307
|
+
}
|
|
308
|
+
removeServer(name) {
|
|
309
|
+
if (this.config.mcpServers?.[name]) {
|
|
310
|
+
delete this.config.mcpServers[name];
|
|
311
|
+
this.activeSessions = this.activeSessions.filter((n) => n !== name);
|
|
312
|
+
Tel.getInstance().trackClientRemoveServer(name);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
getServerNames() {
|
|
316
|
+
return Object.keys(this.config.mcpServers ?? {});
|
|
317
|
+
}
|
|
318
|
+
getServerConfig(name) {
|
|
319
|
+
return this.config.mcpServers?.[name];
|
|
320
|
+
}
|
|
321
|
+
getConfig() {
|
|
322
|
+
return this.config ?? {};
|
|
323
|
+
}
|
|
324
|
+
async createSession(serverName, autoInitialize = true) {
|
|
325
|
+
const servers = this.config.mcpServers ?? {};
|
|
326
|
+
if (Object.keys(servers).length === 0) {
|
|
327
|
+
logger.warn("No MCP servers defined in config");
|
|
328
|
+
}
|
|
329
|
+
if (!servers[serverName]) {
|
|
330
|
+
throw new Error(`Server '${serverName}' not found in config`);
|
|
331
|
+
}
|
|
332
|
+
const connector = this.createConnectorFromConfig(servers[serverName]);
|
|
333
|
+
const session = new MCPSession(connector);
|
|
334
|
+
if (autoInitialize) {
|
|
335
|
+
await session.initialize();
|
|
336
|
+
}
|
|
337
|
+
this.sessions[serverName] = session;
|
|
338
|
+
if (!this.activeSessions.includes(serverName)) {
|
|
339
|
+
this.activeSessions.push(serverName);
|
|
340
|
+
}
|
|
341
|
+
return session;
|
|
342
|
+
}
|
|
343
|
+
async createAllSessions(autoInitialize = true) {
|
|
344
|
+
const servers = this.config.mcpServers ?? {};
|
|
345
|
+
if (Object.keys(servers).length === 0) {
|
|
346
|
+
logger.warn("No MCP servers defined in config");
|
|
347
|
+
}
|
|
348
|
+
for (const name of Object.keys(servers)) {
|
|
349
|
+
await this.createSession(name, autoInitialize);
|
|
350
|
+
}
|
|
351
|
+
return this.sessions;
|
|
352
|
+
}
|
|
353
|
+
getSession(serverName) {
|
|
354
|
+
const session = this.sessions[serverName];
|
|
355
|
+
if (!session) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
return session;
|
|
359
|
+
}
|
|
360
|
+
requireSession(serverName) {
|
|
361
|
+
const session = this.sessions[serverName];
|
|
362
|
+
if (!session) {
|
|
363
|
+
throw new Error(
|
|
364
|
+
`Session '${serverName}' not found. Available sessions: ${this.activeSessions.join(", ") || "none"}`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
return session;
|
|
368
|
+
}
|
|
369
|
+
getAllActiveSessions() {
|
|
370
|
+
return Object.fromEntries(
|
|
371
|
+
this.activeSessions.map((n) => [n, this.sessions[n]])
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
async closeSession(serverName) {
|
|
375
|
+
const session = this.sessions[serverName];
|
|
376
|
+
if (!session) {
|
|
377
|
+
logger.warn(
|
|
378
|
+
`No session exists for server ${serverName}, nothing to close`
|
|
379
|
+
);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
logger.debug(`Closing session for server ${serverName}`);
|
|
384
|
+
await session.disconnect();
|
|
385
|
+
} catch (e) {
|
|
386
|
+
logger.error(`Error closing session for server '${serverName}': ${e}`);
|
|
387
|
+
} finally {
|
|
388
|
+
delete this.sessions[serverName];
|
|
389
|
+
this.activeSessions = this.activeSessions.filter((n) => n !== serverName);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
async closeAllSessions() {
|
|
393
|
+
const serverNames = Object.keys(this.sessions);
|
|
394
|
+
const errors = [];
|
|
395
|
+
for (const serverName of serverNames) {
|
|
396
|
+
try {
|
|
397
|
+
logger.debug(`Closing session for server ${serverName}`);
|
|
398
|
+
await this.closeSession(serverName);
|
|
399
|
+
} catch (e) {
|
|
400
|
+
const errorMsg = `Failed to close session for server '${serverName}': ${e}`;
|
|
401
|
+
logger.error(errorMsg);
|
|
402
|
+
errors.push(errorMsg);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (errors.length) {
|
|
406
|
+
logger.error(
|
|
407
|
+
`Encountered ${errors.length} errors while closing sessions`
|
|
408
|
+
);
|
|
409
|
+
} else {
|
|
410
|
+
logger.debug("All sessions closed successfully");
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
273
415
|
// src/connectors/http.ts
|
|
274
416
|
import { Client } from "@mcp-use/modelcontextprotocol-sdk/client/index.js";
|
|
275
417
|
import {
|
|
@@ -405,6 +547,7 @@ var SseConnectionManager = class extends ConnectionManager {
|
|
|
405
547
|
url;
|
|
406
548
|
opts;
|
|
407
549
|
_transport = null;
|
|
550
|
+
reinitializing = false;
|
|
408
551
|
/**
|
|
409
552
|
* Create an SSE connection manager.
|
|
410
553
|
*
|
|
@@ -417,12 +560,53 @@ var SseConnectionManager = class extends ConnectionManager {
|
|
|
417
560
|
this.opts = opts;
|
|
418
561
|
}
|
|
419
562
|
/**
|
|
420
|
-
* Spawn a new `SSEClientTransport` and
|
|
563
|
+
* Spawn a new `SSEClientTransport` and wrap it with 404 handling.
|
|
564
|
+
* Per MCP spec, clients MUST re-initialize when receiving 404 for stale sessions.
|
|
421
565
|
*/
|
|
422
566
|
async establishConnection() {
|
|
423
|
-
|
|
567
|
+
const transport = new SSEClientTransport(this.url, this.opts);
|
|
568
|
+
const originalSend = transport.send.bind(transport);
|
|
569
|
+
transport.send = async (message) => {
|
|
570
|
+
const sendMessage = /* @__PURE__ */ __name(async (msg) => {
|
|
571
|
+
if (Array.isArray(msg)) {
|
|
572
|
+
for (const singleMsg of msg) {
|
|
573
|
+
await originalSend(singleMsg);
|
|
574
|
+
}
|
|
575
|
+
} else {
|
|
576
|
+
await originalSend(msg);
|
|
577
|
+
}
|
|
578
|
+
}, "sendMessage");
|
|
579
|
+
try {
|
|
580
|
+
await sendMessage(message);
|
|
581
|
+
} catch (error) {
|
|
582
|
+
if (error?.code === 404 && transport.sessionId && !this.reinitializing) {
|
|
583
|
+
logger.warn(
|
|
584
|
+
`[SSE] Session not found (404), re-initializing per MCP spec...`
|
|
585
|
+
);
|
|
586
|
+
this.reinitializing = true;
|
|
587
|
+
try {
|
|
588
|
+
transport.sessionId = void 0;
|
|
589
|
+
await this.reinitialize(transport);
|
|
590
|
+
logger.info(`[SSE] Re-initialization successful, retrying request`);
|
|
591
|
+
await sendMessage(message);
|
|
592
|
+
} finally {
|
|
593
|
+
this.reinitializing = false;
|
|
594
|
+
}
|
|
595
|
+
} else {
|
|
596
|
+
throw error;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
this._transport = transport;
|
|
424
601
|
logger.debug(`${this.constructor.name} connected successfully`);
|
|
425
|
-
return
|
|
602
|
+
return transport;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Re-initialize the transport with a new session
|
|
606
|
+
* This is called when the server returns 404 for a stale session
|
|
607
|
+
*/
|
|
608
|
+
async reinitialize(transport) {
|
|
609
|
+
logger.debug(`[SSE] Re-initialization triggered`);
|
|
426
610
|
}
|
|
427
611
|
/**
|
|
428
612
|
* Close the underlying transport and clean up resources.
|
|
@@ -713,493 +897,9 @@ var HttpConnector = class extends BaseConnector {
|
|
|
713
897
|
}
|
|
714
898
|
};
|
|
715
899
|
|
|
716
|
-
// src/task_managers/websocket.ts
|
|
717
|
-
import WS from "ws";
|
|
718
|
-
var WebSocketConnectionManager = class extends ConnectionManager {
|
|
719
|
-
static {
|
|
720
|
-
__name(this, "WebSocketConnectionManager");
|
|
721
|
-
}
|
|
722
|
-
url;
|
|
723
|
-
headers;
|
|
724
|
-
_ws = null;
|
|
725
|
-
/**
|
|
726
|
-
* @param url The WebSocket URL to connect to.
|
|
727
|
-
* @param headers Optional headers to include in the connection handshake.
|
|
728
|
-
*/
|
|
729
|
-
constructor(url, headers = {}) {
|
|
730
|
-
super();
|
|
731
|
-
this.url = url;
|
|
732
|
-
this.headers = headers;
|
|
733
|
-
}
|
|
734
|
-
/** Establish a WebSocket connection and wait until it is open. */
|
|
735
|
-
async establishConnection() {
|
|
736
|
-
logger.debug(`Connecting to WebSocket: ${this.url}`);
|
|
737
|
-
return new Promise((resolve, reject) => {
|
|
738
|
-
const ws = new WS(this.url, {
|
|
739
|
-
headers: this.headers
|
|
740
|
-
});
|
|
741
|
-
this._ws = ws;
|
|
742
|
-
const onOpen = /* @__PURE__ */ __name(() => {
|
|
743
|
-
cleanup();
|
|
744
|
-
logger.debug("WebSocket connected successfully");
|
|
745
|
-
resolve(ws);
|
|
746
|
-
}, "onOpen");
|
|
747
|
-
const onError = /* @__PURE__ */ __name((err) => {
|
|
748
|
-
cleanup();
|
|
749
|
-
logger.error(`Failed to connect to WebSocket: ${err}`);
|
|
750
|
-
reject(err);
|
|
751
|
-
}, "onError");
|
|
752
|
-
const cleanup = /* @__PURE__ */ __name(() => {
|
|
753
|
-
ws.off("open", onOpen);
|
|
754
|
-
ws.off("error", onError);
|
|
755
|
-
}, "cleanup");
|
|
756
|
-
ws.on("open", onOpen);
|
|
757
|
-
ws.on("error", onError);
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
/** Cleanly close the WebSocket connection. */
|
|
761
|
-
async closeConnection(connection) {
|
|
762
|
-
logger.debug("Closing WebSocket connection");
|
|
763
|
-
return new Promise((resolve) => {
|
|
764
|
-
const onClose = /* @__PURE__ */ __name(() => {
|
|
765
|
-
connection.off("close", onClose);
|
|
766
|
-
this._ws = null;
|
|
767
|
-
resolve();
|
|
768
|
-
}, "onClose");
|
|
769
|
-
if (connection.readyState === WS.CLOSED) {
|
|
770
|
-
onClose();
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
connection.on("close", onClose);
|
|
774
|
-
try {
|
|
775
|
-
connection.close();
|
|
776
|
-
} catch (e) {
|
|
777
|
-
logger.warn(`Error closing WebSocket connection: ${e}`);
|
|
778
|
-
onClose();
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
// src/connectors/websocket.ts
|
|
785
|
-
var WebSocketConnector = class extends BaseConnector {
|
|
786
|
-
static {
|
|
787
|
-
__name(this, "WebSocketConnector");
|
|
788
|
-
}
|
|
789
|
-
url;
|
|
790
|
-
headers;
|
|
791
|
-
connectionManager = null;
|
|
792
|
-
ws = null;
|
|
793
|
-
receiverTask = null;
|
|
794
|
-
pending = /* @__PURE__ */ new Map();
|
|
795
|
-
toolsCache = null;
|
|
796
|
-
constructor(url, opts = {}) {
|
|
797
|
-
super();
|
|
798
|
-
this.url = url;
|
|
799
|
-
this.headers = { ...opts.headers ?? {} };
|
|
800
|
-
if (opts.authToken) this.headers.Authorization = `Bearer ${opts.authToken}`;
|
|
801
|
-
}
|
|
802
|
-
async connect() {
|
|
803
|
-
if (this.connected) {
|
|
804
|
-
logger.debug("Already connected to MCP implementation");
|
|
805
|
-
return;
|
|
806
|
-
}
|
|
807
|
-
logger.debug(`Connecting via WebSocket: ${this.url}`);
|
|
808
|
-
try {
|
|
809
|
-
this.connectionManager = new WebSocketConnectionManager(
|
|
810
|
-
this.url,
|
|
811
|
-
this.headers
|
|
812
|
-
);
|
|
813
|
-
this.ws = await this.connectionManager.start();
|
|
814
|
-
this.receiverTask = this.receiveLoop();
|
|
815
|
-
this.connected = true;
|
|
816
|
-
logger.debug("WebSocket connected successfully");
|
|
817
|
-
} catch (e) {
|
|
818
|
-
logger.error(`Failed to connect: ${e}`);
|
|
819
|
-
await this.cleanupResources();
|
|
820
|
-
throw e;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
async disconnect() {
|
|
824
|
-
if (!this.connected) {
|
|
825
|
-
logger.debug("Not connected to MCP implementation");
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
logger.debug("Disconnecting \u2026");
|
|
829
|
-
await this.cleanupResources();
|
|
830
|
-
this.connected = false;
|
|
831
|
-
}
|
|
832
|
-
sendRequest(method, params = null) {
|
|
833
|
-
if (!this.ws) throw new Error("WebSocket is not connected");
|
|
834
|
-
const id = generateUUID();
|
|
835
|
-
const payload = JSON.stringify({ id, method, params: params ?? {} });
|
|
836
|
-
return new Promise((resolve, reject) => {
|
|
837
|
-
this.pending.set(id, { resolve, reject });
|
|
838
|
-
this.ws.send(payload, (err) => {
|
|
839
|
-
if (err) {
|
|
840
|
-
this.pending.delete(id);
|
|
841
|
-
reject(err);
|
|
842
|
-
}
|
|
843
|
-
});
|
|
844
|
-
});
|
|
845
|
-
}
|
|
846
|
-
async receiveLoop() {
|
|
847
|
-
if (!this.ws) return;
|
|
848
|
-
const socket = this.ws;
|
|
849
|
-
const onMessage = /* @__PURE__ */ __name((msg) => {
|
|
850
|
-
let data;
|
|
851
|
-
try {
|
|
852
|
-
data = JSON.parse(msg.data ?? msg);
|
|
853
|
-
} catch (e) {
|
|
854
|
-
logger.warn("Received non\u2011JSON frame", e);
|
|
855
|
-
return;
|
|
856
|
-
}
|
|
857
|
-
const id = data.id;
|
|
858
|
-
if (id && this.pending.has(id)) {
|
|
859
|
-
const { resolve, reject } = this.pending.get(id);
|
|
860
|
-
this.pending.delete(id);
|
|
861
|
-
if ("result" in data) resolve(data.result);
|
|
862
|
-
else if ("error" in data) reject(data.error);
|
|
863
|
-
} else if (data.method && !data.id) {
|
|
864
|
-
logger.debug("Received notification", data.method, data.params);
|
|
865
|
-
this.handleNotification(data);
|
|
866
|
-
} else {
|
|
867
|
-
logger.debug("Received unsolicited message", data);
|
|
868
|
-
}
|
|
869
|
-
}, "onMessage");
|
|
870
|
-
if (socket.addEventListener) {
|
|
871
|
-
socket.addEventListener("message", onMessage);
|
|
872
|
-
} else {
|
|
873
|
-
socket.on("message", onMessage);
|
|
874
|
-
}
|
|
875
|
-
return new Promise((resolve) => {
|
|
876
|
-
const onClose = /* @__PURE__ */ __name(() => {
|
|
877
|
-
if (socket.removeEventListener) {
|
|
878
|
-
socket.removeEventListener("message", onMessage);
|
|
879
|
-
} else {
|
|
880
|
-
socket.off("message", onMessage);
|
|
881
|
-
}
|
|
882
|
-
this.rejectAll(new Error("WebSocket closed"));
|
|
883
|
-
resolve();
|
|
884
|
-
}, "onClose");
|
|
885
|
-
if (socket.addEventListener) {
|
|
886
|
-
socket.addEventListener("close", onClose);
|
|
887
|
-
} else {
|
|
888
|
-
socket.on("close", onClose);
|
|
889
|
-
}
|
|
890
|
-
});
|
|
891
|
-
}
|
|
892
|
-
rejectAll(err) {
|
|
893
|
-
for (const { reject } of this.pending.values()) reject(err);
|
|
894
|
-
this.pending.clear();
|
|
895
|
-
}
|
|
896
|
-
async handleNotification(data) {
|
|
897
|
-
switch (data.method) {
|
|
898
|
-
case "notifications/tools/list_changed":
|
|
899
|
-
await this.refreshToolsCache();
|
|
900
|
-
break;
|
|
901
|
-
case "notifications/resources/list_changed":
|
|
902
|
-
await this.onResourcesListChanged();
|
|
903
|
-
break;
|
|
904
|
-
case "notifications/prompts/list_changed":
|
|
905
|
-
await this.onPromptsListChanged();
|
|
906
|
-
break;
|
|
907
|
-
default:
|
|
908
|
-
break;
|
|
909
|
-
}
|
|
910
|
-
for (const handler of this.notificationHandlers) {
|
|
911
|
-
try {
|
|
912
|
-
await handler({
|
|
913
|
-
method: data.method,
|
|
914
|
-
params: data.params
|
|
915
|
-
});
|
|
916
|
-
} catch (err) {
|
|
917
|
-
logger.error("Error in notification handler:", err);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* Auto-refresh tools cache when server sends tools/list_changed notification
|
|
923
|
-
* Override to use WebSocket-specific listTools method
|
|
924
|
-
*/
|
|
925
|
-
async refreshToolsCache() {
|
|
926
|
-
try {
|
|
927
|
-
logger.debug(
|
|
928
|
-
"[Auto] Refreshing tools cache due to list_changed notification"
|
|
929
|
-
);
|
|
930
|
-
const tools = await this.listTools();
|
|
931
|
-
this.toolsCache = tools.map((t) => t);
|
|
932
|
-
logger.debug(
|
|
933
|
-
`[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
|
|
934
|
-
);
|
|
935
|
-
} catch (err) {
|
|
936
|
-
logger.warn("[Auto] Failed to refresh tools cache:", err);
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
async initialize() {
|
|
940
|
-
logger.debug("Initializing MCP session over WebSocket");
|
|
941
|
-
const result = await this.sendRequest("initialize");
|
|
942
|
-
const toolsList = await this.listTools();
|
|
943
|
-
this.toolsCache = toolsList.map((t) => t);
|
|
944
|
-
logger.debug(`Initialized with ${this.toolsCache.length} tools`);
|
|
945
|
-
return result;
|
|
946
|
-
}
|
|
947
|
-
async listTools() {
|
|
948
|
-
const res = await this.sendRequest("tools/list");
|
|
949
|
-
return res.tools ?? [];
|
|
950
|
-
}
|
|
951
|
-
async callTool(name, args) {
|
|
952
|
-
return await this.sendRequest("tools/call", { name, arguments: args });
|
|
953
|
-
}
|
|
954
|
-
async listResources() {
|
|
955
|
-
const resources = await this.sendRequest("resources/list");
|
|
956
|
-
return { resources: Array.isArray(resources) ? resources : [] };
|
|
957
|
-
}
|
|
958
|
-
async readResource(uri) {
|
|
959
|
-
const res = await this.sendRequest("resources/read", { uri });
|
|
960
|
-
return res;
|
|
961
|
-
}
|
|
962
|
-
async request(method, params = null) {
|
|
963
|
-
return await this.sendRequest(method, params);
|
|
964
|
-
}
|
|
965
|
-
get tools() {
|
|
966
|
-
if (!this.toolsCache) throw new Error("MCP client is not initialized");
|
|
967
|
-
return this.toolsCache;
|
|
968
|
-
}
|
|
969
|
-
async cleanupResources() {
|
|
970
|
-
if (this.receiverTask) await this.receiverTask.catch(() => {
|
|
971
|
-
});
|
|
972
|
-
this.receiverTask = null;
|
|
973
|
-
this.rejectAll(new Error("WebSocket disconnected"));
|
|
974
|
-
if (this.connectionManager) {
|
|
975
|
-
await this.connectionManager.stop();
|
|
976
|
-
this.connectionManager = null;
|
|
977
|
-
this.ws = null;
|
|
978
|
-
}
|
|
979
|
-
this.toolsCache = null;
|
|
980
|
-
}
|
|
981
|
-
get publicIdentifier() {
|
|
982
|
-
return {
|
|
983
|
-
type: "websocket",
|
|
984
|
-
url: this.url
|
|
985
|
-
};
|
|
986
|
-
}
|
|
987
|
-
};
|
|
988
|
-
|
|
989
|
-
// src/client/base.ts
|
|
990
|
-
var BaseMCPClient = class {
|
|
991
|
-
static {
|
|
992
|
-
__name(this, "BaseMCPClient");
|
|
993
|
-
}
|
|
994
|
-
config = {};
|
|
995
|
-
sessions = {};
|
|
996
|
-
activeSessions = [];
|
|
997
|
-
constructor(config) {
|
|
998
|
-
if (config) {
|
|
999
|
-
this.config = config;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
static fromDict(_cfg) {
|
|
1003
|
-
throw new Error("fromDict must be implemented by concrete class");
|
|
1004
|
-
}
|
|
1005
|
-
addServer(name, serverConfig) {
|
|
1006
|
-
this.config.mcpServers = this.config.mcpServers || {};
|
|
1007
|
-
this.config.mcpServers[name] = serverConfig;
|
|
1008
|
-
Tel.getInstance().trackClientAddServer(name, serverConfig);
|
|
1009
|
-
}
|
|
1010
|
-
removeServer(name) {
|
|
1011
|
-
if (this.config.mcpServers?.[name]) {
|
|
1012
|
-
delete this.config.mcpServers[name];
|
|
1013
|
-
this.activeSessions = this.activeSessions.filter((n) => n !== name);
|
|
1014
|
-
Tel.getInstance().trackClientRemoveServer(name);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
getServerNames() {
|
|
1018
|
-
return Object.keys(this.config.mcpServers ?? {});
|
|
1019
|
-
}
|
|
1020
|
-
getServerConfig(name) {
|
|
1021
|
-
return this.config.mcpServers?.[name];
|
|
1022
|
-
}
|
|
1023
|
-
getConfig() {
|
|
1024
|
-
return this.config ?? {};
|
|
1025
|
-
}
|
|
1026
|
-
async createSession(serverName, autoInitialize = true) {
|
|
1027
|
-
const servers = this.config.mcpServers ?? {};
|
|
1028
|
-
if (Object.keys(servers).length === 0) {
|
|
1029
|
-
logger.warn("No MCP servers defined in config");
|
|
1030
|
-
}
|
|
1031
|
-
if (!servers[serverName]) {
|
|
1032
|
-
throw new Error(`Server '${serverName}' not found in config`);
|
|
1033
|
-
}
|
|
1034
|
-
const connector = this.createConnectorFromConfig(servers[serverName]);
|
|
1035
|
-
const session = new MCPSession(connector);
|
|
1036
|
-
if (autoInitialize) {
|
|
1037
|
-
await session.initialize();
|
|
1038
|
-
}
|
|
1039
|
-
this.sessions[serverName] = session;
|
|
1040
|
-
if (!this.activeSessions.includes(serverName)) {
|
|
1041
|
-
this.activeSessions.push(serverName);
|
|
1042
|
-
}
|
|
1043
|
-
return session;
|
|
1044
|
-
}
|
|
1045
|
-
async createAllSessions(autoInitialize = true) {
|
|
1046
|
-
const servers = this.config.mcpServers ?? {};
|
|
1047
|
-
if (Object.keys(servers).length === 0) {
|
|
1048
|
-
logger.warn("No MCP servers defined in config");
|
|
1049
|
-
}
|
|
1050
|
-
for (const name of Object.keys(servers)) {
|
|
1051
|
-
await this.createSession(name, autoInitialize);
|
|
1052
|
-
}
|
|
1053
|
-
return this.sessions;
|
|
1054
|
-
}
|
|
1055
|
-
getSession(serverName) {
|
|
1056
|
-
const session = this.sessions[serverName];
|
|
1057
|
-
if (!session) {
|
|
1058
|
-
return null;
|
|
1059
|
-
}
|
|
1060
|
-
return session;
|
|
1061
|
-
}
|
|
1062
|
-
getAllActiveSessions() {
|
|
1063
|
-
return Object.fromEntries(
|
|
1064
|
-
this.activeSessions.map((n) => [n, this.sessions[n]])
|
|
1065
|
-
);
|
|
1066
|
-
}
|
|
1067
|
-
async closeSession(serverName) {
|
|
1068
|
-
const session = this.sessions[serverName];
|
|
1069
|
-
if (!session) {
|
|
1070
|
-
logger.warn(
|
|
1071
|
-
`No session exists for server ${serverName}, nothing to close`
|
|
1072
|
-
);
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
try {
|
|
1076
|
-
logger.debug(`Closing session for server ${serverName}`);
|
|
1077
|
-
await session.disconnect();
|
|
1078
|
-
} catch (e) {
|
|
1079
|
-
logger.error(`Error closing session for server '${serverName}': ${e}`);
|
|
1080
|
-
} finally {
|
|
1081
|
-
delete this.sessions[serverName];
|
|
1082
|
-
this.activeSessions = this.activeSessions.filter((n) => n !== serverName);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
async closeAllSessions() {
|
|
1086
|
-
const serverNames = Object.keys(this.sessions);
|
|
1087
|
-
const errors = [];
|
|
1088
|
-
for (const serverName of serverNames) {
|
|
1089
|
-
try {
|
|
1090
|
-
logger.debug(`Closing session for server ${serverName}`);
|
|
1091
|
-
await this.closeSession(serverName);
|
|
1092
|
-
} catch (e) {
|
|
1093
|
-
const errorMsg = `Failed to close session for server '${serverName}': ${e}`;
|
|
1094
|
-
logger.error(errorMsg);
|
|
1095
|
-
errors.push(errorMsg);
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
if (errors.length) {
|
|
1099
|
-
logger.error(
|
|
1100
|
-
`Encountered ${errors.length} errors while closing sessions`
|
|
1101
|
-
);
|
|
1102
|
-
} else {
|
|
1103
|
-
logger.debug("All sessions closed successfully");
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
|
-
// src/client/browser.ts
|
|
1109
|
-
var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
|
|
1110
|
-
static {
|
|
1111
|
-
__name(this, "BrowserMCPClient");
|
|
1112
|
-
}
|
|
1113
|
-
/**
|
|
1114
|
-
* Get the mcp-use package version.
|
|
1115
|
-
* Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
|
|
1116
|
-
*/
|
|
1117
|
-
static getPackageVersion() {
|
|
1118
|
-
return getPackageVersion();
|
|
1119
|
-
}
|
|
1120
|
-
constructor(config) {
|
|
1121
|
-
super(config);
|
|
1122
|
-
this._trackClientInit();
|
|
1123
|
-
}
|
|
1124
|
-
_trackClientInit() {
|
|
1125
|
-
const servers = Object.keys(this.config.mcpServers ?? {});
|
|
1126
|
-
Tel.getInstance().trackMCPClientInit({
|
|
1127
|
-
codeMode: false,
|
|
1128
|
-
// Browser client doesn't support code mode
|
|
1129
|
-
sandbox: false,
|
|
1130
|
-
// Sandbox not supported in browser
|
|
1131
|
-
allCallbacks: false,
|
|
1132
|
-
// Will be set per-server
|
|
1133
|
-
verify: false,
|
|
1134
|
-
servers,
|
|
1135
|
-
numServers: servers.length,
|
|
1136
|
-
isBrowser: true
|
|
1137
|
-
// Browser MCPClient
|
|
1138
|
-
}).catch(
|
|
1139
|
-
(e) => logger.debug(`Failed to track BrowserMCPClient init: ${e}`)
|
|
1140
|
-
);
|
|
1141
|
-
}
|
|
1142
|
-
static fromDict(cfg) {
|
|
1143
|
-
return new _BrowserMCPClient(cfg);
|
|
1144
|
-
}
|
|
1145
|
-
/**
|
|
1146
|
-
* Create a connector from server configuration (Browser version)
|
|
1147
|
-
* Supports HTTP and WebSocket connectors only
|
|
1148
|
-
*/
|
|
1149
|
-
createConnectorFromConfig(serverConfig) {
|
|
1150
|
-
const {
|
|
1151
|
-
url,
|
|
1152
|
-
transport,
|
|
1153
|
-
headers,
|
|
1154
|
-
authToken,
|
|
1155
|
-
authProvider,
|
|
1156
|
-
wrapTransport,
|
|
1157
|
-
clientOptions,
|
|
1158
|
-
samplingCallback,
|
|
1159
|
-
elicitationCallback
|
|
1160
|
-
} = serverConfig;
|
|
1161
|
-
if (!url) {
|
|
1162
|
-
throw new Error("Server URL is required");
|
|
1163
|
-
}
|
|
1164
|
-
const connectorOptions = {
|
|
1165
|
-
headers,
|
|
1166
|
-
authToken,
|
|
1167
|
-
authProvider,
|
|
1168
|
-
// ← Pass OAuth provider to connector
|
|
1169
|
-
wrapTransport,
|
|
1170
|
-
// ← Pass transport wrapper if provided
|
|
1171
|
-
clientOptions,
|
|
1172
|
-
// ← Pass client options (capabilities, etc.) to connector
|
|
1173
|
-
samplingCallback,
|
|
1174
|
-
// ← Pass sampling callback to connector
|
|
1175
|
-
elicitationCallback
|
|
1176
|
-
// ← Pass elicitation callback to connector
|
|
1177
|
-
};
|
|
1178
|
-
if (clientOptions) {
|
|
1179
|
-
console.log(
|
|
1180
|
-
"[BrowserMCPClient] Passing clientOptions to connector:",
|
|
1181
|
-
JSON.stringify(clientOptions, null, 2)
|
|
1182
|
-
);
|
|
1183
|
-
} else {
|
|
1184
|
-
console.warn(
|
|
1185
|
-
"[BrowserMCPClient] No clientOptions provided to connector!"
|
|
1186
|
-
);
|
|
1187
|
-
}
|
|
1188
|
-
if (transport === "websocket" || url.startsWith("ws://") || url.startsWith("wss://")) {
|
|
1189
|
-
return new WebSocketConnector(url, connectorOptions);
|
|
1190
|
-
} else if (transport === "http" || url.startsWith("http://") || url.startsWith("https://")) {
|
|
1191
|
-
return new HttpConnector(url, connectorOptions);
|
|
1192
|
-
} else {
|
|
1193
|
-
return new HttpConnector(url, connectorOptions);
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
};
|
|
1197
|
-
|
|
1198
900
|
export {
|
|
1199
901
|
MCPSession,
|
|
1200
902
|
BaseMCPClient,
|
|
1201
903
|
ConnectionManager,
|
|
1202
|
-
HttpConnector
|
|
1203
|
-
WebSocketConnector,
|
|
1204
|
-
BrowserMCPClient
|
|
904
|
+
HttpConnector
|
|
1205
905
|
};
|