mcp-use 1.11.0-canary.3 → 1.11.0-canary.5

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.
Files changed (45) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/{chunk-FDWI2WVM.js → chunk-454ZT2R7.js} +15 -91
  3. package/dist/{chunk-BONN23WU.js → chunk-52OY3IIW.js} +2 -2
  4. package/dist/chunk-6RVQ5RGR.js +12 -0
  5. package/dist/chunk-BAFXO6MT.js +101 -0
  6. package/dist/{chunk-TZ7SHSRY.js → chunk-FONZ4CWK.js} +1 -1
  7. package/dist/{chunk-WFPXUU4A.js → chunk-FQJ6Z3U6.js} +1 -1
  8. package/dist/{chunk-YIZWQ5PM.js → chunk-JRFJXT2T.js} +1 -1
  9. package/dist/{chunk-DKLRVWPJ.js → chunk-WK34REFK.js} +3 -8
  10. package/dist/{chunk-KZL3RCT6.js → chunk-ZP4QTLQC.js} +1419 -88
  11. package/dist/index.cjs +4745 -4443
  12. package/dist/index.js +26 -1035
  13. package/dist/src/agents/index.cjs +2881 -157
  14. package/dist/src/agents/index.d.ts +2 -0
  15. package/dist/src/agents/index.d.ts.map +1 -1
  16. package/dist/src/agents/index.js +6 -4
  17. package/dist/src/agents/mcp_agent.d.ts +59 -37
  18. package/dist/src/agents/mcp_agent.d.ts.map +1 -1
  19. package/dist/src/agents/remote.d.ts +25 -0
  20. package/dist/src/agents/remote.d.ts.map +1 -1
  21. package/dist/src/agents/types.d.ts +76 -0
  22. package/dist/src/agents/types.d.ts.map +1 -1
  23. package/dist/src/agents/utils/index.d.ts +1 -0
  24. package/dist/src/agents/utils/index.d.ts.map +1 -1
  25. package/dist/src/agents/utils/llm_provider.d.ts +53 -0
  26. package/dist/src/agents/utils/llm_provider.d.ts.map +1 -0
  27. package/dist/src/browser.cjs +1632 -201
  28. package/dist/src/browser.js +18 -7
  29. package/dist/src/client/base.d.ts +1 -0
  30. package/dist/src/client/base.d.ts.map +1 -1
  31. package/dist/src/client/prompts.js +4 -3
  32. package/dist/src/react/index.cjs +12 -3
  33. package/dist/src/react/index.js +5 -4
  34. package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
  35. package/dist/src/server/index.cjs +91 -64
  36. package/dist/src/server/index.js +93 -66
  37. package/dist/src/server/mcp-server.d.ts.map +1 -1
  38. package/dist/src/server/types/common.d.ts +26 -0
  39. package/dist/src/server/types/common.d.ts.map +1 -1
  40. package/dist/src/session.d.ts +2 -2
  41. package/dist/src/session.d.ts.map +1 -1
  42. package/dist/src/version.d.ts +1 -1
  43. package/dist/{tool-execution-helpers-HNASWGXY.js → tool-execution-helpers-3RAOCSJ4.js} +2 -2
  44. package/package.json +5 -4
  45. /package/dist/{chunk-EW4MJSHA.js → chunk-H4BZVTGK.js} +0 -0
@@ -35,9 +35,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
35
35
  async function getNodeModules() {
36
36
  if (typeof process !== "undefined" && process.platform) {
37
37
  try {
38
- const fs = await import("fs");
39
- const path = await import("path");
40
- return { fs: fs.default, path: path.default };
38
+ const fs2 = await import("fs");
39
+ const path2 = await import("path");
40
+ return { fs: fs2.default, path: path2.default };
41
41
  } catch {
42
42
  return { fs: null, path: null };
43
43
  }
@@ -1417,7 +1417,7 @@ __name(generateUUID, "generateUUID");
1417
1417
  init_logging();
1418
1418
 
1419
1419
  // src/version.ts
1420
- var VERSION = "1.11.0-canary.3";
1420
+ var VERSION = "1.11.0-canary.5";
1421
1421
  function getPackageVersion() {
1422
1422
  return VERSION;
1423
1423
  }
@@ -1738,26 +1738,26 @@ var Telemetry = class _Telemetry {
1738
1738
  * Get or create user ID from filesystem (Node.js/Bun)
1739
1739
  */
1740
1740
  _getUserIdFromFilesystem() {
1741
- const fs = require("fs");
1741
+ const fs2 = require("fs");
1742
1742
  const os = require("os");
1743
- const path = require("path");
1743
+ const path2 = require("path");
1744
1744
  if (!this._userIdPath) {
1745
- this._userIdPath = path.join(
1746
- this._getCacheHome(os, path),
1745
+ this._userIdPath = path2.join(
1746
+ this._getCacheHome(os, path2),
1747
1747
  "mcp_use_3",
1748
1748
  "telemetry_user_id"
1749
1749
  );
1750
1750
  }
1751
- const isFirstTime = !fs.existsSync(this._userIdPath);
1751
+ const isFirstTime = !fs2.existsSync(this._userIdPath);
1752
1752
  if (isFirstTime) {
1753
1753
  logger.debug(`Creating user ID path: ${this._userIdPath}`);
1754
- fs.mkdirSync(path.dirname(this._userIdPath), { recursive: true });
1754
+ fs2.mkdirSync(path2.dirname(this._userIdPath), { recursive: true });
1755
1755
  const newUserId = generateUUID();
1756
- fs.writeFileSync(this._userIdPath, newUserId);
1756
+ fs2.writeFileSync(this._userIdPath, newUserId);
1757
1757
  logger.debug(`User ID path created: ${this._userIdPath}`);
1758
1758
  return newUserId;
1759
1759
  }
1760
- return fs.readFileSync(this._userIdPath, "utf-8").trim();
1760
+ return fs2.readFileSync(this._userIdPath, "utf-8").trim();
1761
1761
  }
1762
1762
  /**
1763
1763
  * Get or create user ID from localStorage (Browser)
@@ -1776,9 +1776,9 @@ var Telemetry = class _Telemetry {
1776
1776
  return `session-${generateUUID()}`;
1777
1777
  }
1778
1778
  }
1779
- _getCacheHome(os, path) {
1779
+ _getCacheHome(os, path2) {
1780
1780
  const envVar = process.env.XDG_CACHE_HOME;
1781
- if (envVar && path.isAbsolute(envVar)) {
1781
+ if (envVar && path2.isAbsolute(envVar)) {
1782
1782
  return envVar;
1783
1783
  }
1784
1784
  const platform = process.platform;
@@ -1788,11 +1788,11 @@ var Telemetry = class _Telemetry {
1788
1788
  if (appdata) {
1789
1789
  return appdata;
1790
1790
  }
1791
- return path.join(homeDir, "AppData", "Local");
1791
+ return path2.join(homeDir, "AppData", "Local");
1792
1792
  } else if (platform === "darwin") {
1793
- return path.join(homeDir, "Library", "Caches");
1793
+ return path2.join(homeDir, "Library", "Caches");
1794
1794
  } else {
1795
- return path.join(homeDir, ".cache");
1795
+ return path2.join(homeDir, ".cache");
1796
1796
  }
1797
1797
  }
1798
1798
  async capture(event) {
@@ -1866,12 +1866,12 @@ var Telemetry = class _Telemetry {
1866
1866
  return;
1867
1867
  }
1868
1868
  try {
1869
- const fs = require("fs");
1870
- const path = require("path");
1869
+ const fs2 = require("fs");
1870
+ const path2 = require("path");
1871
1871
  const os = require("os");
1872
1872
  if (!this._versionDownloadPath) {
1873
- this._versionDownloadPath = path.join(
1874
- this._getCacheHome(os, path),
1873
+ this._versionDownloadPath = path2.join(
1874
+ this._getCacheHome(os, path2),
1875
1875
  "mcp_use",
1876
1876
  "download_version"
1877
1877
  );
@@ -1879,19 +1879,19 @@ var Telemetry = class _Telemetry {
1879
1879
  const currentVersion = getPackageVersion();
1880
1880
  let shouldTrack = false;
1881
1881
  let firstDownload = false;
1882
- if (!fs.existsSync(this._versionDownloadPath)) {
1882
+ if (!fs2.existsSync(this._versionDownloadPath)) {
1883
1883
  shouldTrack = true;
1884
1884
  firstDownload = true;
1885
- fs.mkdirSync(path.dirname(this._versionDownloadPath), {
1885
+ fs2.mkdirSync(path2.dirname(this._versionDownloadPath), {
1886
1886
  recursive: true
1887
1887
  });
1888
- fs.writeFileSync(this._versionDownloadPath, currentVersion);
1888
+ fs2.writeFileSync(this._versionDownloadPath, currentVersion);
1889
1889
  } else {
1890
- const savedVersion = fs.readFileSync(this._versionDownloadPath, "utf-8").trim();
1890
+ const savedVersion = fs2.readFileSync(this._versionDownloadPath, "utf-8").trim();
1891
1891
  if (currentVersion > savedVersion) {
1892
1892
  shouldTrack = true;
1893
1893
  firstDownload = false;
1894
- fs.writeFileSync(this._versionDownloadPath, currentVersion);
1894
+ fs2.writeFileSync(this._versionDownloadPath, currentVersion);
1895
1895
  }
1896
1896
  }
1897
1897
  if (shouldTrack) {
@@ -2084,6 +2084,480 @@ var Telemetry = class _Telemetry {
2084
2084
  }
2085
2085
  }
2086
2086
  };
2087
+ var Tel = Telemetry;
2088
+
2089
+ // src/connectors/base.ts
2090
+ var BaseConnector = class {
2091
+ static {
2092
+ __name(this, "BaseConnector");
2093
+ }
2094
+ client = null;
2095
+ connectionManager = null;
2096
+ toolsCache = null;
2097
+ capabilitiesCache = null;
2098
+ serverInfoCache = null;
2099
+ connected = false;
2100
+ opts;
2101
+ notificationHandlers = [];
2102
+ rootsCache = [];
2103
+ constructor(opts = {}) {
2104
+ this.opts = opts;
2105
+ if (opts.roots) {
2106
+ this.rootsCache = [...opts.roots];
2107
+ }
2108
+ }
2109
+ /**
2110
+ * Track connector initialization event
2111
+ * Should be called by subclasses after successful connection
2112
+ */
2113
+ trackConnectorInit(data) {
2114
+ const connectorType = this.constructor.name;
2115
+ Telemetry.getInstance().trackConnectorInit({
2116
+ connectorType,
2117
+ ...data
2118
+ }).catch((e) => logger.debug(`Failed to track connector init: ${e}`));
2119
+ }
2120
+ /**
2121
+ * Register a handler for server notifications
2122
+ *
2123
+ * @param handler - Function to call when a notification is received
2124
+ *
2125
+ * @example
2126
+ * ```typescript
2127
+ * connector.onNotification((notification) => {
2128
+ * console.log(`Received: ${notification.method}`, notification.params);
2129
+ * });
2130
+ * ```
2131
+ */
2132
+ onNotification(handler) {
2133
+ this.notificationHandlers.push(handler);
2134
+ if (this.client) {
2135
+ this.setupNotificationHandler();
2136
+ }
2137
+ }
2138
+ /**
2139
+ * Internal: wire notification handlers to the SDK client
2140
+ * Includes automatic handling for list_changed notifications per MCP spec
2141
+ */
2142
+ setupNotificationHandler() {
2143
+ if (!this.client) return;
2144
+ this.client.fallbackNotificationHandler = async (notification) => {
2145
+ switch (notification.method) {
2146
+ case "notifications/tools/list_changed":
2147
+ await this.refreshToolsCache();
2148
+ break;
2149
+ case "notifications/resources/list_changed":
2150
+ await this.onResourcesListChanged();
2151
+ break;
2152
+ case "notifications/prompts/list_changed":
2153
+ await this.onPromptsListChanged();
2154
+ break;
2155
+ default:
2156
+ break;
2157
+ }
2158
+ for (const handler of this.notificationHandlers) {
2159
+ try {
2160
+ await handler(notification);
2161
+ } catch (err) {
2162
+ logger.error("Error in notification handler:", err);
2163
+ }
2164
+ }
2165
+ };
2166
+ }
2167
+ /**
2168
+ * Auto-refresh tools cache when server sends tools/list_changed notification
2169
+ */
2170
+ async refreshToolsCache() {
2171
+ if (!this.client) return;
2172
+ try {
2173
+ logger.debug(
2174
+ "[Auto] Refreshing tools cache due to list_changed notification"
2175
+ );
2176
+ const result = await this.client.listTools();
2177
+ this.toolsCache = result.tools ?? [];
2178
+ logger.debug(
2179
+ `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
2180
+ );
2181
+ } catch (err) {
2182
+ logger.warn("[Auto] Failed to refresh tools cache:", err);
2183
+ }
2184
+ }
2185
+ /**
2186
+ * Called when server sends resources/list_changed notification
2187
+ * Resources aren't cached by default, but we log for user awareness
2188
+ */
2189
+ async onResourcesListChanged() {
2190
+ logger.debug(
2191
+ "[Auto] Resources list changed - clients should re-fetch if needed"
2192
+ );
2193
+ }
2194
+ /**
2195
+ * Called when server sends prompts/list_changed notification
2196
+ * Prompts aren't cached by default, but we log for user awareness
2197
+ */
2198
+ async onPromptsListChanged() {
2199
+ logger.debug(
2200
+ "[Auto] Prompts list changed - clients should re-fetch if needed"
2201
+ );
2202
+ }
2203
+ /**
2204
+ * Set roots and notify the server.
2205
+ * Roots represent directories or files that the client has access to.
2206
+ *
2207
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
2208
+ *
2209
+ * @example
2210
+ * ```typescript
2211
+ * await connector.setRoots([
2212
+ * { uri: "file:///home/user/project", name: "My Project" },
2213
+ * { uri: "file:///home/user/data" }
2214
+ * ]);
2215
+ * ```
2216
+ */
2217
+ async setRoots(roots) {
2218
+ this.rootsCache = [...roots];
2219
+ if (this.client) {
2220
+ logger.debug(
2221
+ `Sending roots/list_changed notification with ${roots.length} root(s)`
2222
+ );
2223
+ await this.client.sendRootsListChanged();
2224
+ }
2225
+ }
2226
+ /**
2227
+ * Get the current roots.
2228
+ */
2229
+ getRoots() {
2230
+ return [...this.rootsCache];
2231
+ }
2232
+ /**
2233
+ * Internal: set up roots/list request handler.
2234
+ * This is called after the client connects to register the handler for server requests.
2235
+ */
2236
+ setupRootsHandler() {
2237
+ if (!this.client) return;
2238
+ this.client.setRequestHandler(
2239
+ import_types.ListRootsRequestSchema,
2240
+ async (_request, _extra) => {
2241
+ logger.debug(
2242
+ `Server requested roots list, returning ${this.rootsCache.length} root(s)`
2243
+ );
2244
+ return { roots: this.rootsCache };
2245
+ }
2246
+ );
2247
+ }
2248
+ /**
2249
+ * Internal: set up sampling/createMessage request handler.
2250
+ * This is called after the client connects to register the handler for sampling requests.
2251
+ */
2252
+ setupSamplingHandler() {
2253
+ if (!this.client) {
2254
+ logger.debug("setupSamplingHandler: No client available");
2255
+ return;
2256
+ }
2257
+ if (!this.opts.samplingCallback) {
2258
+ logger.debug("setupSamplingHandler: No sampling callback provided");
2259
+ return;
2260
+ }
2261
+ logger.debug("setupSamplingHandler: Setting up sampling request handler");
2262
+ this.client.setRequestHandler(
2263
+ import_types.CreateMessageRequestSchema,
2264
+ async (request, _extra) => {
2265
+ logger.debug("Server requested sampling, forwarding to callback");
2266
+ return await this.opts.samplingCallback(request.params);
2267
+ }
2268
+ );
2269
+ logger.debug(
2270
+ "setupSamplingHandler: Sampling handler registered successfully"
2271
+ );
2272
+ }
2273
+ /**
2274
+ * Internal: set up elicitation/create request handler.
2275
+ * This is called after the client connects to register the handler for elicitation requests.
2276
+ */
2277
+ setupElicitationHandler() {
2278
+ if (!this.client) {
2279
+ logger.debug("setupElicitationHandler: No client available");
2280
+ return;
2281
+ }
2282
+ if (!this.opts.elicitationCallback) {
2283
+ logger.debug("setupElicitationHandler: No elicitation callback provided");
2284
+ return;
2285
+ }
2286
+ logger.debug(
2287
+ "setupElicitationHandler: Setting up elicitation request handler"
2288
+ );
2289
+ this.client.setRequestHandler(
2290
+ import_types.ElicitRequestSchema,
2291
+ async (request, _extra) => {
2292
+ logger.debug("Server requested elicitation, forwarding to callback");
2293
+ return await this.opts.elicitationCallback(request.params);
2294
+ }
2295
+ );
2296
+ logger.debug(
2297
+ "setupElicitationHandler: Elicitation handler registered successfully"
2298
+ );
2299
+ }
2300
+ /** Disconnect and release resources. */
2301
+ async disconnect() {
2302
+ if (!this.connected) {
2303
+ logger.debug("Not connected to MCP implementation");
2304
+ return;
2305
+ }
2306
+ logger.debug("Disconnecting from MCP implementation");
2307
+ await this.cleanupResources();
2308
+ this.connected = false;
2309
+ logger.debug("Disconnected from MCP implementation");
2310
+ }
2311
+ /** Check if the client is connected */
2312
+ get isClientConnected() {
2313
+ return this.client != null;
2314
+ }
2315
+ /**
2316
+ * Initialise the MCP session **after** `connect()` has succeeded.
2317
+ *
2318
+ * In the SDK, `Client.connect(transport)` automatically performs the
2319
+ * protocol‑level `initialize` handshake, so we only need to cache the list of
2320
+ * tools and expose some server info.
2321
+ */
2322
+ async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
2323
+ if (!this.client) {
2324
+ throw new Error("MCP client is not connected");
2325
+ }
2326
+ logger.debug("Caching server capabilities & tools");
2327
+ const capabilities = this.client.getServerCapabilities();
2328
+ this.capabilitiesCache = capabilities || null;
2329
+ const serverInfo = this.client.getServerVersion();
2330
+ this.serverInfoCache = serverInfo || null;
2331
+ const listToolsRes = await this.client.listTools(
2332
+ void 0,
2333
+ defaultRequestOptions
2334
+ );
2335
+ this.toolsCache = listToolsRes.tools ?? [];
2336
+ logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
2337
+ logger.debug("Server capabilities:", capabilities);
2338
+ logger.debug("Server info:", serverInfo);
2339
+ return capabilities;
2340
+ }
2341
+ /** Lazily expose the cached tools list. */
2342
+ get tools() {
2343
+ if (!this.toolsCache) {
2344
+ throw new Error("MCP client is not initialized; call initialize() first");
2345
+ }
2346
+ return this.toolsCache;
2347
+ }
2348
+ /** Expose cached server capabilities. */
2349
+ get serverCapabilities() {
2350
+ return this.capabilitiesCache || {};
2351
+ }
2352
+ /** Expose cached server info. */
2353
+ get serverInfo() {
2354
+ return this.serverInfoCache;
2355
+ }
2356
+ /** Call a tool on the server. */
2357
+ async callTool(name, args, options) {
2358
+ if (!this.client) {
2359
+ throw new Error("MCP client is not connected");
2360
+ }
2361
+ const enhancedOptions = options ? { ...options } : void 0;
2362
+ if (enhancedOptions?.resetTimeoutOnProgress && !enhancedOptions.onprogress) {
2363
+ enhancedOptions.onprogress = () => {
2364
+ };
2365
+ logger.debug(
2366
+ `[BaseConnector] Added onprogress callback for tool '${name}' to enable progressToken`
2367
+ );
2368
+ }
2369
+ logger.debug(`Calling tool '${name}' with args`, args);
2370
+ const res = await this.client.callTool(
2371
+ { name, arguments: args },
2372
+ void 0,
2373
+ enhancedOptions
2374
+ );
2375
+ logger.debug(`Tool '${name}' returned`, res);
2376
+ return res;
2377
+ }
2378
+ /**
2379
+ * List all available tools from the MCP server.
2380
+ * This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
2381
+ *
2382
+ * @param options - Optional request options
2383
+ * @returns Array of available tools
2384
+ */
2385
+ async listTools(options) {
2386
+ if (!this.client) {
2387
+ throw new Error("MCP client is not connected");
2388
+ }
2389
+ const result = await this.client.listTools(void 0, options);
2390
+ return result.tools ?? [];
2391
+ }
2392
+ /**
2393
+ * List resources from the server with optional pagination
2394
+ *
2395
+ * @param cursor - Optional cursor for pagination
2396
+ * @param options - Request options
2397
+ * @returns Resource list with optional nextCursor for pagination
2398
+ */
2399
+ async listResources(cursor, options) {
2400
+ if (!this.client) {
2401
+ throw new Error("MCP client is not connected");
2402
+ }
2403
+ logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
2404
+ return await this.client.listResources({ cursor }, options);
2405
+ }
2406
+ /**
2407
+ * List all resources from the server, automatically handling pagination
2408
+ *
2409
+ * @param options - Request options
2410
+ * @returns Complete list of all resources
2411
+ */
2412
+ async listAllResources(options) {
2413
+ if (!this.client) {
2414
+ throw new Error("MCP client is not connected");
2415
+ }
2416
+ if (!this.capabilitiesCache?.resources) {
2417
+ logger.debug("Server does not advertise resources capability, skipping");
2418
+ return { resources: [] };
2419
+ }
2420
+ try {
2421
+ logger.debug("Listing all resources (with auto-pagination)");
2422
+ const allResources = [];
2423
+ let cursor = void 0;
2424
+ do {
2425
+ const result = await this.client.listResources({ cursor }, options);
2426
+ allResources.push(...result.resources || []);
2427
+ cursor = result.nextCursor;
2428
+ } while (cursor);
2429
+ return { resources: allResources };
2430
+ } catch (err) {
2431
+ const error = err;
2432
+ if (error.code === -32601) {
2433
+ logger.debug("Server advertised resources but method not found");
2434
+ return { resources: [] };
2435
+ }
2436
+ throw err;
2437
+ }
2438
+ }
2439
+ /**
2440
+ * List resource templates from the server
2441
+ *
2442
+ * @param options - Request options
2443
+ * @returns List of available resource templates
2444
+ */
2445
+ async listResourceTemplates(options) {
2446
+ if (!this.client) {
2447
+ throw new Error("MCP client is not connected");
2448
+ }
2449
+ logger.debug("Listing resource templates");
2450
+ return await this.client.listResourceTemplates(void 0, options);
2451
+ }
2452
+ /** Read a resource by URI. */
2453
+ async readResource(uri, options) {
2454
+ if (!this.client) {
2455
+ throw new Error("MCP client is not connected");
2456
+ }
2457
+ logger.debug(`Reading resource ${uri}`);
2458
+ const res = await this.client.readResource({ uri }, options);
2459
+ return res;
2460
+ }
2461
+ /**
2462
+ * Subscribe to resource updates
2463
+ *
2464
+ * @param uri - URI of the resource to subscribe to
2465
+ * @param options - Request options
2466
+ */
2467
+ async subscribeToResource(uri, options) {
2468
+ if (!this.client) {
2469
+ throw new Error("MCP client is not connected");
2470
+ }
2471
+ logger.debug(`Subscribing to resource: ${uri}`);
2472
+ return await this.client.subscribeResource({ uri }, options);
2473
+ }
2474
+ /**
2475
+ * Unsubscribe from resource updates
2476
+ *
2477
+ * @param uri - URI of the resource to unsubscribe from
2478
+ * @param options - Request options
2479
+ */
2480
+ async unsubscribeFromResource(uri, options) {
2481
+ if (!this.client) {
2482
+ throw new Error("MCP client is not connected");
2483
+ }
2484
+ logger.debug(`Unsubscribing from resource: ${uri}`);
2485
+ return await this.client.unsubscribeResource({ uri }, options);
2486
+ }
2487
+ async listPrompts() {
2488
+ if (!this.client) {
2489
+ throw new Error("MCP client is not connected");
2490
+ }
2491
+ if (!this.capabilitiesCache?.prompts) {
2492
+ logger.debug("Server does not advertise prompts capability, skipping");
2493
+ return { prompts: [] };
2494
+ }
2495
+ try {
2496
+ logger.debug("Listing prompts");
2497
+ return await this.client.listPrompts();
2498
+ } catch (err) {
2499
+ const error = err;
2500
+ if (error.code === -32601) {
2501
+ logger.debug("Server advertised prompts but method not found");
2502
+ return { prompts: [] };
2503
+ }
2504
+ throw err;
2505
+ }
2506
+ }
2507
+ async getPrompt(name, args) {
2508
+ if (!this.client) {
2509
+ throw new Error("MCP client is not connected");
2510
+ }
2511
+ logger.debug(`Getting prompt ${name}`);
2512
+ return await this.client.getPrompt({ name, arguments: args });
2513
+ }
2514
+ /** Send a raw request through the client. */
2515
+ async request(method, params = null, options) {
2516
+ if (!this.client) {
2517
+ throw new Error("MCP client is not connected");
2518
+ }
2519
+ logger.debug(`Sending raw request '${method}' with params`, params);
2520
+ return await this.client.request(
2521
+ { method, params: params ?? {} },
2522
+ void 0,
2523
+ options
2524
+ );
2525
+ }
2526
+ /**
2527
+ * Helper to tear down the client & connection manager safely.
2528
+ */
2529
+ async cleanupResources() {
2530
+ const issues = [];
2531
+ if (this.client) {
2532
+ try {
2533
+ if (typeof this.client.close === "function") {
2534
+ await this.client.close();
2535
+ }
2536
+ } catch (e) {
2537
+ const msg = `Error closing client: ${e}`;
2538
+ logger.warn(msg);
2539
+ issues.push(msg);
2540
+ } finally {
2541
+ this.client = null;
2542
+ }
2543
+ }
2544
+ if (this.connectionManager) {
2545
+ try {
2546
+ await this.connectionManager.stop();
2547
+ } catch (e) {
2548
+ const msg = `Error stopping connection manager: ${e}`;
2549
+ logger.warn(msg);
2550
+ issues.push(msg);
2551
+ } finally {
2552
+ this.connectionManager = null;
2553
+ }
2554
+ }
2555
+ this.toolsCache = null;
2556
+ if (issues.length) {
2557
+ logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
2558
+ }
2559
+ }
2560
+ };
2087
2561
 
2088
2562
  // src/client/connectors/codeMode.ts
2089
2563
  var CODE_MODE_AGENT_PROMPT = `
@@ -2173,6 +2647,110 @@ return {
2173
2647
 
2174
2648
  Remember: Always discover and understand available tools before attempting to use them in code execution.
2175
2649
  `;
2650
+ var CodeModeConnector = class extends BaseConnector {
2651
+ static {
2652
+ __name(this, "CodeModeConnector");
2653
+ }
2654
+ mcpClient;
2655
+ _tools;
2656
+ constructor(client) {
2657
+ super();
2658
+ this.mcpClient = client;
2659
+ this.connected = true;
2660
+ this._tools = this._createToolsList();
2661
+ }
2662
+ async connect() {
2663
+ this.connected = true;
2664
+ }
2665
+ async disconnect() {
2666
+ this.connected = false;
2667
+ }
2668
+ get publicIdentifier() {
2669
+ return { name: "code_mode", version: "1.0.0" };
2670
+ }
2671
+ _createToolsList() {
2672
+ return [
2673
+ {
2674
+ name: "execute_code",
2675
+ description: "Execute JavaScript/TypeScript code with access to MCP tools. This is the PRIMARY way to interact with MCP servers in code mode. Write code that discovers tools using search_tools(), calls tools as async functions (e.g., await github.get_pull_request(...)), processes data efficiently, and returns results. Use 'await' for async operations and 'return' to return values. Available in code: search_tools(), __tool_namespaces, and server.tool_name() functions.",
2676
+ inputSchema: {
2677
+ type: "object",
2678
+ properties: {
2679
+ code: {
2680
+ type: "string",
2681
+ description: "JavaScript/TypeScript code to execute. Use 'await' for async operations. Use 'return' to return a value. Available: search_tools(), server.tool_name(), __tool_namespaces"
2682
+ },
2683
+ timeout: {
2684
+ type: "number",
2685
+ description: "Execution timeout in milliseconds",
2686
+ default: 3e4
2687
+ }
2688
+ },
2689
+ required: ["code"]
2690
+ }
2691
+ },
2692
+ {
2693
+ name: "search_tools",
2694
+ description: "Search and discover available MCP tools across all servers. Use this to find out what tools are available before writing code. Returns tool information including names, descriptions, and schemas. Can filter by query and control detail level.",
2695
+ inputSchema: {
2696
+ type: "object",
2697
+ properties: {
2698
+ query: {
2699
+ type: "string",
2700
+ description: "Search query to filter tools by name or description",
2701
+ default: ""
2702
+ },
2703
+ detail_level: {
2704
+ type: "string",
2705
+ description: "Detail level: 'names', 'descriptions', or 'full'",
2706
+ enum: ["names", "descriptions", "full"],
2707
+ default: "full"
2708
+ }
2709
+ }
2710
+ }
2711
+ }
2712
+ ];
2713
+ }
2714
+ // Override tools getter to return static list immediately
2715
+ get tools() {
2716
+ return this._tools;
2717
+ }
2718
+ async initialize() {
2719
+ this.toolsCache = this._tools;
2720
+ return { capabilities: {}, version: "1.0.0" };
2721
+ }
2722
+ async callTool(name, args) {
2723
+ if (name === "execute_code") {
2724
+ const code = args.code;
2725
+ const timeout = args.timeout || 3e4;
2726
+ const result = await this.mcpClient.executeCode(code, timeout);
2727
+ return {
2728
+ content: [
2729
+ {
2730
+ type: "text",
2731
+ text: JSON.stringify(result)
2732
+ }
2733
+ ]
2734
+ };
2735
+ } else if (name === "search_tools") {
2736
+ const query = args.query || "";
2737
+ const detailLevel = args.detail_level;
2738
+ const result = await this.mcpClient.searchTools(
2739
+ query,
2740
+ detailLevel && detailLevel in ["names", "descriptions", "full"] ? detailLevel : "full"
2741
+ );
2742
+ return {
2743
+ content: [
2744
+ {
2745
+ type: "text",
2746
+ text: JSON.stringify(result)
2747
+ }
2748
+ ]
2749
+ };
2750
+ }
2751
+ throw new Error(`Unknown tool: ${name}`);
2752
+ }
2753
+ };
2176
2754
 
2177
2755
  // src/client/prompts.ts
2178
2756
  var PROMPTS = {
@@ -3179,63 +3757,1933 @@ var LangChainAdapter = class extends BaseAdapter {
3179
3757
  return JSON.stringify(content);
3180
3758
  }).join("\n");
3181
3759
  }
3182
- return "Resource is empty or unavailable";
3183
- } catch (err) {
3184
- logger.error(`Error reading resource: ${err.message}`);
3185
- return `Error reading resource: ${String(err)}`;
3760
+ return "Resource is empty or unavailable";
3761
+ } catch (err) {
3762
+ logger.error(`Error reading resource: ${err.message}`);
3763
+ return `Error reading resource: ${String(err)}`;
3764
+ }
3765
+ }, "func")
3766
+ });
3767
+ return tool;
3768
+ }
3769
+ /**
3770
+ * Convert a single MCP prompt into a LangChainJS structured tool.
3771
+ * The resulting tool executes getPrompt on the connector with the prompt's name
3772
+ * and the user-provided arguments (if any).
3773
+ */
3774
+ convertPrompt(mcpPrompt, connector) {
3775
+ let argsSchema = import_zod2.z.object({}).optional();
3776
+ if (mcpPrompt.arguments && mcpPrompt.arguments.length > 0) {
3777
+ const schemaFields = {};
3778
+ for (const arg of mcpPrompt.arguments) {
3779
+ const zodType = import_zod2.z.string();
3780
+ if (arg.required !== false) {
3781
+ schemaFields[arg.name] = zodType;
3782
+ } else {
3783
+ schemaFields[arg.name] = zodType.optional();
3784
+ }
3785
+ }
3786
+ argsSchema = Object.keys(schemaFields).length > 0 ? import_zod2.z.object(schemaFields) : import_zod2.z.object({}).optional();
3787
+ }
3788
+ const tool = new import_tools.DynamicStructuredTool({
3789
+ name: mcpPrompt.name,
3790
+ description: mcpPrompt.description || "",
3791
+ schema: argsSchema,
3792
+ func: /* @__PURE__ */ __name(async (input) => {
3793
+ logger.debug(
3794
+ `Prompt tool: "${mcpPrompt.name}" called with args: ${JSON.stringify(input)}`
3795
+ );
3796
+ try {
3797
+ const result = await connector.getPrompt(mcpPrompt.name, input);
3798
+ if (result.messages && result.messages.length > 0) {
3799
+ return result.messages.map((msg) => {
3800
+ if (typeof msg === "string") {
3801
+ return msg;
3802
+ }
3803
+ if (msg.content) {
3804
+ return typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
3805
+ }
3806
+ return JSON.stringify(msg);
3807
+ }).join("\n");
3808
+ }
3809
+ return "Prompt returned no messages";
3810
+ } catch (err) {
3811
+ logger.error(`Error getting prompt: ${err.message}`);
3812
+ return `Error getting prompt: ${String(err)}`;
3813
+ }
3814
+ }, "func")
3815
+ });
3816
+ return tool;
3817
+ }
3818
+ };
3819
+
3820
+ // src/client.ts
3821
+ var import_node_fs2 = __toESM(require("fs"), 1);
3822
+ var import_node_path = __toESM(require("path"), 1);
3823
+
3824
+ // src/client/base.ts
3825
+ init_logging();
3826
+
3827
+ // src/session.ts
3828
+ var MCPSession = class {
3829
+ static {
3830
+ __name(this, "MCPSession");
3831
+ }
3832
+ connector;
3833
+ autoConnect;
3834
+ constructor(connector, autoConnect = true) {
3835
+ this.connector = connector;
3836
+ this.autoConnect = autoConnect;
3837
+ }
3838
+ async connect() {
3839
+ await this.connector.connect();
3840
+ }
3841
+ async disconnect() {
3842
+ await this.connector.disconnect();
3843
+ }
3844
+ async initialize() {
3845
+ if (!this.isConnected && this.autoConnect) {
3846
+ await this.connect();
3847
+ }
3848
+ await this.connector.initialize();
3849
+ }
3850
+ get isConnected() {
3851
+ return this.connector && this.connector.isClientConnected;
3852
+ }
3853
+ /**
3854
+ * Register an event handler for session events
3855
+ *
3856
+ * @param event - The event type to listen for
3857
+ * @param handler - The handler function to call when the event occurs
3858
+ *
3859
+ * @example
3860
+ * ```typescript
3861
+ * session.on("notification", async (notification) => {
3862
+ * console.log(`Received: ${notification.method}`, notification.params);
3863
+ *
3864
+ * if (notification.method === "notifications/tools/list_changed") {
3865
+ * // Refresh tools list
3866
+ * }
3867
+ * });
3868
+ * ```
3869
+ */
3870
+ on(event, handler) {
3871
+ if (event === "notification") {
3872
+ this.connector.onNotification(handler);
3873
+ }
3874
+ }
3875
+ /**
3876
+ * Set roots and notify the server.
3877
+ * Roots represent directories or files that the client has access to.
3878
+ *
3879
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
3880
+ *
3881
+ * @example
3882
+ * ```typescript
3883
+ * await session.setRoots([
3884
+ * { uri: "file:///home/user/project", name: "My Project" },
3885
+ * { uri: "file:///home/user/data" }
3886
+ * ]);
3887
+ * ```
3888
+ */
3889
+ async setRoots(roots) {
3890
+ return this.connector.setRoots(roots);
3891
+ }
3892
+ /**
3893
+ * Get the current roots.
3894
+ */
3895
+ getRoots() {
3896
+ return this.connector.getRoots();
3897
+ }
3898
+ /**
3899
+ * Get the cached list of tools from the server.
3900
+ *
3901
+ * @returns Array of available tools
3902
+ *
3903
+ * @example
3904
+ * ```typescript
3905
+ * const tools = session.tools;
3906
+ * console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
3907
+ * ```
3908
+ */
3909
+ get tools() {
3910
+ return this.connector.tools;
3911
+ }
3912
+ /**
3913
+ * List all available tools from the MCP server.
3914
+ * This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
3915
+ *
3916
+ * @param options - Optional request options
3917
+ * @returns Array of available tools
3918
+ *
3919
+ * @example
3920
+ * ```typescript
3921
+ * const tools = await session.listTools();
3922
+ * console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
3923
+ * ```
3924
+ */
3925
+ async listTools(options) {
3926
+ return this.connector.listTools(options);
3927
+ }
3928
+ /**
3929
+ * Get the server capabilities advertised during initialization.
3930
+ *
3931
+ * @returns Server capabilities object
3932
+ */
3933
+ get serverCapabilities() {
3934
+ return this.connector.serverCapabilities;
3935
+ }
3936
+ /**
3937
+ * Get the server information (name and version).
3938
+ *
3939
+ * @returns Server info object or null if not available
3940
+ */
3941
+ get serverInfo() {
3942
+ return this.connector.serverInfo;
3943
+ }
3944
+ /**
3945
+ * Call a tool on the server.
3946
+ *
3947
+ * @param name - Name of the tool to call
3948
+ * @param args - Arguments to pass to the tool (defaults to empty object)
3949
+ * @param options - Optional request options (timeout, progress handlers, etc.)
3950
+ * @returns Result from the tool execution
3951
+ *
3952
+ * @example
3953
+ * ```typescript
3954
+ * const result = await session.callTool("add", { a: 5, b: 3 });
3955
+ * console.log(`Result: ${result.content[0].text}`);
3956
+ * ```
3957
+ */
3958
+ async callTool(name, args = {}, options) {
3959
+ return this.connector.callTool(name, args, options);
3960
+ }
3961
+ /**
3962
+ * List resources from the server with optional pagination.
3963
+ *
3964
+ * @param cursor - Optional cursor for pagination
3965
+ * @param options - Request options
3966
+ * @returns Resource list with optional nextCursor for pagination
3967
+ *
3968
+ * @example
3969
+ * ```typescript
3970
+ * const result = await session.listResources();
3971
+ * console.log(`Found ${result.resources.length} resources`);
3972
+ * ```
3973
+ */
3974
+ async listResources(cursor, options) {
3975
+ return this.connector.listResources(cursor, options);
3976
+ }
3977
+ /**
3978
+ * List all resources from the server, automatically handling pagination.
3979
+ *
3980
+ * @param options - Request options
3981
+ * @returns Complete list of all resources
3982
+ *
3983
+ * @example
3984
+ * ```typescript
3985
+ * const result = await session.listAllResources();
3986
+ * console.log(`Total resources: ${result.resources.length}`);
3987
+ * ```
3988
+ */
3989
+ async listAllResources(options) {
3990
+ return this.connector.listAllResources(options);
3991
+ }
3992
+ /**
3993
+ * List resource templates from the server.
3994
+ *
3995
+ * @param options - Request options
3996
+ * @returns List of available resource templates
3997
+ *
3998
+ * @example
3999
+ * ```typescript
4000
+ * const result = await session.listResourceTemplates();
4001
+ * console.log(`Available templates: ${result.resourceTemplates.length}`);
4002
+ * ```
4003
+ */
4004
+ async listResourceTemplates(options) {
4005
+ return this.connector.listResourceTemplates(options);
4006
+ }
4007
+ /**
4008
+ * Read a resource by URI.
4009
+ *
4010
+ * @param uri - URI of the resource to read
4011
+ * @param options - Request options
4012
+ * @returns Resource content
4013
+ *
4014
+ * @example
4015
+ * ```typescript
4016
+ * const resource = await session.readResource("file:///path/to/file.txt");
4017
+ * console.log(resource.contents);
4018
+ * ```
4019
+ */
4020
+ async readResource(uri, options) {
4021
+ return this.connector.readResource(uri, options);
4022
+ }
4023
+ /**
4024
+ * Subscribe to resource updates.
4025
+ *
4026
+ * @param uri - URI of the resource to subscribe to
4027
+ * @param options - Request options
4028
+ *
4029
+ * @example
4030
+ * ```typescript
4031
+ * await session.subscribeToResource("file:///path/to/file.txt");
4032
+ * // Now you'll receive notifications when this resource changes
4033
+ * ```
4034
+ */
4035
+ async subscribeToResource(uri, options) {
4036
+ return this.connector.subscribeToResource(uri, options);
4037
+ }
4038
+ /**
4039
+ * Unsubscribe from resource updates.
4040
+ *
4041
+ * @param uri - URI of the resource to unsubscribe from
4042
+ * @param options - Request options
4043
+ *
4044
+ * @example
4045
+ * ```typescript
4046
+ * await session.unsubscribeFromResource("file:///path/to/file.txt");
4047
+ * ```
4048
+ */
4049
+ async unsubscribeFromResource(uri, options) {
4050
+ return this.connector.unsubscribeFromResource(uri, options);
4051
+ }
4052
+ /**
4053
+ * List available prompts from the server.
4054
+ *
4055
+ * @returns List of available prompts
4056
+ *
4057
+ * @example
4058
+ * ```typescript
4059
+ * const result = await session.listPrompts();
4060
+ * console.log(`Available prompts: ${result.prompts.length}`);
4061
+ * ```
4062
+ */
4063
+ async listPrompts() {
4064
+ return this.connector.listPrompts();
4065
+ }
4066
+ /**
4067
+ * Get a specific prompt with arguments.
4068
+ *
4069
+ * @param name - Name of the prompt to get
4070
+ * @param args - Arguments for the prompt
4071
+ * @returns Prompt result
4072
+ *
4073
+ * @example
4074
+ * ```typescript
4075
+ * const prompt = await session.getPrompt("greeting", { name: "Alice" });
4076
+ * console.log(prompt.messages);
4077
+ * ```
4078
+ */
4079
+ async getPrompt(name, args) {
4080
+ return this.connector.getPrompt(name, args);
4081
+ }
4082
+ /**
4083
+ * Send a raw request through the client.
4084
+ *
4085
+ * @param method - MCP method name
4086
+ * @param params - Request parameters
4087
+ * @param options - Request options
4088
+ * @returns Response from the server
4089
+ *
4090
+ * @example
4091
+ * ```typescript
4092
+ * const result = await session.request("custom/method", { key: "value" });
4093
+ * ```
4094
+ */
4095
+ async request(method, params = null, options) {
4096
+ return this.connector.request(method, params, options);
4097
+ }
4098
+ };
4099
+
4100
+ // src/client/base.ts
4101
+ var BaseMCPClient = class {
4102
+ static {
4103
+ __name(this, "BaseMCPClient");
4104
+ }
4105
+ config = {};
4106
+ sessions = {};
4107
+ activeSessions = [];
4108
+ constructor(config) {
4109
+ if (config) {
4110
+ this.config = config;
4111
+ }
4112
+ }
4113
+ static fromDict(_cfg) {
4114
+ throw new Error("fromDict must be implemented by concrete class");
4115
+ }
4116
+ addServer(name, serverConfig) {
4117
+ this.config.mcpServers = this.config.mcpServers || {};
4118
+ this.config.mcpServers[name] = serverConfig;
4119
+ Tel.getInstance().trackClientAddServer(name, serverConfig);
4120
+ }
4121
+ removeServer(name) {
4122
+ if (this.config.mcpServers?.[name]) {
4123
+ delete this.config.mcpServers[name];
4124
+ this.activeSessions = this.activeSessions.filter((n) => n !== name);
4125
+ Tel.getInstance().trackClientRemoveServer(name);
4126
+ }
4127
+ }
4128
+ getServerNames() {
4129
+ return Object.keys(this.config.mcpServers ?? {});
4130
+ }
4131
+ getServerConfig(name) {
4132
+ return this.config.mcpServers?.[name];
4133
+ }
4134
+ getConfig() {
4135
+ return this.config ?? {};
4136
+ }
4137
+ async createSession(serverName, autoInitialize = true) {
4138
+ const servers = this.config.mcpServers ?? {};
4139
+ if (Object.keys(servers).length === 0) {
4140
+ logger.warn("No MCP servers defined in config");
4141
+ }
4142
+ if (!servers[serverName]) {
4143
+ throw new Error(`Server '${serverName}' not found in config`);
4144
+ }
4145
+ const connector = this.createConnectorFromConfig(servers[serverName]);
4146
+ const session = new MCPSession(connector);
4147
+ if (autoInitialize) {
4148
+ await session.initialize();
4149
+ }
4150
+ this.sessions[serverName] = session;
4151
+ if (!this.activeSessions.includes(serverName)) {
4152
+ this.activeSessions.push(serverName);
4153
+ }
4154
+ return session;
4155
+ }
4156
+ async createAllSessions(autoInitialize = true) {
4157
+ const servers = this.config.mcpServers ?? {};
4158
+ if (Object.keys(servers).length === 0) {
4159
+ logger.warn("No MCP servers defined in config");
4160
+ }
4161
+ for (const name of Object.keys(servers)) {
4162
+ await this.createSession(name, autoInitialize);
4163
+ }
4164
+ return this.sessions;
4165
+ }
4166
+ getSession(serverName) {
4167
+ const session = this.sessions[serverName];
4168
+ if (!session) {
4169
+ return null;
4170
+ }
4171
+ return session;
4172
+ }
4173
+ requireSession(serverName) {
4174
+ const session = this.sessions[serverName];
4175
+ if (!session) {
4176
+ throw new Error(
4177
+ `Session '${serverName}' not found. Available sessions: ${this.activeSessions.join(", ") || "none"}`
4178
+ );
4179
+ }
4180
+ return session;
4181
+ }
4182
+ getAllActiveSessions() {
4183
+ return Object.fromEntries(
4184
+ this.activeSessions.map((n) => [n, this.sessions[n]])
4185
+ );
4186
+ }
4187
+ async closeSession(serverName) {
4188
+ const session = this.sessions[serverName];
4189
+ if (!session) {
4190
+ logger.warn(
4191
+ `No session exists for server ${serverName}, nothing to close`
4192
+ );
4193
+ return;
4194
+ }
4195
+ try {
4196
+ logger.debug(`Closing session for server ${serverName}`);
4197
+ await session.disconnect();
4198
+ } catch (e) {
4199
+ logger.error(`Error closing session for server '${serverName}': ${e}`);
4200
+ } finally {
4201
+ delete this.sessions[serverName];
4202
+ this.activeSessions = this.activeSessions.filter((n) => n !== serverName);
4203
+ }
4204
+ }
4205
+ async closeAllSessions() {
4206
+ const serverNames = Object.keys(this.sessions);
4207
+ const errors = [];
4208
+ for (const serverName of serverNames) {
4209
+ try {
4210
+ logger.debug(`Closing session for server ${serverName}`);
4211
+ await this.closeSession(serverName);
4212
+ } catch (e) {
4213
+ const errorMsg = `Failed to close session for server '${serverName}': ${e}`;
4214
+ logger.error(errorMsg);
4215
+ errors.push(errorMsg);
4216
+ }
4217
+ }
4218
+ if (errors.length) {
4219
+ logger.error(
4220
+ `Encountered ${errors.length} errors while closing sessions`
4221
+ );
4222
+ } else {
4223
+ logger.debug("All sessions closed successfully");
4224
+ }
4225
+ }
4226
+ };
4227
+
4228
+ // src/client/executors/base.ts
4229
+ init_logging();
4230
+ var BaseCodeExecutor = class {
4231
+ static {
4232
+ __name(this, "BaseCodeExecutor");
4233
+ }
4234
+ client;
4235
+ _connecting = false;
4236
+ constructor(client) {
4237
+ this.client = client;
4238
+ }
4239
+ /**
4240
+ * Ensure all configured MCP servers are connected before execution.
4241
+ * Prevents race conditions with a connection lock.
4242
+ */
4243
+ async ensureServersConnected() {
4244
+ const configuredServers = this.client.getServerNames();
4245
+ const activeSessions = Object.keys(this.client.getAllActiveSessions());
4246
+ const missingServers = configuredServers.filter(
4247
+ (s) => !activeSessions.includes(s)
4248
+ );
4249
+ if (missingServers.length > 0 && !this._connecting) {
4250
+ this._connecting = true;
4251
+ try {
4252
+ logger.debug(
4253
+ `Connecting to configured servers for code execution: ${missingServers.join(", ")}`
4254
+ );
4255
+ await this.client.createAllSessions();
4256
+ } finally {
4257
+ this._connecting = false;
4258
+ }
4259
+ } else if (missingServers.length > 0 && this._connecting) {
4260
+ logger.debug("Waiting for ongoing server connection...");
4261
+ const startWait = Date.now();
4262
+ while (this._connecting && Date.now() - startWait < 5e3) {
4263
+ await new Promise((resolve) => setTimeout(resolve, 100));
4264
+ }
4265
+ }
4266
+ }
4267
+ /**
4268
+ * Get tool namespace information from all active MCP sessions.
4269
+ * Filters out the internal code_mode server.
4270
+ */
4271
+ getToolNamespaces() {
4272
+ const namespaces = [];
4273
+ const activeSessions = this.client.getAllActiveSessions();
4274
+ for (const [serverName, session] of Object.entries(activeSessions)) {
4275
+ if (serverName === "code_mode") continue;
4276
+ try {
4277
+ const connector = session.connector;
4278
+ let tools;
4279
+ try {
4280
+ tools = connector.tools;
4281
+ } catch (e) {
4282
+ logger.warn(`Tools not available for server ${serverName}: ${e}`);
4283
+ continue;
4284
+ }
4285
+ if (!tools || tools.length === 0) continue;
4286
+ namespaces.push({ serverName, tools, session });
4287
+ } catch (e) {
4288
+ logger.warn(`Failed to load tools for server ${serverName}: ${e}`);
4289
+ }
4290
+ }
4291
+ return namespaces;
4292
+ }
4293
+ /**
4294
+ * Create a search function for discovering available MCP tools.
4295
+ * Used by code execution environments to find tools at runtime.
4296
+ */
4297
+ createSearchToolsFunction() {
4298
+ return async (query = "", detailLevel = "full") => {
4299
+ const allTools = [];
4300
+ const allNamespaces = /* @__PURE__ */ new Set();
4301
+ const queryLower = query.toLowerCase();
4302
+ const activeSessions = this.client.getAllActiveSessions();
4303
+ for (const [serverName, session] of Object.entries(activeSessions)) {
4304
+ if (serverName === "code_mode") continue;
4305
+ try {
4306
+ const tools = session.connector.tools;
4307
+ if (tools && tools.length > 0) {
4308
+ allNamespaces.add(serverName);
4309
+ }
4310
+ for (const tool of tools) {
4311
+ if (detailLevel === "names") {
4312
+ allTools.push({ name: tool.name, server: serverName });
4313
+ } else if (detailLevel === "descriptions") {
4314
+ allTools.push({
4315
+ name: tool.name,
4316
+ server: serverName,
4317
+ description: tool.description
4318
+ });
4319
+ } else {
4320
+ allTools.push({
4321
+ name: tool.name,
4322
+ server: serverName,
4323
+ description: tool.description,
4324
+ input_schema: tool.inputSchema
4325
+ });
4326
+ }
4327
+ }
4328
+ } catch (e) {
4329
+ logger.warn(`Failed to search tools in server ${serverName}: ${e}`);
4330
+ }
4331
+ }
4332
+ let filteredTools = allTools;
4333
+ if (query) {
4334
+ filteredTools = allTools.filter((tool) => {
4335
+ const nameMatch = tool.name.toLowerCase().includes(queryLower);
4336
+ const descMatch = tool.description?.toLowerCase().includes(queryLower);
4337
+ const serverMatch = tool.server.toLowerCase().includes(queryLower);
4338
+ return nameMatch || descMatch || serverMatch;
4339
+ });
4340
+ }
4341
+ return {
4342
+ meta: {
4343
+ total_tools: allTools.length,
4344
+ namespaces: Array.from(allNamespaces).sort(),
4345
+ result_count: filteredTools.length
4346
+ },
4347
+ results: filteredTools
4348
+ };
4349
+ };
4350
+ }
4351
+ };
4352
+
4353
+ // src/client/executors/e2b.ts
4354
+ init_logging();
4355
+ var E2BCodeExecutor = class extends BaseCodeExecutor {
4356
+ static {
4357
+ __name(this, "E2BCodeExecutor");
4358
+ }
4359
+ e2bApiKey;
4360
+ codeExecSandbox = null;
4361
+ SandboxClass = null;
4362
+ timeoutMs;
4363
+ constructor(client, options) {
4364
+ super(client);
4365
+ this.e2bApiKey = options.apiKey;
4366
+ this.timeoutMs = options.timeoutMs ?? 3e5;
4367
+ }
4368
+ /**
4369
+ * Lazy load E2B Sandbox class.
4370
+ * This allows the library to work without E2B installed.
4371
+ */
4372
+ async ensureSandboxClass() {
4373
+ if (this.SandboxClass) return;
4374
+ try {
4375
+ const e2b = await import("@e2b/code-interpreter");
4376
+ this.SandboxClass = e2b.Sandbox;
4377
+ } catch (error) {
4378
+ throw new Error(
4379
+ "@e2b/code-interpreter is not installed. The E2B code executor requires this optional dependency. Install it with: yarn add @e2b/code-interpreter"
4380
+ );
4381
+ }
4382
+ }
4383
+ /**
4384
+ * Get or create a dedicated sandbox for code execution.
4385
+ */
4386
+ async getOrCreateCodeExecSandbox() {
4387
+ if (this.codeExecSandbox) return this.codeExecSandbox;
4388
+ await this.ensureSandboxClass();
4389
+ logger.debug("Starting E2B sandbox for code execution...");
4390
+ this.codeExecSandbox = await this.SandboxClass.create("base", {
4391
+ apiKey: this.e2bApiKey,
4392
+ timeoutMs: this.timeoutMs
4393
+ });
4394
+ return this.codeExecSandbox;
4395
+ }
4396
+ /**
4397
+ * Generate the shim code that exposes tools to the sandbox environment.
4398
+ * Creates a bridge that intercepts tool calls and sends them back to host.
4399
+ */
4400
+ generateShim(tools) {
4401
+ let shim = `
4402
+ // MCP Bridge Shim
4403
+ global.__callMcpTool = async (server, tool, args) => {
4404
+ const id = Math.random().toString(36).substring(7);
4405
+ console.log(JSON.stringify({
4406
+ type: '__MCP_TOOL_CALL__',
4407
+ id,
4408
+ server,
4409
+ tool,
4410
+ args
4411
+ }));
4412
+
4413
+ const resultPath = \`/tmp/mcp_result_\${id}.json\`;
4414
+ const fs = require('fs');
4415
+
4416
+ // Poll for result file
4417
+ let attempts = 0;
4418
+ while (attempts < 300) { // 30 seconds timeout
4419
+ if (fs.existsSync(resultPath)) {
4420
+ const content = fs.readFileSync(resultPath, 'utf8');
4421
+ const result = JSON.parse(content);
4422
+ fs.unlinkSync(resultPath); // Clean up
4423
+
4424
+ if (result.error) {
4425
+ throw new Error(result.error);
4426
+ }
4427
+ return result.data;
4428
+ }
4429
+ await new Promise(resolve => setTimeout(resolve, 100));
4430
+ attempts++;
4431
+ }
4432
+ throw new Error('Tool execution timed out');
4433
+ };
4434
+
4435
+ // Global search_tools helper
4436
+ global.search_tools = async (query, detailLevel = 'full') => {
4437
+ const allTools = ${JSON.stringify(
4438
+ Object.entries(tools).flatMap(
4439
+ ([server, serverTools]) => serverTools.map((tool) => ({
4440
+ name: tool.name,
4441
+ description: tool.description,
4442
+ server,
4443
+ input_schema: tool.inputSchema
4444
+ }))
4445
+ )
4446
+ )};
4447
+
4448
+ const filtered = allTools.filter(tool => {
4449
+ if (!query) return true;
4450
+ const q = query.toLowerCase();
4451
+ return tool.name.toLowerCase().includes(q) ||
4452
+ (tool.description && tool.description.toLowerCase().includes(q));
4453
+ });
4454
+
4455
+ if (detailLevel === 'names') {
4456
+ return filtered.map(t => ({ name: t.name, server: t.server }));
4457
+ } else if (detailLevel === 'descriptions') {
4458
+ return filtered.map(t => ({ name: t.name, server: t.server, description: t.description }));
4459
+ }
4460
+ return filtered;
4461
+ };
4462
+ `;
4463
+ for (const [serverName, serverTools] of Object.entries(tools)) {
4464
+ if (!serverTools || serverTools.length === 0) continue;
4465
+ const safeServerName = serverName.replace(/[^a-zA-Z0-9_]/g, "_");
4466
+ shim += `
4467
+ global['${serverName}'] = {`;
4468
+ for (const tool of serverTools) {
4469
+ shim += `
4470
+ '${tool.name}': async (args) => await global.__callMcpTool('${serverName}', '${tool.name}', args),`;
4471
+ }
4472
+ shim += `
4473
+ };
4474
+
4475
+ // Also expose as safe name if different
4476
+ if ('${safeServerName}' !== '${serverName}') {
4477
+ global['${safeServerName}'] = global['${serverName}'];
4478
+ }
4479
+ `;
4480
+ }
4481
+ return shim;
4482
+ }
4483
+ /**
4484
+ * Build the tool catalog for the shim.
4485
+ * Returns a map of server names to their available tools.
4486
+ */
4487
+ buildToolCatalog() {
4488
+ const catalog = {};
4489
+ const namespaces = this.getToolNamespaces();
4490
+ for (const { serverName, tools } of namespaces) {
4491
+ catalog[serverName] = tools;
4492
+ }
4493
+ return catalog;
4494
+ }
4495
+ /**
4496
+ * Execute JavaScript/TypeScript code in an E2B sandbox with MCP tool access.
4497
+ * Tool calls are proxied back to the host via the bridge pattern.
4498
+ *
4499
+ * @param code - Code to execute
4500
+ * @param timeout - Execution timeout in milliseconds (default: 30000)
4501
+ */
4502
+ async execute(code, timeout = 3e4) {
4503
+ const startTime = Date.now();
4504
+ let result = null;
4505
+ let error = null;
4506
+ let logs = [];
4507
+ try {
4508
+ await this.ensureServersConnected();
4509
+ const sandbox = await this.getOrCreateCodeExecSandbox();
4510
+ const toolCatalog = this.buildToolCatalog();
4511
+ const shim = this.generateShim(toolCatalog);
4512
+ const wrappedCode = `
4513
+ ${shim}
4514
+
4515
+ (async () => {
4516
+ try {
4517
+ const func = async () => {
4518
+ ${code}
4519
+ };
4520
+ const result = await func();
4521
+ console.log('__MCP_RESULT_START__');
4522
+ console.log(JSON.stringify(result));
4523
+ console.log('__MCP_RESULT_END__');
4524
+ } catch (e) {
4525
+ console.error(e);
4526
+ process.exit(1);
4527
+ }
4528
+ })();
4529
+ `;
4530
+ const filename = `exec_${Date.now()}.js`;
4531
+ await sandbox.files.write(filename, wrappedCode);
4532
+ const execution = await sandbox.commands.run(`node ${filename}`, {
4533
+ timeoutMs: timeout,
4534
+ onStdout: /* @__PURE__ */ __name(async (data) => {
4535
+ try {
4536
+ const lines = data.split("\n");
4537
+ for (const line of lines) {
4538
+ if (line.trim().startsWith('{"type":"__MCP_TOOL_CALL__"')) {
4539
+ const call = JSON.parse(line);
4540
+ if (call.type === "__MCP_TOOL_CALL__") {
4541
+ try {
4542
+ logger.debug(
4543
+ `[E2B Bridge] Calling tool ${call.server}.${call.tool}`
4544
+ );
4545
+ const activeSessions = this.client.getAllActiveSessions();
4546
+ const session = activeSessions[call.server];
4547
+ if (!session) {
4548
+ throw new Error(`Server ${call.server} not found`);
4549
+ }
4550
+ const toolResult = await session.connector.callTool(
4551
+ call.tool,
4552
+ call.args
4553
+ );
4554
+ let extractedResult = toolResult;
4555
+ if (toolResult.content && toolResult.content.length > 0) {
4556
+ const item = toolResult.content[0];
4557
+ if (item.type === "text") {
4558
+ try {
4559
+ extractedResult = JSON.parse(item.text);
4560
+ } catch {
4561
+ extractedResult = item.text;
4562
+ }
4563
+ } else {
4564
+ extractedResult = item;
4565
+ }
4566
+ }
4567
+ const resultPath = `/tmp/mcp_result_${call.id}.json`;
4568
+ await sandbox.files.write(
4569
+ resultPath,
4570
+ JSON.stringify({ data: extractedResult })
4571
+ );
4572
+ } catch (err) {
4573
+ logger.error(
4574
+ `[E2B Bridge] Tool execution failed: ${err.message}`
4575
+ );
4576
+ const resultPath = `/tmp/mcp_result_${call.id}.json`;
4577
+ await sandbox.files.write(
4578
+ resultPath,
4579
+ JSON.stringify({
4580
+ error: err.message || String(err)
4581
+ })
4582
+ );
4583
+ }
4584
+ }
4585
+ }
4586
+ }
4587
+ } catch (e) {
4588
+ }
4589
+ }, "onStdout")
4590
+ });
4591
+ logs = [execution.stdout, execution.stderr].filter(Boolean);
4592
+ if (execution.exitCode !== 0) {
4593
+ error = execution.stderr || "Execution failed";
4594
+ } else {
4595
+ const stdout = execution.stdout;
4596
+ const startMarker = "__MCP_RESULT_START__";
4597
+ const endMarker = "__MCP_RESULT_END__";
4598
+ const startIndex = stdout.indexOf(startMarker);
4599
+ const endIndex = stdout.indexOf(endMarker);
4600
+ if (startIndex !== -1 && endIndex !== -1) {
4601
+ const jsonStr = stdout.substring(startIndex + startMarker.length, endIndex).trim();
4602
+ try {
4603
+ result = JSON.parse(jsonStr);
4604
+ } catch (e) {
4605
+ result = jsonStr;
4606
+ }
4607
+ logs = logs.map((log) => {
4608
+ let cleaned = log.replace(
4609
+ new RegExp(startMarker + "[\\s\\S]*?" + endMarker),
4610
+ "[Result captured]"
4611
+ );
4612
+ cleaned = cleaned.split("\n").filter((l) => !l.includes("__MCP_TOOL_CALL__")).join("\n");
4613
+ return cleaned;
4614
+ });
4615
+ }
4616
+ }
4617
+ } catch (e) {
4618
+ error = e.message || String(e);
4619
+ if (error && (error.includes("timeout") || error.includes("timed out"))) {
4620
+ error = "Script execution timed out";
4621
+ }
4622
+ }
4623
+ return {
4624
+ result,
4625
+ logs,
4626
+ error,
4627
+ execution_time: (Date.now() - startTime) / 1e3
4628
+ };
4629
+ }
4630
+ /**
4631
+ * Clean up the E2B sandbox.
4632
+ * Should be called when the executor is no longer needed.
4633
+ */
4634
+ async cleanup() {
4635
+ if (this.codeExecSandbox) {
4636
+ try {
4637
+ await this.codeExecSandbox.kill();
4638
+ this.codeExecSandbox = null;
4639
+ logger.debug("E2B code execution sandbox stopped");
4640
+ } catch (error) {
4641
+ logger.error("Failed to stop E2B code execution sandbox:", error);
4642
+ }
4643
+ }
4644
+ }
4645
+ };
4646
+
4647
+ // src/client/executors/vm.ts
4648
+ init_logging();
4649
+ var vm = null;
4650
+ var vmCheckAttempted = false;
4651
+ function getVMModuleName() {
4652
+ return ["node", "vm"].join(":");
4653
+ }
4654
+ __name(getVMModuleName, "getVMModuleName");
4655
+ function tryLoadVM() {
4656
+ if (vmCheckAttempted) {
4657
+ return vm !== null;
4658
+ }
4659
+ vmCheckAttempted = true;
4660
+ try {
4661
+ const nodeRequire = typeof require !== "undefined" ? require : null;
4662
+ if (nodeRequire) {
4663
+ vm = nodeRequire(getVMModuleName());
4664
+ return true;
4665
+ }
4666
+ } catch (error) {
4667
+ logger.debug("node:vm module not available via require");
4668
+ }
4669
+ return false;
4670
+ }
4671
+ __name(tryLoadVM, "tryLoadVM");
4672
+ async function tryLoadVMAsync() {
4673
+ if (vm !== null) {
4674
+ return true;
4675
+ }
4676
+ if (!vmCheckAttempted) {
4677
+ if (tryLoadVM()) {
4678
+ return true;
4679
+ }
4680
+ }
4681
+ try {
4682
+ vm = await import(
4683
+ /* @vite-ignore */
4684
+ getVMModuleName()
4685
+ );
4686
+ return true;
4687
+ } catch (error) {
4688
+ logger.debug(
4689
+ "node:vm module not available in this environment (e.g., Deno)"
4690
+ );
4691
+ return false;
4692
+ }
4693
+ }
4694
+ __name(tryLoadVMAsync, "tryLoadVMAsync");
4695
+ var VMCodeExecutor = class extends BaseCodeExecutor {
4696
+ static {
4697
+ __name(this, "VMCodeExecutor");
4698
+ }
4699
+ defaultTimeout;
4700
+ memoryLimitMb;
4701
+ constructor(client, options) {
4702
+ super(client);
4703
+ this.defaultTimeout = options?.timeoutMs ?? 3e4;
4704
+ this.memoryLimitMb = options?.memoryLimitMb;
4705
+ tryLoadVM();
4706
+ }
4707
+ /**
4708
+ * Ensure VM module is loaded before execution
4709
+ */
4710
+ async ensureVMLoaded() {
4711
+ if (vm !== null) {
4712
+ return;
4713
+ }
4714
+ const loaded = await tryLoadVMAsync();
4715
+ if (!loaded) {
4716
+ throw new Error(
4717
+ "node:vm module is not available in this environment. Please use E2B executor instead or run in a Node.js environment."
4718
+ );
4719
+ }
4720
+ }
4721
+ /**
4722
+ * Execute JavaScript/TypeScript code with access to MCP tools.
4723
+ *
4724
+ * @param code - Code to execute
4725
+ * @param timeout - Execution timeout in milliseconds (default: configured timeout or 30000)
4726
+ */
4727
+ async execute(code, timeout) {
4728
+ const effectiveTimeout = timeout ?? this.defaultTimeout;
4729
+ await this.ensureVMLoaded();
4730
+ await this.ensureServersConnected();
4731
+ const logs = [];
4732
+ const startTime = Date.now();
4733
+ let result = null;
4734
+ let error = null;
4735
+ try {
4736
+ const context = await this._buildContext(logs);
4737
+ const wrappedCode = `
4738
+ (async () => {
4739
+ try {
4740
+ ${code}
4741
+ } catch (e) {
4742
+ throw e;
4743
+ }
4744
+ })()
4745
+ `;
4746
+ const script = new vm.Script(wrappedCode, {
4747
+ filename: "agent_code.js"
4748
+ });
4749
+ const promise = script.runInNewContext(context, {
4750
+ timeout: effectiveTimeout,
4751
+ displayErrors: true
4752
+ });
4753
+ result = await promise;
4754
+ } catch (e) {
4755
+ error = e.message || String(e);
4756
+ if (e.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || e.message === "Script execution timed out." || typeof error === "string" && (error.includes("timed out") || error.includes("timeout"))) {
4757
+ error = "Script execution timed out";
4758
+ }
4759
+ if (e.stack) {
4760
+ logger.debug(`Code execution error stack: ${e.stack}`);
4761
+ }
4762
+ }
4763
+ const executionTime = (Date.now() - startTime) / 1e3;
4764
+ return {
4765
+ result,
4766
+ logs,
4767
+ error,
4768
+ execution_time: executionTime
4769
+ };
4770
+ }
4771
+ /**
4772
+ * Build the VM execution context with MCP tools and standard globals.
4773
+ *
4774
+ * @param logs - Array to capture console output
4775
+ */
4776
+ async _buildContext(logs) {
4777
+ const logHandler = /* @__PURE__ */ __name((...args) => {
4778
+ logs.push(
4779
+ args.map(
4780
+ (arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
4781
+ ).join(" ")
4782
+ );
4783
+ }, "logHandler");
4784
+ const sandbox = {
4785
+ console: {
4786
+ log: logHandler,
4787
+ error: /* @__PURE__ */ __name((...args) => {
4788
+ logHandler("[ERROR]", ...args);
4789
+ }, "error"),
4790
+ warn: /* @__PURE__ */ __name((...args) => {
4791
+ logHandler("[WARN]", ...args);
4792
+ }, "warn"),
4793
+ info: logHandler,
4794
+ debug: logHandler
4795
+ },
4796
+ // Standard globals
4797
+ Object,
4798
+ Array,
4799
+ String,
4800
+ Number,
4801
+ Boolean,
4802
+ Date,
4803
+ Math,
4804
+ JSON,
4805
+ RegExp,
4806
+ Map,
4807
+ Set,
4808
+ Promise,
4809
+ parseInt,
4810
+ parseFloat,
4811
+ isNaN,
4812
+ isFinite,
4813
+ encodeURI,
4814
+ decodeURI,
4815
+ encodeURIComponent,
4816
+ decodeURIComponent,
4817
+ setTimeout,
4818
+ clearTimeout,
4819
+ // Helper for tools
4820
+ search_tools: this.createSearchToolsFunction(),
4821
+ __tool_namespaces: []
4822
+ };
4823
+ const toolNamespaces = {};
4824
+ const namespaceInfos = this.getToolNamespaces();
4825
+ for (const { serverName, tools, session } of namespaceInfos) {
4826
+ const serverNamespace = {};
4827
+ for (const tool of tools) {
4828
+ const toolName = tool.name;
4829
+ serverNamespace[toolName] = async (args) => {
4830
+ const result = await session.connector.callTool(toolName, args || {});
4831
+ if (result.content && result.content.length > 0) {
4832
+ const item = result.content[0];
4833
+ if (item.type === "text") {
4834
+ try {
4835
+ return JSON.parse(item.text);
4836
+ } catch {
4837
+ return item.text;
4838
+ }
4839
+ }
4840
+ return item;
4841
+ }
4842
+ return result;
4843
+ };
4844
+ }
4845
+ sandbox[serverName] = serverNamespace;
4846
+ toolNamespaces[serverName] = true;
4847
+ }
4848
+ sandbox.__tool_namespaces = Object.keys(toolNamespaces);
4849
+ return vm.createContext(sandbox);
4850
+ }
4851
+ /**
4852
+ * Clean up resources.
4853
+ * VM executor doesn't need cleanup, but method kept for interface consistency.
4854
+ */
4855
+ async cleanup() {
4856
+ }
4857
+ };
4858
+
4859
+ // src/config.ts
4860
+ var import_node_fs = require("fs");
4861
+
4862
+ // src/connectors/http.ts
4863
+ var import_client = require("@mcp-use/modelcontextprotocol-sdk/client/index.js");
4864
+ var import_streamableHttp = require("@mcp-use/modelcontextprotocol-sdk/client/streamableHttp.js");
4865
+ init_logging();
4866
+
4867
+ // src/task_managers/sse.ts
4868
+ var import_sse = require("@mcp-use/modelcontextprotocol-sdk/client/sse.js");
4869
+ init_logging();
4870
+
4871
+ // src/task_managers/base.ts
4872
+ init_logging();
4873
+ var ConnectionManager = class {
4874
+ static {
4875
+ __name(this, "ConnectionManager");
4876
+ }
4877
+ _readyPromise;
4878
+ _readyResolver;
4879
+ _donePromise;
4880
+ _doneResolver;
4881
+ _exception = null;
4882
+ _connection = null;
4883
+ _task = null;
4884
+ _abortController = null;
4885
+ constructor() {
4886
+ this.reset();
4887
+ }
4888
+ /**
4889
+ * Start the connection manager and establish a connection.
4890
+ *
4891
+ * @returns The established connection.
4892
+ * @throws If the connection cannot be established.
4893
+ */
4894
+ async start() {
4895
+ this.reset();
4896
+ logger.debug(`Starting ${this.constructor.name}`);
4897
+ this._task = this.connectionTask();
4898
+ await this._readyPromise;
4899
+ if (this._exception) {
4900
+ throw this._exception;
4901
+ }
4902
+ if (this._connection === null) {
4903
+ throw new Error("Connection was not established");
4904
+ }
4905
+ return this._connection;
4906
+ }
4907
+ /**
4908
+ * Stop the connection manager and close the connection.
4909
+ */
4910
+ async stop() {
4911
+ if (this._task && this._abortController) {
4912
+ logger.debug(`Cancelling ${this.constructor.name} task`);
4913
+ this._abortController.abort();
4914
+ try {
4915
+ await this._task;
4916
+ } catch (e) {
4917
+ if (e instanceof Error && e.name === "AbortError") {
4918
+ logger.debug(`${this.constructor.name} task aborted successfully`);
4919
+ } else {
4920
+ logger.warn(`Error stopping ${this.constructor.name} task: ${e}`);
4921
+ }
4922
+ }
4923
+ }
4924
+ await this._donePromise;
4925
+ logger.debug(`${this.constructor.name} task completed`);
4926
+ }
4927
+ /**
4928
+ * Reset all internal state.
4929
+ */
4930
+ reset() {
4931
+ this._readyPromise = new Promise((res) => this._readyResolver = res);
4932
+ this._donePromise = new Promise((res) => this._doneResolver = res);
4933
+ this._exception = null;
4934
+ this._connection = null;
4935
+ this._task = null;
4936
+ this._abortController = new AbortController();
4937
+ }
4938
+ /**
4939
+ * The background task responsible for establishing and maintaining the
4940
+ * connection until it is cancelled.
4941
+ */
4942
+ async connectionTask() {
4943
+ logger.debug(`Running ${this.constructor.name} task`);
4944
+ try {
4945
+ this._connection = await this.establishConnection();
4946
+ logger.debug(`${this.constructor.name} connected successfully`);
4947
+ this._readyResolver();
4948
+ await this.waitForAbort();
4949
+ } catch (err) {
4950
+ this._exception = err;
4951
+ logger.error(`Error in ${this.constructor.name} task: ${err}`);
4952
+ this._readyResolver();
4953
+ } finally {
4954
+ if (this._connection !== null) {
4955
+ try {
4956
+ await this.closeConnection(this._connection);
4957
+ } catch (closeErr) {
4958
+ logger.warn(
4959
+ `Error closing connection in ${this.constructor.name}: ${closeErr}`
4960
+ );
4961
+ }
4962
+ this._connection = null;
4963
+ }
4964
+ this._doneResolver();
4965
+ }
4966
+ }
4967
+ /**
4968
+ * Helper that returns a promise which resolves when the abort signal fires.
4969
+ */
4970
+ async waitForAbort() {
4971
+ return new Promise((_resolve, _reject) => {
4972
+ if (!this._abortController) {
4973
+ return;
4974
+ }
4975
+ const signal = this._abortController.signal;
4976
+ if (signal.aborted) {
4977
+ _resolve();
4978
+ return;
4979
+ }
4980
+ const onAbort = /* @__PURE__ */ __name(() => {
4981
+ signal.removeEventListener("abort", onAbort);
4982
+ _resolve();
4983
+ }, "onAbort");
4984
+ signal.addEventListener("abort", onAbort);
4985
+ });
4986
+ }
4987
+ };
4988
+
4989
+ // src/task_managers/sse.ts
4990
+ var SseConnectionManager = class extends ConnectionManager {
4991
+ static {
4992
+ __name(this, "SseConnectionManager");
4993
+ }
4994
+ url;
4995
+ opts;
4996
+ _transport = null;
4997
+ /**
4998
+ * Create an SSE connection manager.
4999
+ *
5000
+ * @param url The SSE endpoint URL.
5001
+ * @param opts Optional transport options (auth, headers, etc.).
5002
+ */
5003
+ constructor(url, opts) {
5004
+ super();
5005
+ this.url = typeof url === "string" ? new URL(url) : url;
5006
+ this.opts = opts;
5007
+ }
5008
+ /**
5009
+ * Spawn a new `SSEClientTransport` and start the connection.
5010
+ */
5011
+ async establishConnection() {
5012
+ this._transport = new import_sse.SSEClientTransport(this.url, this.opts);
5013
+ logger.debug(`${this.constructor.name} connected successfully`);
5014
+ return this._transport;
5015
+ }
5016
+ /**
5017
+ * Close the underlying transport and clean up resources.
5018
+ */
5019
+ async closeConnection(_connection) {
5020
+ if (this._transport) {
5021
+ try {
5022
+ await this._transport.close();
5023
+ } catch (e) {
5024
+ logger.warn(`Error closing SSE transport: ${e}`);
5025
+ } finally {
5026
+ this._transport = null;
5027
+ }
5028
+ }
5029
+ }
5030
+ };
5031
+
5032
+ // src/connectors/http.ts
5033
+ var HttpConnector = class extends BaseConnector {
5034
+ static {
5035
+ __name(this, "HttpConnector");
5036
+ }
5037
+ baseUrl;
5038
+ headers;
5039
+ timeout;
5040
+ sseReadTimeout;
5041
+ clientInfo;
5042
+ preferSse;
5043
+ transportType = null;
5044
+ streamableTransport = null;
5045
+ constructor(baseUrl, opts = {}) {
5046
+ super(opts);
5047
+ this.baseUrl = baseUrl.replace(/\/$/, "");
5048
+ this.headers = { ...opts.headers ?? {} };
5049
+ if (opts.authToken) {
5050
+ this.headers.Authorization = `Bearer ${opts.authToken}`;
5051
+ }
5052
+ this.timeout = opts.timeout ?? 3e4;
5053
+ this.sseReadTimeout = opts.sseReadTimeout ?? 3e5;
5054
+ this.clientInfo = opts.clientInfo ?? {
5055
+ name: "http-connector",
5056
+ version: "1.0.0"
5057
+ };
5058
+ this.preferSse = opts.preferSse ?? false;
5059
+ }
5060
+ /** Establish connection to the MCP implementation via HTTP (streamable or SSE). */
5061
+ async connect() {
5062
+ if (this.connected) {
5063
+ logger.debug("Already connected to MCP implementation");
5064
+ return;
5065
+ }
5066
+ const baseUrl = this.baseUrl;
5067
+ if (this.preferSse) {
5068
+ logger.debug(`Connecting to MCP implementation via HTTP/SSE: ${baseUrl}`);
5069
+ await this.connectWithSse(baseUrl);
5070
+ return;
5071
+ }
5072
+ logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
5073
+ try {
5074
+ logger.info("\u{1F504} Attempting streamable HTTP transport...");
5075
+ await this.connectWithStreamableHttp(baseUrl);
5076
+ logger.info("\u2705 Successfully connected via streamable HTTP");
5077
+ } catch (err) {
5078
+ let fallbackReason = "Unknown error";
5079
+ let is401Error = false;
5080
+ if (err instanceof import_streamableHttp.StreamableHTTPError) {
5081
+ const streamableErr = err;
5082
+ is401Error = streamableErr.code === 401;
5083
+ if (streamableErr.code === 400 && streamableErr.message.includes("Missing session ID")) {
5084
+ fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
5085
+ logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
5086
+ } else if (streamableErr.code === 404 || streamableErr.code === 405) {
5087
+ fallbackReason = `Server returned ${streamableErr.code} - server likely doesn't support streamable HTTP`;
5088
+ logger.debug(fallbackReason);
5089
+ } else {
5090
+ fallbackReason = `Server returned ${streamableErr.code}: ${streamableErr.message}`;
5091
+ logger.debug(fallbackReason);
5092
+ }
5093
+ } else if (err instanceof Error) {
5094
+ const errorStr = err.toString();
5095
+ const errorMsg = err.message || "";
5096
+ is401Error = errorStr.includes("401") || errorMsg.includes("Unauthorized");
5097
+ if (errorStr.includes("Missing session ID") || errorStr.includes("Bad Request: Missing session ID") || errorMsg.includes("FastMCP session ID error")) {
5098
+ fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
5099
+ logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
5100
+ } else if (errorStr.includes("405 Method Not Allowed") || errorStr.includes("404 Not Found")) {
5101
+ fallbackReason = "Server doesn't support streamable HTTP (405/404)";
5102
+ logger.debug(fallbackReason);
5103
+ } else {
5104
+ fallbackReason = `Streamable HTTP failed: ${err.message}`;
5105
+ logger.debug(fallbackReason);
5106
+ }
5107
+ }
5108
+ if (is401Error) {
5109
+ logger.info("Authentication required - skipping SSE fallback");
5110
+ await this.cleanupResources();
5111
+ const authError = new Error("Authentication required");
5112
+ authError.code = 401;
5113
+ throw authError;
5114
+ }
5115
+ logger.info("\u{1F504} Falling back to SSE transport...");
5116
+ try {
5117
+ await this.connectWithSse(baseUrl);
5118
+ } catch (sseErr) {
5119
+ logger.error(`Failed to connect with both transports:`);
5120
+ logger.error(` Streamable HTTP: ${fallbackReason}`);
5121
+ logger.error(` SSE: ${sseErr}`);
5122
+ await this.cleanupResources();
5123
+ const sseIs401 = sseErr?.message?.includes("401") || sseErr?.message?.includes("Unauthorized");
5124
+ if (sseIs401) {
5125
+ const authError = new Error("Authentication required");
5126
+ authError.code = 401;
5127
+ throw authError;
5128
+ }
5129
+ throw new Error(
5130
+ "Could not connect to server with any available transport"
5131
+ );
5132
+ }
5133
+ }
5134
+ }
5135
+ async connectWithStreamableHttp(baseUrl) {
5136
+ try {
5137
+ const streamableTransport = new import_streamableHttp.StreamableHTTPClientTransport(
5138
+ new URL(baseUrl),
5139
+ {
5140
+ authProvider: this.opts.authProvider,
5141
+ // ← Pass OAuth provider to SDK
5142
+ requestInit: {
5143
+ headers: this.headers
5144
+ },
5145
+ // Pass through reconnection options
5146
+ reconnectionOptions: {
5147
+ maxReconnectionDelay: 3e4,
5148
+ initialReconnectionDelay: 1e3,
5149
+ reconnectionDelayGrowFactor: 1.5,
5150
+ maxRetries: 2
5151
+ }
5152
+ // Don't pass sessionId - let the SDK generate it automatically during connect()
5153
+ }
5154
+ );
5155
+ let transport = streamableTransport;
5156
+ if (this.opts.wrapTransport) {
5157
+ const serverId = this.baseUrl;
5158
+ transport = this.opts.wrapTransport(
5159
+ transport,
5160
+ serverId
5161
+ );
5162
+ }
5163
+ const clientOptions = {
5164
+ ...this.opts.clientOptions || {},
5165
+ capabilities: {
5166
+ ...this.opts.clientOptions?.capabilities || {},
5167
+ roots: { listChanged: true },
5168
+ // Always advertise roots capability
5169
+ // Add sampling capability if callback is provided
5170
+ ...this.opts.samplingCallback ? { sampling: {} } : {},
5171
+ // Add elicitation capability if callback is provided
5172
+ ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
5173
+ }
5174
+ };
5175
+ logger.debug(
5176
+ `Creating Client with capabilities:`,
5177
+ JSON.stringify(clientOptions.capabilities, null, 2)
5178
+ );
5179
+ this.client = new import_client.Client(this.clientInfo, clientOptions);
5180
+ this.setupRootsHandler();
5181
+ logger.debug("Roots handler registered before connect");
5182
+ try {
5183
+ await this.client.connect(transport, {
5184
+ timeout: Math.min(this.timeout, 3e3)
5185
+ });
5186
+ const sessionId = streamableTransport.sessionId;
5187
+ if (sessionId) {
5188
+ logger.debug(`Session ID obtained: ${sessionId}`);
5189
+ } else {
5190
+ logger.warn(
5191
+ "Session ID not available after connect - this may cause issues with SSE stream"
5192
+ );
5193
+ }
5194
+ } catch (connectErr) {
5195
+ if (connectErr instanceof Error) {
5196
+ const errMsg = connectErr.message || connectErr.toString();
5197
+ if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID") || errMsg.includes("Mcp-Session-Id header is required")) {
5198
+ const wrappedError = new Error(
5199
+ `Session ID error: ${errMsg}. The SDK should automatically extract session ID from initialize response.`
5200
+ );
5201
+ wrappedError.cause = connectErr;
5202
+ throw wrappedError;
5203
+ }
5204
+ }
5205
+ throw connectErr;
5206
+ }
5207
+ this.streamableTransport = streamableTransport;
5208
+ this.connectionManager = {
5209
+ stop: /* @__PURE__ */ __name(async () => {
5210
+ if (this.streamableTransport) {
5211
+ try {
5212
+ await this.streamableTransport.terminateSession();
5213
+ await this.streamableTransport.close();
5214
+ } catch (e) {
5215
+ logger.warn(`Error closing Streamable HTTP transport: ${e}`);
5216
+ } finally {
5217
+ this.streamableTransport = null;
5218
+ }
5219
+ }
5220
+ }, "stop")
5221
+ };
5222
+ this.connected = true;
5223
+ this.transportType = "streamable-http";
5224
+ this.setupNotificationHandler();
5225
+ this.setupSamplingHandler();
5226
+ this.setupElicitationHandler();
5227
+ logger.debug(
5228
+ `Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
5229
+ );
5230
+ this.trackConnectorInit({
5231
+ serverUrl: this.baseUrl,
5232
+ publicIdentifier: `${this.baseUrl} (streamable-http)`
5233
+ });
5234
+ } catch (err) {
5235
+ await this.cleanupResources();
5236
+ throw err;
5237
+ }
5238
+ }
5239
+ async connectWithSse(baseUrl) {
5240
+ try {
5241
+ this.connectionManager = new SseConnectionManager(baseUrl, {
5242
+ authProvider: this.opts.authProvider,
5243
+ // ← Pass OAuth provider to SDK (same as streamable HTTP)
5244
+ requestInit: {
5245
+ headers: this.headers
5246
+ }
5247
+ });
5248
+ let transport = await this.connectionManager.start();
5249
+ if (this.opts.wrapTransport) {
5250
+ const serverId = this.baseUrl;
5251
+ transport = this.opts.wrapTransport(transport, serverId);
5252
+ }
5253
+ const clientOptions = {
5254
+ ...this.opts.clientOptions || {},
5255
+ capabilities: {
5256
+ ...this.opts.clientOptions?.capabilities || {},
5257
+ roots: { listChanged: true },
5258
+ // Always advertise roots capability
5259
+ // Add sampling capability if callback is provided
5260
+ ...this.opts.samplingCallback ? { sampling: {} } : {},
5261
+ // Add elicitation capability if callback is provided
5262
+ ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
5263
+ }
5264
+ };
5265
+ logger.debug(
5266
+ `Creating Client with capabilities (SSE):`,
5267
+ JSON.stringify(clientOptions.capabilities, null, 2)
5268
+ );
5269
+ this.client = new import_client.Client(this.clientInfo, clientOptions);
5270
+ this.setupRootsHandler();
5271
+ logger.debug("Roots handler registered before connect (SSE)");
5272
+ await this.client.connect(transport);
5273
+ this.connected = true;
5274
+ this.transportType = "sse";
5275
+ this.setupNotificationHandler();
5276
+ this.setupSamplingHandler();
5277
+ this.setupElicitationHandler();
5278
+ logger.debug(
5279
+ `Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
5280
+ );
5281
+ this.trackConnectorInit({
5282
+ serverUrl: this.baseUrl,
5283
+ publicIdentifier: `${this.baseUrl} (sse)`
5284
+ });
5285
+ } catch (err) {
5286
+ await this.cleanupResources();
5287
+ throw err;
5288
+ }
5289
+ }
5290
+ get publicIdentifier() {
5291
+ return {
5292
+ type: "http",
5293
+ url: this.baseUrl,
5294
+ transport: this.transportType || "unknown"
5295
+ };
5296
+ }
5297
+ /**
5298
+ * Get the transport type being used (streamable-http or sse)
5299
+ */
5300
+ getTransportType() {
5301
+ return this.transportType;
5302
+ }
5303
+ };
5304
+
5305
+ // src/connectors/stdio.ts
5306
+ var import_node_process = __toESM(require("process"), 1);
5307
+ var import_client2 = require("@mcp-use/modelcontextprotocol-sdk/client/index.js");
5308
+ init_logging();
5309
+
5310
+ // src/task_managers/stdio.ts
5311
+ var import_stdio = require("@mcp-use/modelcontextprotocol-sdk/client/stdio.js");
5312
+ init_logging();
5313
+ var StdioConnectionManager = class extends ConnectionManager {
5314
+ static {
5315
+ __name(this, "StdioConnectionManager");
5316
+ }
5317
+ serverParams;
5318
+ errlog;
5319
+ _transport = null;
5320
+ /**
5321
+ * Create a new stdio connection manager.
5322
+ *
5323
+ * @param serverParams Parameters for the stdio server process.
5324
+ * @param errlog Stream to which the server's stderr should be piped.
5325
+ * Defaults to `process.stderr`.
5326
+ */
5327
+ constructor(serverParams, errlog = process.stderr) {
5328
+ super();
5329
+ this.serverParams = serverParams;
5330
+ this.errlog = errlog;
5331
+ }
5332
+ /**
5333
+ * Establish the stdio connection by spawning the server process and starting
5334
+ * the SDK's transport. Returns the live `StdioClientTransport` instance.
5335
+ */
5336
+ async establishConnection() {
5337
+ this._transport = new import_stdio.StdioClientTransport(this.serverParams);
5338
+ if (this._transport.stderr && typeof this._transport.stderr.pipe === "function") {
5339
+ this._transport.stderr.pipe(
5340
+ this.errlog
5341
+ );
5342
+ }
5343
+ logger.debug(`${this.constructor.name} connected successfully`);
5344
+ return this._transport;
5345
+ }
5346
+ /**
5347
+ * Close the stdio connection, making sure the transport cleans up the child
5348
+ * process and associated resources.
5349
+ */
5350
+ async closeConnection(_connection) {
5351
+ if (this._transport) {
5352
+ try {
5353
+ await this._transport.close();
5354
+ } catch (e) {
5355
+ logger.warn(`Error closing stdio transport: ${e}`);
5356
+ } finally {
5357
+ this._transport = null;
5358
+ }
5359
+ }
5360
+ }
5361
+ };
5362
+
5363
+ // src/connectors/stdio.ts
5364
+ var StdioConnector = class extends BaseConnector {
5365
+ static {
5366
+ __name(this, "StdioConnector");
5367
+ }
5368
+ command;
5369
+ args;
5370
+ env;
5371
+ errlog;
5372
+ clientInfo;
5373
+ constructor({
5374
+ command = "npx",
5375
+ args = [],
5376
+ env,
5377
+ errlog = import_node_process.default.stderr,
5378
+ ...rest
5379
+ } = {}) {
5380
+ super(rest);
5381
+ this.command = command;
5382
+ this.args = args;
5383
+ this.env = env;
5384
+ this.errlog = errlog;
5385
+ this.clientInfo = rest.clientInfo ?? {
5386
+ name: "stdio-connector",
5387
+ version: "1.0.0"
5388
+ };
5389
+ }
5390
+ /** Establish connection to the MCP implementation. */
5391
+ async connect() {
5392
+ if (this.connected) {
5393
+ logger.debug("Already connected to MCP implementation");
5394
+ return;
5395
+ }
5396
+ logger.debug(`Connecting to MCP implementation via stdio: ${this.command}`);
5397
+ try {
5398
+ let mergedEnv;
5399
+ if (this.env) {
5400
+ mergedEnv = {};
5401
+ for (const [key, value] of Object.entries(import_node_process.default.env)) {
5402
+ if (value !== void 0) {
5403
+ mergedEnv[key] = value;
5404
+ }
3186
5405
  }
3187
- }, "func")
5406
+ Object.assign(mergedEnv, this.env);
5407
+ }
5408
+ const serverParams = {
5409
+ command: this.command,
5410
+ args: this.args,
5411
+ env: mergedEnv
5412
+ };
5413
+ this.connectionManager = new StdioConnectionManager(
5414
+ serverParams,
5415
+ this.errlog
5416
+ );
5417
+ const transport = await this.connectionManager.start();
5418
+ const clientOptions = {
5419
+ ...this.opts.clientOptions || {},
5420
+ capabilities: {
5421
+ ...this.opts.clientOptions?.capabilities || {},
5422
+ roots: { listChanged: true },
5423
+ // Always advertise roots capability
5424
+ // Add sampling capability if callback is provided
5425
+ ...this.opts.samplingCallback ? { sampling: {} } : {},
5426
+ // Add elicitation capability if callback is provided
5427
+ ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
5428
+ }
5429
+ };
5430
+ this.client = new import_client2.Client(this.clientInfo, clientOptions);
5431
+ await this.client.connect(transport);
5432
+ this.connected = true;
5433
+ this.setupNotificationHandler();
5434
+ this.setupRootsHandler();
5435
+ this.setupSamplingHandler();
5436
+ this.setupElicitationHandler();
5437
+ logger.debug(
5438
+ `Successfully connected to MCP implementation: ${this.command}`
5439
+ );
5440
+ this.trackConnectorInit({
5441
+ serverCommand: this.command,
5442
+ serverArgs: this.args,
5443
+ publicIdentifier: `${this.command} ${this.args.join(" ")}`
5444
+ });
5445
+ } catch (err) {
5446
+ logger.error(`Failed to connect to MCP implementation: ${err}`);
5447
+ await this.cleanupResources();
5448
+ throw err;
5449
+ }
5450
+ }
5451
+ get publicIdentifier() {
5452
+ return {
5453
+ type: "stdio",
5454
+ "command&args": `${this.command} ${this.args.join(" ")}`
5455
+ };
5456
+ }
5457
+ };
5458
+
5459
+ // src/config.ts
5460
+ function loadConfigFile(filepath) {
5461
+ const raw = (0, import_node_fs.readFileSync)(filepath, "utf-8");
5462
+ return JSON.parse(raw);
5463
+ }
5464
+ __name(loadConfigFile, "loadConfigFile");
5465
+ function createConnectorFromConfig(serverConfig, connectorOptions) {
5466
+ if ("command" in serverConfig && "args" in serverConfig) {
5467
+ return new StdioConnector({
5468
+ command: serverConfig.command,
5469
+ args: serverConfig.args,
5470
+ env: serverConfig.env,
5471
+ ...connectorOptions
3188
5472
  });
3189
- return tool;
5473
+ }
5474
+ if ("url" in serverConfig) {
5475
+ const transport = serverConfig.transport || "http";
5476
+ return new HttpConnector(serverConfig.url, {
5477
+ headers: serverConfig.headers,
5478
+ authToken: serverConfig.auth_token || serverConfig.authToken,
5479
+ // Only force SSE if explicitly requested
5480
+ preferSse: serverConfig.preferSse || transport === "sse",
5481
+ ...connectorOptions
5482
+ });
5483
+ }
5484
+ throw new Error("Cannot determine connector type from config");
5485
+ }
5486
+ __name(createConnectorFromConfig, "createConnectorFromConfig");
5487
+
5488
+ // src/client.ts
5489
+ init_logging();
5490
+ var MCPClient = class _MCPClient extends BaseMCPClient {
5491
+ static {
5492
+ __name(this, "MCPClient");
3190
5493
  }
3191
5494
  /**
3192
- * Convert a single MCP prompt into a LangChainJS structured tool.
3193
- * The resulting tool executes getPrompt on the connector with the prompt's name
3194
- * and the user-provided arguments (if any).
5495
+ * Get the mcp-use package version.
5496
+ * Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
3195
5497
  */
3196
- convertPrompt(mcpPrompt, connector) {
3197
- let argsSchema = import_zod2.z.object({}).optional();
3198
- if (mcpPrompt.arguments && mcpPrompt.arguments.length > 0) {
3199
- const schemaFields = {};
3200
- for (const arg of mcpPrompt.arguments) {
3201
- const zodType = import_zod2.z.string();
3202
- if (arg.required !== false) {
3203
- schemaFields[arg.name] = zodType;
3204
- } else {
3205
- schemaFields[arg.name] = zodType.optional();
3206
- }
5498
+ static getPackageVersion() {
5499
+ return getPackageVersion();
5500
+ }
5501
+ codeMode = false;
5502
+ _codeExecutor = null;
5503
+ _customCodeExecutor = null;
5504
+ _codeExecutorConfig = "vm";
5505
+ _executorOptions;
5506
+ _samplingCallback;
5507
+ _elicitationCallback;
5508
+ constructor(config, options) {
5509
+ if (config) {
5510
+ if (typeof config === "string") {
5511
+ super(loadConfigFile(config));
5512
+ } else {
5513
+ super(config);
3207
5514
  }
3208
- argsSchema = Object.keys(schemaFields).length > 0 ? import_zod2.z.object(schemaFields) : import_zod2.z.object({}).optional();
5515
+ } else {
5516
+ super();
5517
+ }
5518
+ let codeModeEnabled = false;
5519
+ let executorConfig = "vm";
5520
+ let executorOptions;
5521
+ if (options?.codeMode) {
5522
+ if (typeof options.codeMode === "boolean") {
5523
+ codeModeEnabled = options.codeMode;
5524
+ } else {
5525
+ codeModeEnabled = options.codeMode.enabled;
5526
+ executorConfig = options.codeMode.executor ?? "vm";
5527
+ executorOptions = options.codeMode.executorOptions;
5528
+ }
5529
+ }
5530
+ this.codeMode = codeModeEnabled;
5531
+ this._codeExecutorConfig = executorConfig;
5532
+ this._executorOptions = executorOptions;
5533
+ this._samplingCallback = options?.samplingCallback;
5534
+ this._elicitationCallback = options?.elicitationCallback;
5535
+ if (this.codeMode) {
5536
+ this._setupCodeModeConnector();
5537
+ }
5538
+ this._trackClientInit();
5539
+ }
5540
+ _trackClientInit() {
5541
+ const servers = Object.keys(this.config.mcpServers ?? {});
5542
+ const hasSamplingCallback = !!this._samplingCallback;
5543
+ const hasElicitationCallback = !!this._elicitationCallback;
5544
+ Tel.getInstance().trackMCPClientInit({
5545
+ codeMode: this.codeMode,
5546
+ sandbox: false,
5547
+ // Sandbox not supported in TS yet
5548
+ allCallbacks: hasSamplingCallback && hasElicitationCallback,
5549
+ verify: false,
5550
+ // No verify option in TS client
5551
+ servers,
5552
+ numServers: servers.length,
5553
+ isBrowser: false
5554
+ // Node.js MCPClient
5555
+ }).catch((e) => logger.debug(`Failed to track MCPClient init: ${e}`));
5556
+ }
5557
+ static fromDict(cfg, options) {
5558
+ return new _MCPClient(cfg, options);
5559
+ }
5560
+ static fromConfigFile(path2, options) {
5561
+ return new _MCPClient(loadConfigFile(path2), options);
5562
+ }
5563
+ /**
5564
+ * Save configuration to a file (Node.js only)
5565
+ */
5566
+ saveConfig(filepath) {
5567
+ const dir = import_node_path.default.dirname(filepath);
5568
+ if (!import_node_fs2.default.existsSync(dir)) {
5569
+ import_node_fs2.default.mkdirSync(dir, { recursive: true });
3209
5570
  }
3210
- const tool = new import_tools.DynamicStructuredTool({
3211
- name: mcpPrompt.name,
3212
- description: mcpPrompt.description || "",
3213
- schema: argsSchema,
3214
- func: /* @__PURE__ */ __name(async (input) => {
3215
- logger.debug(
3216
- `Prompt tool: "${mcpPrompt.name}" called with args: ${JSON.stringify(input)}`
5571
+ import_node_fs2.default.writeFileSync(filepath, JSON.stringify(this.config, null, 2), "utf-8");
5572
+ }
5573
+ /**
5574
+ * Create a connector from server configuration (Node.js version)
5575
+ * Supports all connector types including StdioConnector
5576
+ */
5577
+ createConnectorFromConfig(serverConfig) {
5578
+ return createConnectorFromConfig(serverConfig, {
5579
+ samplingCallback: this._samplingCallback,
5580
+ elicitationCallback: this._elicitationCallback
5581
+ });
5582
+ }
5583
+ _setupCodeModeConnector() {
5584
+ logger.debug("Code mode connector initialized as internal meta server");
5585
+ const connector = new CodeModeConnector(this);
5586
+ const session = new MCPSession(connector);
5587
+ this.sessions["code_mode"] = session;
5588
+ this.activeSessions.push("code_mode");
5589
+ }
5590
+ _ensureCodeExecutor() {
5591
+ if (!this._codeExecutor) {
5592
+ const config = this._codeExecutorConfig;
5593
+ if (config instanceof BaseCodeExecutor) {
5594
+ this._codeExecutor = config;
5595
+ } else if (typeof config === "function") {
5596
+ this._customCodeExecutor = config;
5597
+ throw new Error(
5598
+ "Custom executor function should be handled in executeCode"
3217
5599
  );
5600
+ } else if (config === "e2b") {
5601
+ const opts = this._executorOptions;
5602
+ if (!opts?.apiKey) {
5603
+ logger.warn("E2B executor requires apiKey. Falling back to VM.");
5604
+ try {
5605
+ this._codeExecutor = new VMCodeExecutor(
5606
+ this,
5607
+ this._executorOptions
5608
+ );
5609
+ } catch (error) {
5610
+ throw new Error(
5611
+ "VM executor is not available in this environment and E2B API key is not provided. Please provide an E2B API key or run in a Node.js environment."
5612
+ );
5613
+ }
5614
+ } else {
5615
+ this._codeExecutor = new E2BCodeExecutor(this, opts);
5616
+ }
5617
+ } else {
3218
5618
  try {
3219
- const result = await connector.getPrompt(mcpPrompt.name, input);
3220
- if (result.messages && result.messages.length > 0) {
3221
- return result.messages.map((msg) => {
3222
- if (typeof msg === "string") {
3223
- return msg;
3224
- }
3225
- if (msg.content) {
3226
- return typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
3227
- }
3228
- return JSON.stringify(msg);
3229
- }).join("\n");
5619
+ this._codeExecutor = new VMCodeExecutor(
5620
+ this,
5621
+ this._executorOptions
5622
+ );
5623
+ } catch (error) {
5624
+ const e2bOpts = this._executorOptions;
5625
+ const e2bApiKey = e2bOpts?.apiKey || process.env.E2B_API_KEY;
5626
+ if (e2bApiKey) {
5627
+ logger.info(
5628
+ "VM executor not available in this environment. Falling back to E2B."
5629
+ );
5630
+ this._codeExecutor = new E2BCodeExecutor(this, {
5631
+ ...e2bOpts,
5632
+ apiKey: e2bApiKey
5633
+ });
5634
+ } else {
5635
+ throw new Error(
5636
+ "VM executor is not available in this environment. Please provide an E2B API key via executorOptions or E2B_API_KEY environment variable, or run in a Node.js environment."
5637
+ );
3230
5638
  }
3231
- return "Prompt returned no messages";
3232
- } catch (err) {
3233
- logger.error(`Error getting prompt: ${err.message}`);
3234
- return `Error getting prompt: ${String(err)}`;
3235
5639
  }
3236
- }, "func")
5640
+ }
5641
+ }
5642
+ return this._codeExecutor;
5643
+ }
5644
+ /**
5645
+ * Execute code in code mode
5646
+ */
5647
+ async executeCode(code, timeout) {
5648
+ if (!this.codeMode) {
5649
+ throw new Error("Code execution mode is not enabled");
5650
+ }
5651
+ if (this._customCodeExecutor) {
5652
+ return this._customCodeExecutor(code, timeout);
5653
+ }
5654
+ return this._ensureCodeExecutor().execute(code, timeout);
5655
+ }
5656
+ /**
5657
+ * Search available tools (used by code mode)
5658
+ */
5659
+ async searchTools(query = "", detailLevel = "full") {
5660
+ if (!this.codeMode) {
5661
+ throw new Error("Code execution mode is not enabled");
5662
+ }
5663
+ return this._ensureCodeExecutor().createSearchToolsFunction()(
5664
+ query,
5665
+ detailLevel
5666
+ );
5667
+ }
5668
+ /**
5669
+ * Override getServerNames to exclude internal code_mode server
5670
+ */
5671
+ getServerNames() {
5672
+ const isCodeModeEnabled = this.codeMode;
5673
+ return super.getServerNames().filter((name) => {
5674
+ return !isCodeModeEnabled || name !== "code_mode";
3237
5675
  });
3238
- return tool;
5676
+ }
5677
+ /**
5678
+ * Close the client and clean up resources including code executors.
5679
+ * This ensures E2B sandboxes and other resources are properly released.
5680
+ */
5681
+ async close() {
5682
+ if (this._codeExecutor) {
5683
+ await this._codeExecutor.cleanup();
5684
+ this._codeExecutor = null;
5685
+ }
5686
+ await this.closeAllSessions();
3239
5687
  }
3240
5688
  };
3241
5689
 
@@ -3903,6 +6351,26 @@ var import_zod8 = require("zod");
3903
6351
  init_logging();
3904
6352
  var API_CHATS_ENDPOINT = "/api/v1/chats";
3905
6353
  var API_CHAT_EXECUTE_ENDPOINT = "/api/v1/chats/{chat_id}/execute";
6354
+ function normalizeRemoteRunOptions(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
6355
+ if (typeof queryOrOptions === "object" && queryOrOptions !== null) {
6356
+ const options = queryOrOptions;
6357
+ return {
6358
+ query: options.prompt,
6359
+ maxSteps: options.maxSteps,
6360
+ manageConnector: options.manageConnector,
6361
+ externalHistory: options.externalHistory,
6362
+ outputSchema: options.schema
6363
+ };
6364
+ }
6365
+ return {
6366
+ query: queryOrOptions,
6367
+ maxSteps,
6368
+ manageConnector,
6369
+ externalHistory,
6370
+ outputSchema
6371
+ };
6372
+ }
6373
+ __name(normalizeRemoteRunOptions, "normalizeRemoteRunOptions");
3906
6374
  var RemoteAgent = class {
3907
6375
  static {
3908
6376
  __name(this, "RemoteAgent");
@@ -3999,8 +6467,20 @@ var RemoteAgent = class {
3999
6467
  throw new Error(`Failed to create chat session: ${String(e)}`);
4000
6468
  }
4001
6469
  }
4002
- async run(query, maxSteps, manageConnector, externalHistory, outputSchema) {
4003
- if (externalHistory !== void 0) {
6470
+ async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
6471
+ const {
6472
+ query,
6473
+ maxSteps: steps,
6474
+ externalHistory: history,
6475
+ outputSchema: schema
6476
+ } = normalizeRemoteRunOptions(
6477
+ queryOrOptions,
6478
+ maxSteps,
6479
+ manageConnector,
6480
+ externalHistory,
6481
+ outputSchema
6482
+ );
6483
+ if (history !== void 0) {
4004
6484
  logger.warn("External history is not yet supported for remote execution");
4005
6485
  }
4006
6486
  try {
@@ -4011,10 +6491,10 @@ var RemoteAgent = class {
4011
6491
  const chatId = this.chatId;
4012
6492
  const executionPayload = {
4013
6493
  query,
4014
- max_steps: maxSteps ?? 10
6494
+ max_steps: steps ?? 10
4015
6495
  };
4016
- if (outputSchema) {
4017
- executionPayload.output_schema = this.pydanticToJsonSchema(outputSchema);
6496
+ if (schema) {
6497
+ executionPayload.output_schema = this.pydanticToJsonSchema(schema);
4018
6498
  logger.info(`\u{1F527} Using structured output with schema`);
4019
6499
  }
4020
6500
  const headers = {
@@ -4088,8 +6568,8 @@ Raw error: ${result}`
4088
6568
  );
4089
6569
  }
4090
6570
  }
4091
- if (outputSchema) {
4092
- return this.parseStructuredResponse(result, outputSchema);
6571
+ if (schema) {
6572
+ return this.parseStructuredResponse(result, schema);
4093
6573
  }
4094
6574
  if (typeof result === "object" && result !== null && "result" in result) {
4095
6575
  return result.result;
@@ -4114,9 +6594,9 @@ Raw error: ${result}`
4114
6594
  }
4115
6595
  }
4116
6596
  // eslint-disable-next-line require-yield
4117
- async *stream(query, maxSteps, manageConnector, externalHistory, outputSchema) {
6597
+ async *stream(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
4118
6598
  const result = await this.run(
4119
- query,
6599
+ queryOrOptions,
4120
6600
  maxSteps,
4121
6601
  manageConnector,
4122
6602
  externalHistory,
@@ -4129,7 +6609,153 @@ Raw error: ${result}`
4129
6609
  }
4130
6610
  };
4131
6611
 
6612
+ // src/agents/utils/llm_provider.ts
6613
+ init_logging();
6614
+ var PROVIDER_CONFIG = {
6615
+ openai: {
6616
+ package: "@langchain/openai",
6617
+ className: "ChatOpenAI",
6618
+ envVars: ["OPENAI_API_KEY"],
6619
+ defaultModel: "gpt-4o"
6620
+ },
6621
+ anthropic: {
6622
+ package: "@langchain/anthropic",
6623
+ className: "ChatAnthropic",
6624
+ envVars: ["ANTHROPIC_API_KEY"],
6625
+ defaultModel: "claude-3-5-sonnet-20241022"
6626
+ },
6627
+ google: {
6628
+ package: "@langchain/google-genai",
6629
+ className: "ChatGoogleGenerativeAI",
6630
+ envVars: ["GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
6631
+ defaultModel: "gemini-pro"
6632
+ },
6633
+ groq: {
6634
+ package: "@langchain/groq",
6635
+ className: "ChatGroq",
6636
+ envVars: ["GROQ_API_KEY"],
6637
+ defaultModel: "llama-3.1-70b-versatile"
6638
+ }
6639
+ };
6640
+ function parseLLMString(llmString) {
6641
+ const parts = llmString.split("/");
6642
+ if (parts.length !== 2) {
6643
+ throw new Error(
6644
+ `Invalid LLM string format. Expected 'provider/model', got '${llmString}'. Examples: 'openai/gpt-4', 'anthropic/claude-3-5-sonnet-20241022', 'google/gemini-pro', 'groq/llama-3.1-70b-versatile'`
6645
+ );
6646
+ }
6647
+ const [provider, model] = parts;
6648
+ if (!provider || !model) {
6649
+ throw new Error(
6650
+ `Invalid LLM string format. Both provider and model must be non-empty. Got '${llmString}'`
6651
+ );
6652
+ }
6653
+ const normalizedProvider = provider.toLowerCase();
6654
+ if (!(normalizedProvider in PROVIDER_CONFIG)) {
6655
+ const supportedProviders = Object.keys(PROVIDER_CONFIG).join(", ");
6656
+ throw new Error(
6657
+ `Unsupported LLM provider '${provider}'. Supported providers: ${supportedProviders}`
6658
+ );
6659
+ }
6660
+ return { provider: normalizedProvider, model };
6661
+ }
6662
+ __name(parseLLMString, "parseLLMString");
6663
+ function getAPIKey(provider, config) {
6664
+ if (config?.apiKey) {
6665
+ return config.apiKey;
6666
+ }
6667
+ const providerConfig = PROVIDER_CONFIG[provider];
6668
+ for (const envVar of providerConfig.envVars) {
6669
+ const apiKey = process.env[envVar];
6670
+ if (apiKey) {
6671
+ logger.debug(
6672
+ `Using API key from environment variable ${envVar} for provider ${provider}`
6673
+ );
6674
+ return apiKey;
6675
+ }
6676
+ }
6677
+ const envVarsStr = providerConfig.envVars.join(" or ");
6678
+ throw new Error(
6679
+ `API key not found for provider '${provider}'. Set ${envVarsStr} environment variable or pass apiKey in llmConfig. Example: new MCPAgent({ llm: '${provider}/model', llmConfig: { apiKey: 'your-key' } })`
6680
+ );
6681
+ }
6682
+ __name(getAPIKey, "getAPIKey");
6683
+ async function createLLMFromString(llmString, config) {
6684
+ logger.info(`Creating LLM from string: ${llmString}`);
6685
+ const { provider, model } = parseLLMString(llmString);
6686
+ const providerConfig = PROVIDER_CONFIG[provider];
6687
+ const apiKey = getAPIKey(provider, config);
6688
+ let providerModule;
6689
+ try {
6690
+ logger.debug(`Importing package ${providerConfig.package}...`);
6691
+ providerModule = await import(providerConfig.package);
6692
+ } catch (error) {
6693
+ if (error?.code === "MODULE_NOT_FOUND" || error?.message?.includes("Cannot find module") || error?.message?.includes("Cannot find package")) {
6694
+ throw new Error(
6695
+ `Package '${providerConfig.package}' is not installed. Install it with: npm install ${providerConfig.package} or yarn add ${providerConfig.package}`
6696
+ );
6697
+ }
6698
+ throw new Error(
6699
+ `Failed to import ${providerConfig.package}: ${error?.message || error}`
6700
+ );
6701
+ }
6702
+ const LLMClass = providerModule[providerConfig.className];
6703
+ if (!LLMClass) {
6704
+ throw new Error(
6705
+ `Could not find ${providerConfig.className} in package ${providerConfig.package}. This might be a version compatibility issue.`
6706
+ );
6707
+ }
6708
+ const llmConfig = {
6709
+ model,
6710
+ apiKey,
6711
+ ...config
6712
+ };
6713
+ if (config?.apiKey) {
6714
+ delete llmConfig.apiKey;
6715
+ llmConfig.apiKey = apiKey;
6716
+ }
6717
+ if (provider === "anthropic") {
6718
+ llmConfig.model = model;
6719
+ } else if (provider === "google") {
6720
+ llmConfig.model = model;
6721
+ } else if (provider === "openai") {
6722
+ llmConfig.model = model;
6723
+ } else if (provider === "groq") {
6724
+ llmConfig.model = model;
6725
+ }
6726
+ try {
6727
+ const llmInstance = new LLMClass(llmConfig);
6728
+ logger.info(`Successfully created ${provider} LLM with model ${model}`);
6729
+ return llmInstance;
6730
+ } catch (error) {
6731
+ throw new Error(
6732
+ `Failed to instantiate ${providerConfig.className} with model '${model}': ${error?.message || error}`
6733
+ );
6734
+ }
6735
+ }
6736
+ __name(createLLMFromString, "createLLMFromString");
6737
+
4132
6738
  // src/agents/mcp_agent.ts
6739
+ function normalizeRunOptions(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
6740
+ if (typeof queryOrOptions === "object" && queryOrOptions !== null) {
6741
+ const options = queryOrOptions;
6742
+ return {
6743
+ query: options.prompt,
6744
+ maxSteps: options.maxSteps,
6745
+ manageConnector: options.manageConnector,
6746
+ externalHistory: options.externalHistory,
6747
+ outputSchema: options.schema
6748
+ };
6749
+ }
6750
+ return {
6751
+ query: queryOrOptions,
6752
+ maxSteps,
6753
+ manageConnector,
6754
+ externalHistory,
6755
+ outputSchema
6756
+ };
6757
+ }
6758
+ __name(normalizeRunOptions, "normalizeRunOptions");
4133
6759
  var MCPAgent = class {
4134
6760
  static {
4135
6761
  __name(this, "MCPAgent");
@@ -4175,6 +6801,12 @@ var MCPAgent = class {
4175
6801
  // Remote agent support
4176
6802
  isRemote = false;
4177
6803
  remoteAgent = null;
6804
+ // Simplified mode support
6805
+ isSimplifiedMode = false;
6806
+ llmString;
6807
+ llmConfig;
6808
+ mcpServersConfig;
6809
+ clientOwnedByAgent = false;
4178
6810
  constructor(options) {
4179
6811
  if (options.agentId) {
4180
6812
  this.isRemote = true;
@@ -4208,9 +6840,36 @@ var MCPAgent = class {
4208
6840
  "llm is required for local execution. For remote execution, provide agentId instead."
4209
6841
  );
4210
6842
  }
4211
- this.llm = options.llm;
4212
- this.client = options.client;
4213
- this.connectors = options.connectors ?? [];
6843
+ const isSimplifiedMode = typeof options.llm === "string";
6844
+ if (isSimplifiedMode) {
6845
+ this.isSimplifiedMode = true;
6846
+ this.llmString = options.llm;
6847
+ this.llmConfig = options.llmConfig;
6848
+ this.mcpServersConfig = options.mcpServers;
6849
+ if (!this.mcpServersConfig || Object.keys(this.mcpServersConfig).length === 0) {
6850
+ throw new Error(
6851
+ "Simplified mode requires 'mcpServers' configuration. Provide an object with server configurations, e.g., { filesystem: { command: 'npx', args: [...] } }"
6852
+ );
6853
+ }
6854
+ this.llm = void 0;
6855
+ this.client = void 0;
6856
+ this.clientOwnedByAgent = true;
6857
+ this.connectors = [];
6858
+ logger.info(
6859
+ `\u{1F3AF} Simplified mode enabled: LLM will be created from '${this.llmString}'`
6860
+ );
6861
+ } else {
6862
+ this.isSimplifiedMode = false;
6863
+ this.llm = options.llm;
6864
+ this.client = options.client;
6865
+ this.connectors = options.connectors ?? [];
6866
+ this.clientOwnedByAgent = false;
6867
+ if (!this.client && this.connectors.length === 0) {
6868
+ throw new Error(
6869
+ "Explicit mode requires either 'client' or at least one 'connector'. Alternatively, use simplified mode with 'llm' as a string and 'mcpServers' config."
6870
+ );
6871
+ }
6872
+ }
4214
6873
  this.maxSteps = options.maxSteps ?? 5;
4215
6874
  this.autoInitialize = options.autoInitialize ?? false;
4216
6875
  this.memoryEnabled = options.memoryEnabled ?? true;
@@ -4223,28 +6882,30 @@ var MCPAgent = class {
4223
6882
  this.useServerManager = options.useServerManager ?? false;
4224
6883
  this.verbose = options.verbose ?? false;
4225
6884
  this.observe = options.observe ?? true;
4226
- if (!this.client && this.connectors.length === 0) {
4227
- throw new Error(
4228
- "Either 'client' or at least one 'connector' must be provided."
4229
- );
4230
- }
4231
- if (this.useServerManager) {
4232
- if (!this.client) {
4233
- throw new Error(
4234
- "'client' must be provided when 'useServerManager' is true."
4235
- );
6885
+ if (!this.isSimplifiedMode) {
6886
+ if (this.useServerManager) {
6887
+ if (!this.client) {
6888
+ throw new Error(
6889
+ "'client' must be provided when 'useServerManager' is true."
6890
+ );
6891
+ }
6892
+ this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
6893
+ this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
6894
+ } else {
6895
+ this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
6896
+ }
6897
+ this.telemetry = Telemetry.getInstance();
6898
+ if (this.llm) {
6899
+ const [provider, name] = extractModelInfo(this.llm);
6900
+ this.modelProvider = provider;
6901
+ this.modelName = name;
6902
+ } else {
6903
+ this.modelProvider = "unknown";
6904
+ this.modelName = "unknown";
4236
6905
  }
4237
- this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
4238
- this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
4239
6906
  } else {
4240
6907
  this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
4241
- }
4242
- this.telemetry = Telemetry.getInstance();
4243
- if (this.llm) {
4244
- const [provider, name] = extractModelInfo(this.llm);
4245
- this.modelProvider = provider;
4246
- this.modelName = name;
4247
- } else {
6908
+ this.telemetry = Telemetry.getInstance();
4248
6909
  this.modelProvider = "unknown";
4249
6910
  this.modelName = "unknown";
4250
6911
  }
@@ -4275,6 +6936,40 @@ var MCPAgent = class {
4275
6936
  return;
4276
6937
  }
4277
6938
  logger.info("\u{1F680} Initializing MCP agent and connecting to services...");
6939
+ if (this.isSimplifiedMode) {
6940
+ logger.info(
6941
+ "\u{1F3AF} Simplified mode: Creating client and LLM from configuration..."
6942
+ );
6943
+ if (this.mcpServersConfig) {
6944
+ logger.info(
6945
+ `Creating MCPClient with ${Object.keys(this.mcpServersConfig).length} server(s)...`
6946
+ );
6947
+ this.client = new MCPClient({ mcpServers: this.mcpServersConfig });
6948
+ logger.info("\u2705 MCPClient created successfully");
6949
+ }
6950
+ if (this.llmString) {
6951
+ logger.info(`Creating LLM from string: ${this.llmString}...`);
6952
+ try {
6953
+ this.llm = await createLLMFromString(this.llmString, this.llmConfig);
6954
+ logger.info("\u2705 LLM created successfully");
6955
+ const [provider, name] = extractModelInfo(this.llm);
6956
+ this.modelProvider = provider;
6957
+ this.modelName = name;
6958
+ } catch (error) {
6959
+ throw new Error(
6960
+ `Failed to create LLM from string '${this.llmString}': ${error?.message || error}`
6961
+ );
6962
+ }
6963
+ }
6964
+ if (this.useServerManager) {
6965
+ if (!this.client) {
6966
+ throw new Error(
6967
+ "'client' must be available when 'useServerManager' is true."
6968
+ );
6969
+ }
6970
+ this.serverManager = new ServerManager(this.client, this.adapter);
6971
+ }
6972
+ }
4278
6973
  this.callbacks = await this.observabilityManager.getCallbacks();
4279
6974
  const handlerNames = await this.observabilityManager.getHandlerNames();
4280
6975
  if (handlerNames.length > 0) {
@@ -4817,33 +7512,47 @@ var MCPAgent = class {
4817
7512
  }
4818
7513
  }
4819
7514
  }
4820
- async run(query, maxSteps, manageConnector, externalHistory, outputSchema) {
4821
- if (this.isRemote && this.remoteAgent) {
4822
- return this.remoteAgent.run(
4823
- query,
4824
- maxSteps,
4825
- manageConnector,
4826
- externalHistory,
4827
- outputSchema
4828
- );
4829
- }
4830
- const generator = this.stream(
7515
+ async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
7516
+ const {
4831
7517
  query,
7518
+ maxSteps: steps,
7519
+ manageConnector: manage,
7520
+ externalHistory: history,
7521
+ outputSchema: schema
7522
+ } = normalizeRunOptions(
7523
+ queryOrOptions,
4832
7524
  maxSteps,
4833
7525
  manageConnector,
4834
7526
  externalHistory,
4835
7527
  outputSchema
4836
7528
  );
7529
+ if (this.isRemote && this.remoteAgent) {
7530
+ return this.remoteAgent.run(query, steps, manage, history, schema);
7531
+ }
7532
+ const generator = this.stream(query, steps, manage, history, schema);
4837
7533
  return this._consumeAndReturn(generator);
4838
7534
  }
4839
- async *stream(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
7535
+ async *stream(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
7536
+ const {
7537
+ query,
7538
+ maxSteps: steps,
7539
+ manageConnector: manage,
7540
+ externalHistory: history,
7541
+ outputSchema: schema
7542
+ } = normalizeRunOptions(
7543
+ queryOrOptions,
7544
+ maxSteps,
7545
+ manageConnector,
7546
+ externalHistory,
7547
+ outputSchema
7548
+ );
4840
7549
  if (this.isRemote && this.remoteAgent) {
4841
7550
  const result = await this.remoteAgent.run(
4842
7551
  query,
4843
- maxSteps,
4844
- manageConnector,
4845
- externalHistory,
4846
- outputSchema
7552
+ steps,
7553
+ manage,
7554
+ history,
7555
+ schema
4847
7556
  );
4848
7557
  return result;
4849
7558
  }
@@ -4853,7 +7562,7 @@ var MCPAgent = class {
4853
7562
  let finalOutput = null;
4854
7563
  let stepsTaken = 0;
4855
7564
  try {
4856
- if (manageConnector && !this._initialized) {
7565
+ if (manage && !this._initialized) {
4857
7566
  await this.initialize();
4858
7567
  initializedHere = true;
4859
7568
  } else if (!this._initialized && this.autoInitialize) {
@@ -4877,7 +7586,7 @@ var MCPAgent = class {
4877
7586
  this._agentExecutor = this.createAgent();
4878
7587
  }
4879
7588
  }
4880
- const historyToUse = externalHistory ?? this.conversationHistory;
7589
+ const historyToUse = history ?? this.conversationHistory;
4881
7590
  const langchainHistory = [];
4882
7591
  for (const msg of historyToUse) {
4883
7592
  if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
@@ -5018,13 +7727,13 @@ var MCPAgent = class {
5018
7727
  this.addToHistory(msg);
5019
7728
  }
5020
7729
  }
5021
- if (outputSchema && finalOutput) {
7730
+ if (schema && finalOutput) {
5022
7731
  try {
5023
7732
  logger.info("\u{1F527} Attempting structured output...");
5024
7733
  const structuredResult = await this._attemptStructuredOutput(
5025
7734
  finalOutput,
5026
7735
  this.llm,
5027
- outputSchema
7736
+ schema
5028
7737
  );
5029
7738
  if (this.memoryEnabled) {
5030
7739
  this.addToHistory(
@@ -5050,7 +7759,7 @@ var MCPAgent = class {
5050
7759
  return finalOutput || "No output generated";
5051
7760
  } catch (e) {
5052
7761
  logger.error(`\u274C Error running query: ${e}`);
5053
- if (initializedHere && manageConnector) {
7762
+ if (initializedHere && manage) {
5054
7763
  logger.info("\u{1F9F9} Cleaning up resources after error");
5055
7764
  await this.close();
5056
7765
  }
@@ -5080,9 +7789,9 @@ var MCPAgent = class {
5080
7789
  maxStepsConfigured: this.maxSteps,
5081
7790
  memoryEnabled: this.memoryEnabled,
5082
7791
  useServerManager: this.useServerManager,
5083
- maxStepsUsed: maxSteps ?? null,
5084
- manageConnector,
5085
- externalHistoryUsed: externalHistory !== void 0,
7792
+ maxStepsUsed: steps ?? null,
7793
+ manageConnector: manage ?? true,
7794
+ externalHistoryUsed: history !== void 0,
5086
7795
  stepsTaken,
5087
7796
  toolsUsedCount: this.toolsUsedNames.length,
5088
7797
  toolsUsedNames: this.toolsUsedNames,
@@ -5091,7 +7800,7 @@ var MCPAgent = class {
5091
7800
  errorType: success ? null : "execution_error",
5092
7801
  conversationHistoryLength
5093
7802
  });
5094
- if (manageConnector && !this.client && initializedHere) {
7803
+ if (manage && !this.client && initializedHere) {
5095
7804
  logger.info("\u{1F9F9} Closing agent after stream completion");
5096
7805
  await this.close();
5097
7806
  }
@@ -5119,15 +7828,28 @@ var MCPAgent = class {
5119
7828
  this._agentExecutor = null;
5120
7829
  this._tools = [];
5121
7830
  if (this.client) {
5122
- logger.info("\u{1F504} Closing client and cleaning up resources");
5123
- await this.client.close();
5124
- this.sessions = {};
7831
+ if (this.clientOwnedByAgent) {
7832
+ logger.info(
7833
+ "\u{1F504} Closing internally-created client (simplified mode) and cleaning up resources"
7834
+ );
7835
+ await this.client.close();
7836
+ this.sessions = {};
7837
+ this.client = void 0;
7838
+ } else {
7839
+ logger.info("\u{1F504} Closing client and cleaning up resources");
7840
+ await this.client.close();
7841
+ this.sessions = {};
7842
+ }
5125
7843
  } else {
5126
7844
  for (const connector of this.connectors) {
5127
7845
  logger.info("\u{1F504} Disconnecting connector");
5128
7846
  await connector.disconnect();
5129
7847
  }
5130
7848
  }
7849
+ if (this.isSimplifiedMode && this.llm) {
7850
+ logger.debug("\u{1F504} Clearing LLM reference (simplified mode)");
7851
+ this.llm = void 0;
7852
+ }
5131
7853
  if ("connectorToolMap" in this.adapter) {
5132
7854
  this.adapter = new LangChainAdapter();
5133
7855
  }
@@ -5136,16 +7858,12 @@ var MCPAgent = class {
5136
7858
  logger.info("\u{1F44B} Agent closed successfully");
5137
7859
  }
5138
7860
  }
5139
- /**
5140
- * Yields with pretty-printed output for code mode.
5141
- * This method formats and displays tool executions in a user-friendly way with syntax highlighting.
5142
- */
5143
- async *prettyStreamEvents(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
7861
+ async *prettyStreamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
5144
7862
  const { prettyStreamEvents: prettyStream } = await Promise.resolve().then(() => (init_display(), display_exports));
5145
7863
  const finalResponse = "";
5146
7864
  for await (const _ of prettyStream(
5147
7865
  this.streamEvents(
5148
- query,
7866
+ queryOrOptions,
5149
7867
  maxSteps,
5150
7868
  manageConnector,
5151
7869
  externalHistory,
@@ -5156,22 +7874,32 @@ var MCPAgent = class {
5156
7874
  }
5157
7875
  return finalResponse;
5158
7876
  }
5159
- /**
5160
- * Yields LangChain StreamEvent objects from the underlying streamEvents() method.
5161
- * This provides token-level streaming and fine-grained event updates.
5162
- */
5163
- async *streamEvents(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
7877
+ async *streamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
7878
+ const normalized = normalizeRunOptions(
7879
+ queryOrOptions,
7880
+ maxSteps,
7881
+ manageConnector,
7882
+ externalHistory,
7883
+ outputSchema
7884
+ );
7885
+ let { query } = normalized;
7886
+ const {
7887
+ maxSteps: steps,
7888
+ manageConnector: manage,
7889
+ externalHistory: history,
7890
+ outputSchema: schema
7891
+ } = normalized;
5164
7892
  let initializedHere = false;
5165
7893
  const startTime = Date.now();
5166
7894
  let success = false;
5167
7895
  let eventCount = 0;
5168
7896
  let totalResponseLength = 0;
5169
7897
  let finalResponse = "";
5170
- if (outputSchema) {
5171
- query = this._enhanceQueryWithSchema(query, outputSchema);
7898
+ if (schema) {
7899
+ query = this._enhanceQueryWithSchema(query, schema);
5172
7900
  }
5173
7901
  try {
5174
- if (manageConnector && !this._initialized) {
7902
+ if (manage && !this._initialized) {
5175
7903
  await this.initialize();
5176
7904
  initializedHere = true;
5177
7905
  } else if (!this._initialized && this.autoInitialize) {
@@ -5182,14 +7910,14 @@ var MCPAgent = class {
5182
7910
  if (!agentExecutor) {
5183
7911
  throw new Error("MCP agent failed to initialize");
5184
7912
  }
5185
- this.maxSteps = maxSteps ?? this.maxSteps;
7913
+ this.maxSteps = steps ?? this.maxSteps;
5186
7914
  const display_query = typeof query === "string" && query.length > 50 ? `${query.slice(0, 50).replace(/\n/g, " ")}...` : typeof query === "string" ? query.replace(/\n/g, " ") : String(query);
5187
7915
  logger.info(`\u{1F4AC} Received query for streamEvents: '${display_query}'`);
5188
7916
  if (this.memoryEnabled) {
5189
7917
  logger.info(`\u{1F504} Adding user message to history: ${display_query}`);
5190
7918
  this.addToHistory(new import_langchain2.HumanMessage({ content: query }));
5191
7919
  }
5192
- const historyToUse = externalHistory ?? this.conversationHistory;
7920
+ const historyToUse = history ?? this.conversationHistory;
5193
7921
  const langchainHistory = [];
5194
7922
  for (const msg of historyToUse) {
5195
7923
  if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
@@ -5256,17 +7984,13 @@ var MCPAgent = class {
5256
7984
  }
5257
7985
  }
5258
7986
  }
5259
- if (outputSchema && finalResponse) {
7987
+ if (schema && finalResponse) {
5260
7988
  logger.info("\u{1F527} Attempting structured output conversion...");
5261
7989
  try {
5262
7990
  let conversionCompleted = false;
5263
7991
  let conversionResult = null;
5264
7992
  let conversionError = null;
5265
- this._attemptStructuredOutput(
5266
- finalResponse,
5267
- this.llm,
5268
- outputSchema
5269
- ).then((result) => {
7993
+ this._attemptStructuredOutput(finalResponse, this.llm, schema).then((result) => {
5270
7994
  conversionCompleted = true;
5271
7995
  conversionResult = result;
5272
7996
  return result;
@@ -5321,7 +8045,7 @@ var MCPAgent = class {
5321
8045
  success = true;
5322
8046
  } catch (e) {
5323
8047
  logger.error(`\u274C Error during streamEvents: ${e}`);
5324
- if (initializedHere && manageConnector) {
8048
+ if (initializedHere && manage) {
5325
8049
  logger.info(
5326
8050
  "\u{1F9F9} Cleaning up resources after initialization error in streamEvents"
5327
8051
  );
@@ -5352,15 +8076,15 @@ var MCPAgent = class {
5352
8076
  maxStepsConfigured: this.maxSteps,
5353
8077
  memoryEnabled: this.memoryEnabled,
5354
8078
  useServerManager: this.useServerManager,
5355
- maxStepsUsed: maxSteps ?? null,
5356
- manageConnector,
5357
- externalHistoryUsed: externalHistory !== void 0,
8079
+ maxStepsUsed: steps ?? null,
8080
+ manageConnector: manage ?? true,
8081
+ externalHistoryUsed: history !== void 0,
5358
8082
  response: `[STREAMED RESPONSE - ${totalResponseLength} chars]`,
5359
8083
  executionTimeMs,
5360
8084
  errorType: success ? null : "streaming_error",
5361
8085
  conversationHistoryLength
5362
8086
  });
5363
- if (manageConnector && !this.client && initializedHere) {
8087
+ if (manage && !this.client && initializedHere) {
5364
8088
  logger.info("\u{1F9F9} Closing agent after streamEvents completion");
5365
8089
  await this.close();
5366
8090
  }