mcp-use 1.10.6 → 1.11.0-canary.11

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 (140) hide show
  1. package/README.md +1 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/{chunk-KIWNNI6F.js → chunk-2NE5H4KG.js} +16 -2
  4. package/dist/{chunk-D5WOXLJ2.js → chunk-4QWS5ME6.js} +171 -11
  5. package/dist/chunk-7P2EMREO.js +101 -0
  6. package/dist/chunk-7PSUUT4A.js +1055 -0
  7. package/dist/{chunk-44DFBJUL.js → chunk-BOCIQYWG.js} +196 -496
  8. package/dist/chunk-BPZJIV4V.js +1873 -0
  9. package/dist/{chunk-EEUJZMOP.js → chunk-CVKKDXI3.js} +1 -1
  10. package/dist/chunk-DPK5NHDR.js +12 -0
  11. package/dist/{chunk-FDKY2O5P.js → chunk-EHCLF3JO.js} +443 -969
  12. package/dist/{chunk-34R6SIER.js → chunk-FRUZDWXH.js} +1 -1
  13. package/dist/chunk-GXNAXUDI.js +0 -0
  14. package/dist/{chunk-JH3ZOGLI.js → chunk-J3WTIYVV.js} +2 -2
  15. package/dist/{chunk-CPG2WZUL.js → chunk-JRGQRPTN.js} +1 -1
  16. package/dist/chunk-MFSO5PUW.js +1049 -0
  17. package/dist/chunk-SQSJ5NKY.js +1055 -0
  18. package/dist/chunk-T4EDAWDS.js +2638 -0
  19. package/dist/chunk-UWWLWLS2.js +62 -0
  20. package/dist/{chunk-BLWPCOUZ.js → chunk-V4YUDB7N.js} +3 -8
  21. package/dist/index.cjs +5065 -4608
  22. package/dist/index.d.ts +2 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +46 -1061
  25. package/dist/{langfuse-N5Y5BSXK.js → langfuse-74RGPTAH.js} +2 -2
  26. package/dist/notifications-FLGIFS56.js +9 -0
  27. package/dist/src/adapters/base.d.ts +44 -0
  28. package/dist/src/adapters/base.d.ts.map +1 -1
  29. package/dist/src/adapters/index.cjs +1346 -0
  30. package/dist/src/adapters/index.js +11 -0
  31. package/dist/src/adapters/langchain_adapter.d.ts +12 -1
  32. package/dist/src/adapters/langchain_adapter.d.ts.map +1 -1
  33. package/dist/src/agents/index.cjs +3141 -159
  34. package/dist/src/agents/index.d.ts +2 -0
  35. package/dist/src/agents/index.d.ts.map +1 -1
  36. package/dist/src/agents/index.js +12 -8
  37. package/dist/src/agents/mcp_agent.d.ts +59 -37
  38. package/dist/src/agents/mcp_agent.d.ts.map +1 -1
  39. package/dist/src/agents/remote.d.ts +25 -0
  40. package/dist/src/agents/remote.d.ts.map +1 -1
  41. package/dist/src/agents/types.d.ts +76 -0
  42. package/dist/src/agents/types.d.ts.map +1 -1
  43. package/dist/src/agents/utils/index.d.ts +1 -0
  44. package/dist/src/agents/utils/index.d.ts.map +1 -1
  45. package/dist/src/agents/utils/llm_provider.d.ts +53 -0
  46. package/dist/src/agents/utils/llm_provider.d.ts.map +1 -0
  47. package/dist/src/browser.cjs +1856 -423
  48. package/dist/src/browser.d.ts +1 -2
  49. package/dist/src/browser.d.ts.map +1 -1
  50. package/dist/src/browser.js +30 -19
  51. package/dist/src/client/base.d.ts +1 -0
  52. package/dist/src/client/base.d.ts.map +1 -1
  53. package/dist/src/client/browser.d.ts +2 -2
  54. package/dist/src/client/browser.d.ts.map +1 -1
  55. package/dist/src/client/prompts.cjs +1 -1
  56. package/dist/src/client/prompts.js +5 -4
  57. package/dist/src/client.cjs +3788 -0
  58. package/dist/src/client.d.ts +2 -0
  59. package/dist/src/client.d.ts.map +1 -1
  60. package/dist/src/client.js +23 -0
  61. package/dist/src/config.d.ts.map +1 -1
  62. package/dist/src/connectors/base.d.ts +8 -0
  63. package/dist/src/connectors/base.d.ts.map +1 -1
  64. package/dist/src/connectors/index.d.ts +0 -1
  65. package/dist/src/connectors/index.d.ts.map +1 -1
  66. package/dist/src/managers/server_manager.d.ts.map +1 -1
  67. package/dist/src/managers/tools/connect_mcp_server.d.ts.map +1 -1
  68. package/dist/src/react/index.cjs +259 -298
  69. package/dist/src/react/index.js +9 -8
  70. package/dist/src/react/types.d.ts +42 -4
  71. package/dist/src/react/types.d.ts.map +1 -1
  72. package/dist/src/react/useMcp.d.ts.map +1 -1
  73. package/dist/src/react/useWidget.d.ts +11 -7
  74. package/dist/src/react/useWidget.d.ts.map +1 -1
  75. package/dist/src/react/widget-types.d.ts +6 -2
  76. package/dist/src/react/widget-types.d.ts.map +1 -1
  77. package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
  78. package/dist/src/server/index.cjs +1288 -140
  79. package/dist/src/server/index.d.ts +2 -0
  80. package/dist/src/server/index.d.ts.map +1 -1
  81. package/dist/src/server/index.js +1183 -102
  82. package/dist/src/server/mcp-server.d.ts +5 -1
  83. package/dist/src/server/mcp-server.d.ts.map +1 -1
  84. package/dist/src/server/notifications/index.d.ts +1 -1
  85. package/dist/src/server/notifications/index.d.ts.map +1 -1
  86. package/dist/src/server/notifications/notification-registration.d.ts +51 -0
  87. package/dist/src/server/notifications/notification-registration.d.ts.map +1 -1
  88. package/dist/src/server/sessions/index.d.ts +3 -1
  89. package/dist/src/server/sessions/index.d.ts.map +1 -1
  90. package/dist/src/server/sessions/session-manager.d.ts +36 -19
  91. package/dist/src/server/sessions/session-manager.d.ts.map +1 -1
  92. package/dist/src/server/sessions/stores/filesystem.d.ts +121 -0
  93. package/dist/src/server/sessions/stores/filesystem.d.ts.map +1 -0
  94. package/dist/src/server/sessions/stores/index.d.ts +94 -0
  95. package/dist/src/server/sessions/stores/index.d.ts.map +1 -0
  96. package/dist/src/server/sessions/stores/memory.d.ts +82 -0
  97. package/dist/src/server/sessions/stores/memory.d.ts.map +1 -0
  98. package/dist/src/server/sessions/stores/redis.d.ts +164 -0
  99. package/dist/src/server/sessions/stores/redis.d.ts.map +1 -0
  100. package/dist/src/server/sessions/streams/index.d.ts +77 -0
  101. package/dist/src/server/sessions/streams/index.d.ts.map +1 -0
  102. package/dist/src/server/sessions/streams/memory.d.ts +76 -0
  103. package/dist/src/server/sessions/streams/memory.d.ts.map +1 -0
  104. package/dist/src/server/sessions/streams/redis.d.ts +146 -0
  105. package/dist/src/server/sessions/streams/redis.d.ts.map +1 -0
  106. package/dist/src/server/types/common.d.ts +105 -28
  107. package/dist/src/server/types/common.d.ts.map +1 -1
  108. package/dist/src/server/types/resource.d.ts +16 -0
  109. package/dist/src/server/types/resource.d.ts.map +1 -1
  110. package/dist/src/server/types/widget.d.ts +21 -2
  111. package/dist/src/server/types/widget.d.ts.map +1 -1
  112. package/dist/src/server/utils/response-helpers.d.ts +12 -6
  113. package/dist/src/server/utils/response-helpers.d.ts.map +1 -1
  114. package/dist/src/server/widgets/index.d.ts +1 -1
  115. package/dist/src/server/widgets/index.d.ts.map +1 -1
  116. package/dist/src/server/widgets/mount-widgets-dev.d.ts.map +1 -1
  117. package/dist/src/server/widgets/setup-widget-routes.d.ts.map +1 -1
  118. package/dist/src/server/widgets/ui-resource-registration.d.ts.map +1 -1
  119. package/dist/src/server/widgets/widget-helpers.d.ts +22 -0
  120. package/dist/src/server/widgets/widget-helpers.d.ts.map +1 -1
  121. package/dist/src/server/widgets/widget-types.d.ts +2 -0
  122. package/dist/src/server/widgets/widget-types.d.ts.map +1 -1
  123. package/dist/src/session.d.ts +16 -2
  124. package/dist/src/session.d.ts.map +1 -1
  125. package/dist/src/task_managers/index.d.ts +10 -1
  126. package/dist/src/task_managers/index.d.ts.map +1 -1
  127. package/dist/src/task_managers/sse.d.ts +34 -1
  128. package/dist/src/task_managers/sse.d.ts.map +1 -1
  129. package/dist/src/task_managers/streamable_http.d.ts +8 -2
  130. package/dist/src/task_managers/streamable_http.d.ts.map +1 -1
  131. package/dist/src/version.d.ts +1 -1
  132. package/dist/src/version.d.ts.map +1 -1
  133. package/dist/{tool-execution-helpers-4X6A63AS.js → tool-execution-helpers-3BYYGIA5.js} +3 -3
  134. package/dist/tsup.config.d.ts.map +1 -1
  135. package/package.json +47 -14
  136. package/dist/src/connectors/websocket.d.ts +0 -38
  137. package/dist/src/connectors/websocket.d.ts.map +0 -1
  138. package/dist/src/task_managers/websocket.d.ts +0 -18
  139. package/dist/src/task_managers/websocket.d.ts.map +0 -1
  140. /package/dist/{chunk-EW4MJSHA.js → chunk-LGDFGYRL.js} +0 -0
@@ -0,0 +1,3788 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/client.ts
32
+ var client_exports = {};
33
+ __export(client_exports, {
34
+ BaseCodeExecutor: () => BaseCodeExecutor,
35
+ E2BCodeExecutor: () => E2BCodeExecutor,
36
+ MCPClient: () => MCPClient,
37
+ MCPSession: () => MCPSession,
38
+ VMCodeExecutor: () => VMCodeExecutor,
39
+ isVMAvailable: () => isVMAvailable
40
+ });
41
+ module.exports = __toCommonJS(client_exports);
42
+ var import_node_fs2 = __toESM(require("fs"), 1);
43
+ var import_node_path = __toESM(require("path"), 1);
44
+
45
+ // src/logging.ts
46
+ async function getNodeModules() {
47
+ if (typeof process !== "undefined" && process.platform) {
48
+ try {
49
+ const fs2 = await import("fs");
50
+ const path2 = await import("path");
51
+ return { fs: fs2.default, path: path2.default };
52
+ } catch {
53
+ return { fs: null, path: null };
54
+ }
55
+ }
56
+ return { fs: null, path: null };
57
+ }
58
+ __name(getNodeModules, "getNodeModules");
59
+ var winston = null;
60
+ function loadWinstonSync() {
61
+ if (typeof require !== "undefined") {
62
+ try {
63
+ winston = require("winston");
64
+ } catch {
65
+ }
66
+ }
67
+ }
68
+ __name(loadWinstonSync, "loadWinstonSync");
69
+ async function getWinston() {
70
+ if (!winston) {
71
+ winston = await import("winston");
72
+ }
73
+ return winston;
74
+ }
75
+ __name(getWinston, "getWinston");
76
+ var DEFAULT_LOGGER_NAME = "mcp-use";
77
+ function isNodeJSEnvironment() {
78
+ try {
79
+ if (typeof navigator !== "undefined" && navigator.userAgent?.includes("Cloudflare-Workers")) {
80
+ return false;
81
+ }
82
+ if (typeof globalThis.EdgeRuntime !== "undefined" || typeof globalThis.Deno !== "undefined") {
83
+ return false;
84
+ }
85
+ const hasNodeGlobals = typeof process !== "undefined" && typeof process.platform !== "undefined" && typeof __dirname !== "undefined";
86
+ return hasNodeGlobals;
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+ __name(isNodeJSEnvironment, "isNodeJSEnvironment");
92
+ var SimpleConsoleLogger = class {
93
+ static {
94
+ __name(this, "SimpleConsoleLogger");
95
+ }
96
+ _level;
97
+ name;
98
+ constructor(name = DEFAULT_LOGGER_NAME, level = "info") {
99
+ this.name = name;
100
+ this._level = level;
101
+ }
102
+ shouldLog(level) {
103
+ const levels = [
104
+ "error",
105
+ "warn",
106
+ "info",
107
+ "http",
108
+ "verbose",
109
+ "debug",
110
+ "silly"
111
+ ];
112
+ const currentIndex = levels.indexOf(this._level);
113
+ const messageIndex = levels.indexOf(level);
114
+ return messageIndex <= currentIndex;
115
+ }
116
+ formatMessage(level, message) {
117
+ const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
118
+ return `${timestamp} [${this.name}] ${level}: ${message}`;
119
+ }
120
+ error(message) {
121
+ if (this.shouldLog("error")) {
122
+ console.error(this.formatMessage("error", message));
123
+ }
124
+ }
125
+ warn(message) {
126
+ if (this.shouldLog("warn")) {
127
+ console.warn(this.formatMessage("warn", message));
128
+ }
129
+ }
130
+ info(message) {
131
+ if (this.shouldLog("info")) {
132
+ console.info(this.formatMessage("info", message));
133
+ }
134
+ }
135
+ debug(message) {
136
+ if (this.shouldLog("debug")) {
137
+ console.debug(this.formatMessage("debug", message));
138
+ }
139
+ }
140
+ http(message) {
141
+ if (this.shouldLog("http")) {
142
+ console.log(this.formatMessage("http", message));
143
+ }
144
+ }
145
+ verbose(message) {
146
+ if (this.shouldLog("verbose")) {
147
+ console.log(this.formatMessage("verbose", message));
148
+ }
149
+ }
150
+ silly(message) {
151
+ if (this.shouldLog("silly")) {
152
+ console.log(this.formatMessage("silly", message));
153
+ }
154
+ }
155
+ // Make it compatible with Winston interface
156
+ get level() {
157
+ return this._level;
158
+ }
159
+ set level(newLevel) {
160
+ this._level = newLevel;
161
+ }
162
+ };
163
+ function resolveLevel(env) {
164
+ const envValue = typeof process !== "undefined" && process.env ? env : void 0;
165
+ switch (envValue?.trim()) {
166
+ case "2":
167
+ return "debug";
168
+ case "1":
169
+ return "info";
170
+ default:
171
+ return "info";
172
+ }
173
+ }
174
+ __name(resolveLevel, "resolveLevel");
175
+ var Logger = class {
176
+ static {
177
+ __name(this, "Logger");
178
+ }
179
+ static instances = {};
180
+ static simpleInstances = {};
181
+ static currentFormat = "minimal";
182
+ static get(name = DEFAULT_LOGGER_NAME) {
183
+ if (!isNodeJSEnvironment()) {
184
+ if (!this.simpleInstances[name]) {
185
+ const debugEnv = typeof process !== "undefined" && process.env?.DEBUG || void 0;
186
+ this.simpleInstances[name] = new SimpleConsoleLogger(
187
+ name,
188
+ resolveLevel(debugEnv)
189
+ );
190
+ }
191
+ return this.simpleInstances[name];
192
+ }
193
+ if (!this.instances[name]) {
194
+ if (!winston) {
195
+ throw new Error("Winston not loaded - call Logger.configure() first");
196
+ }
197
+ const { createLogger, format } = winston;
198
+ const { combine, timestamp, label, colorize, splat } = format;
199
+ this.instances[name] = createLogger({
200
+ level: resolveLevel(process.env.DEBUG),
201
+ format: combine(
202
+ colorize(),
203
+ splat(),
204
+ label({ label: name }),
205
+ timestamp({ format: "HH:mm:ss" }),
206
+ this.getFormatter()
207
+ ),
208
+ transports: [new winston.transports.Console()]
209
+ });
210
+ }
211
+ return this.instances[name];
212
+ }
213
+ static getFormatter() {
214
+ if (!winston) {
215
+ throw new Error("Winston not loaded");
216
+ }
217
+ const { format } = winston;
218
+ const { printf } = format;
219
+ const minimalFormatter = printf(({ level, message, label, timestamp }) => {
220
+ return `${timestamp} [${label}] ${level}: ${message}`;
221
+ });
222
+ const detailedFormatter = printf(({ level, message, label, timestamp }) => {
223
+ return `${timestamp} [${label}] ${level.toUpperCase()}: ${message}`;
224
+ });
225
+ const emojiFormatter = printf(({ level, message, label, timestamp }) => {
226
+ return `${timestamp} [${label}] ${level.toUpperCase()}: ${message}`;
227
+ });
228
+ switch (this.currentFormat) {
229
+ case "minimal":
230
+ return minimalFormatter;
231
+ case "detailed":
232
+ return detailedFormatter;
233
+ case "emoji":
234
+ return emojiFormatter;
235
+ default:
236
+ return minimalFormatter;
237
+ }
238
+ }
239
+ static async configure(options = {}) {
240
+ const { level, console: console2 = true, file, format = "minimal" } = options;
241
+ const debugEnv = typeof process !== "undefined" && process.env?.DEBUG || void 0;
242
+ const resolvedLevel = level ?? resolveLevel(debugEnv);
243
+ this.currentFormat = format;
244
+ if (!isNodeJSEnvironment()) {
245
+ Object.values(this.simpleInstances).forEach((logger2) => {
246
+ logger2.level = resolvedLevel;
247
+ });
248
+ return;
249
+ }
250
+ await getWinston();
251
+ if (!winston) {
252
+ throw new Error("Failed to load winston");
253
+ }
254
+ const root = this.get();
255
+ root.level = resolvedLevel;
256
+ const winstonRoot = root;
257
+ winstonRoot.clear();
258
+ if (console2) {
259
+ winstonRoot.add(new winston.transports.Console());
260
+ }
261
+ if (file) {
262
+ const { fs: nodeFs, path: nodePath } = await getNodeModules();
263
+ if (nodeFs && nodePath) {
264
+ const dir = nodePath.dirname(nodePath.resolve(file));
265
+ if (!nodeFs.existsSync(dir)) {
266
+ nodeFs.mkdirSync(dir, { recursive: true });
267
+ }
268
+ winstonRoot.add(new winston.transports.File({ filename: file }));
269
+ }
270
+ }
271
+ const { format: winstonFormat } = winston;
272
+ const { combine, timestamp, label, colorize, splat } = winstonFormat;
273
+ Object.values(this.instances).forEach((logger2) => {
274
+ if (logger2 && "format" in logger2) {
275
+ logger2.level = resolvedLevel;
276
+ logger2.format = combine(
277
+ colorize(),
278
+ splat(),
279
+ label({ label: DEFAULT_LOGGER_NAME }),
280
+ timestamp({ format: "HH:mm:ss" }),
281
+ this.getFormatter()
282
+ );
283
+ }
284
+ });
285
+ }
286
+ static setDebug(enabled) {
287
+ let level;
288
+ if (enabled === 2 || enabled === true) level = "debug";
289
+ else if (enabled === 1) level = "info";
290
+ else level = "info";
291
+ Object.values(this.simpleInstances).forEach((logger2) => {
292
+ logger2.level = level;
293
+ });
294
+ Object.values(this.instances).forEach((logger2) => {
295
+ if (logger2) {
296
+ logger2.level = level;
297
+ }
298
+ });
299
+ if (typeof process !== "undefined" && process.env) {
300
+ process.env.DEBUG = enabled ? enabled === true ? "2" : String(enabled) : "0";
301
+ }
302
+ }
303
+ static setFormat(format) {
304
+ this.currentFormat = format;
305
+ this.configure({ format });
306
+ }
307
+ };
308
+ if (isNodeJSEnvironment()) {
309
+ loadWinstonSync();
310
+ if (winston) {
311
+ Logger.configure();
312
+ }
313
+ }
314
+ var logger = Logger.get();
315
+
316
+ // src/session.ts
317
+ var MCPSession = class {
318
+ static {
319
+ __name(this, "MCPSession");
320
+ }
321
+ connector;
322
+ autoConnect;
323
+ constructor(connector, autoConnect = true) {
324
+ this.connector = connector;
325
+ this.autoConnect = autoConnect;
326
+ }
327
+ async connect() {
328
+ await this.connector.connect();
329
+ }
330
+ async disconnect() {
331
+ await this.connector.disconnect();
332
+ }
333
+ async initialize() {
334
+ if (!this.isConnected && this.autoConnect) {
335
+ await this.connect();
336
+ }
337
+ await this.connector.initialize();
338
+ }
339
+ get isConnected() {
340
+ return this.connector && this.connector.isClientConnected;
341
+ }
342
+ /**
343
+ * Register an event handler for session events
344
+ *
345
+ * @param event - The event type to listen for
346
+ * @param handler - The handler function to call when the event occurs
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * session.on("notification", async (notification) => {
351
+ * console.log(`Received: ${notification.method}`, notification.params);
352
+ *
353
+ * if (notification.method === "notifications/tools/list_changed") {
354
+ * // Refresh tools list
355
+ * }
356
+ * });
357
+ * ```
358
+ */
359
+ on(event, handler) {
360
+ if (event === "notification") {
361
+ this.connector.onNotification(handler);
362
+ }
363
+ }
364
+ /**
365
+ * Set roots and notify the server.
366
+ * Roots represent directories or files that the client has access to.
367
+ *
368
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * await session.setRoots([
373
+ * { uri: "file:///home/user/project", name: "My Project" },
374
+ * { uri: "file:///home/user/data" }
375
+ * ]);
376
+ * ```
377
+ */
378
+ async setRoots(roots) {
379
+ return this.connector.setRoots(roots);
380
+ }
381
+ /**
382
+ * Get the current roots.
383
+ */
384
+ getRoots() {
385
+ return this.connector.getRoots();
386
+ }
387
+ /**
388
+ * Get the cached list of tools from the server.
389
+ *
390
+ * @returns Array of available tools
391
+ *
392
+ * @example
393
+ * ```typescript
394
+ * const tools = session.tools;
395
+ * console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
396
+ * ```
397
+ */
398
+ get tools() {
399
+ return this.connector.tools;
400
+ }
401
+ /**
402
+ * List all available tools from the MCP server.
403
+ * This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
404
+ *
405
+ * @param options - Optional request options
406
+ * @returns Array of available tools
407
+ *
408
+ * @example
409
+ * ```typescript
410
+ * const tools = await session.listTools();
411
+ * console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`);
412
+ * ```
413
+ */
414
+ async listTools(options) {
415
+ return this.connector.listTools(options);
416
+ }
417
+ /**
418
+ * Get the server capabilities advertised during initialization.
419
+ *
420
+ * @returns Server capabilities object
421
+ */
422
+ get serverCapabilities() {
423
+ return this.connector.serverCapabilities;
424
+ }
425
+ /**
426
+ * Get the server information (name and version).
427
+ *
428
+ * @returns Server info object or null if not available
429
+ */
430
+ get serverInfo() {
431
+ return this.connector.serverInfo;
432
+ }
433
+ /**
434
+ * Call a tool on the server.
435
+ *
436
+ * @param name - Name of the tool to call
437
+ * @param args - Arguments to pass to the tool (defaults to empty object)
438
+ * @param options - Optional request options (timeout, progress handlers, etc.)
439
+ * @returns Result from the tool execution
440
+ *
441
+ * @example
442
+ * ```typescript
443
+ * const result = await session.callTool("add", { a: 5, b: 3 });
444
+ * console.log(`Result: ${result.content[0].text}`);
445
+ * ```
446
+ */
447
+ async callTool(name, args = {}, options) {
448
+ return this.connector.callTool(name, args, options);
449
+ }
450
+ /**
451
+ * List resources from the server with optional pagination.
452
+ *
453
+ * @param cursor - Optional cursor for pagination
454
+ * @param options - Request options
455
+ * @returns Resource list with optional nextCursor for pagination
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * const result = await session.listResources();
460
+ * console.log(`Found ${result.resources.length} resources`);
461
+ * ```
462
+ */
463
+ async listResources(cursor, options) {
464
+ return this.connector.listResources(cursor, options);
465
+ }
466
+ /**
467
+ * List all resources from the server, automatically handling pagination.
468
+ *
469
+ * @param options - Request options
470
+ * @returns Complete list of all resources
471
+ *
472
+ * @example
473
+ * ```typescript
474
+ * const result = await session.listAllResources();
475
+ * console.log(`Total resources: ${result.resources.length}`);
476
+ * ```
477
+ */
478
+ async listAllResources(options) {
479
+ return this.connector.listAllResources(options);
480
+ }
481
+ /**
482
+ * List resource templates from the server.
483
+ *
484
+ * @param options - Request options
485
+ * @returns List of available resource templates
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * const result = await session.listResourceTemplates();
490
+ * console.log(`Available templates: ${result.resourceTemplates.length}`);
491
+ * ```
492
+ */
493
+ async listResourceTemplates(options) {
494
+ return this.connector.listResourceTemplates(options);
495
+ }
496
+ /**
497
+ * Read a resource by URI.
498
+ *
499
+ * @param uri - URI of the resource to read
500
+ * @param options - Request options
501
+ * @returns Resource content
502
+ *
503
+ * @example
504
+ * ```typescript
505
+ * const resource = await session.readResource("file:///path/to/file.txt");
506
+ * console.log(resource.contents);
507
+ * ```
508
+ */
509
+ async readResource(uri, options) {
510
+ return this.connector.readResource(uri, options);
511
+ }
512
+ /**
513
+ * Subscribe to resource updates.
514
+ *
515
+ * @param uri - URI of the resource to subscribe to
516
+ * @param options - Request options
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * await session.subscribeToResource("file:///path/to/file.txt");
521
+ * // Now you'll receive notifications when this resource changes
522
+ * ```
523
+ */
524
+ async subscribeToResource(uri, options) {
525
+ return this.connector.subscribeToResource(uri, options);
526
+ }
527
+ /**
528
+ * Unsubscribe from resource updates.
529
+ *
530
+ * @param uri - URI of the resource to unsubscribe from
531
+ * @param options - Request options
532
+ *
533
+ * @example
534
+ * ```typescript
535
+ * await session.unsubscribeFromResource("file:///path/to/file.txt");
536
+ * ```
537
+ */
538
+ async unsubscribeFromResource(uri, options) {
539
+ return this.connector.unsubscribeFromResource(uri, options);
540
+ }
541
+ /**
542
+ * List available prompts from the server.
543
+ *
544
+ * @returns List of available prompts
545
+ *
546
+ * @example
547
+ * ```typescript
548
+ * const result = await session.listPrompts();
549
+ * console.log(`Available prompts: ${result.prompts.length}`);
550
+ * ```
551
+ */
552
+ async listPrompts() {
553
+ return this.connector.listPrompts();
554
+ }
555
+ /**
556
+ * Get a specific prompt with arguments.
557
+ *
558
+ * @param name - Name of the prompt to get
559
+ * @param args - Arguments for the prompt
560
+ * @returns Prompt result
561
+ *
562
+ * @example
563
+ * ```typescript
564
+ * const prompt = await session.getPrompt("greeting", { name: "Alice" });
565
+ * console.log(prompt.messages);
566
+ * ```
567
+ */
568
+ async getPrompt(name, args) {
569
+ return this.connector.getPrompt(name, args);
570
+ }
571
+ /**
572
+ * Send a raw request through the client.
573
+ *
574
+ * @param method - MCP method name
575
+ * @param params - Request parameters
576
+ * @param options - Request options
577
+ * @returns Response from the server
578
+ *
579
+ * @example
580
+ * ```typescript
581
+ * const result = await session.request("custom/method", { key: "value" });
582
+ * ```
583
+ */
584
+ async request(method, params = null, options) {
585
+ return this.connector.request(method, params, options);
586
+ }
587
+ };
588
+
589
+ // src/telemetry/events.ts
590
+ var BaseTelemetryEvent = class {
591
+ static {
592
+ __name(this, "BaseTelemetryEvent");
593
+ }
594
+ };
595
+ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
596
+ constructor(data) {
597
+ super();
598
+ this.data = data;
599
+ }
600
+ static {
601
+ __name(this, "MCPAgentExecutionEvent");
602
+ }
603
+ get name() {
604
+ return "mcp_agent_execution";
605
+ }
606
+ get properties() {
607
+ return {
608
+ // Core execution info
609
+ execution_method: this.data.executionMethod,
610
+ query: this.data.query,
611
+ query_length: this.data.query.length,
612
+ success: this.data.success,
613
+ // Agent configuration
614
+ model_provider: this.data.modelProvider,
615
+ model_name: this.data.modelName,
616
+ server_count: this.data.serverCount,
617
+ server_identifiers: this.data.serverIdentifiers,
618
+ total_tools_available: this.data.totalToolsAvailable,
619
+ tools_available_names: this.data.toolsAvailableNames,
620
+ max_steps_configured: this.data.maxStepsConfigured,
621
+ memory_enabled: this.data.memoryEnabled,
622
+ use_server_manager: this.data.useServerManager,
623
+ // Execution parameters (always include, even if null)
624
+ max_steps_used: this.data.maxStepsUsed,
625
+ manage_connector: this.data.manageConnector,
626
+ external_history_used: this.data.externalHistoryUsed,
627
+ // Execution results (always include, even if null)
628
+ steps_taken: this.data.stepsTaken ?? null,
629
+ tools_used_count: this.data.toolsUsedCount ?? null,
630
+ tools_used_names: this.data.toolsUsedNames ?? null,
631
+ response: this.data.response ?? null,
632
+ response_length: this.data.response ? this.data.response.length : null,
633
+ execution_time_ms: this.data.executionTimeMs ?? null,
634
+ error_type: this.data.errorType ?? null,
635
+ conversation_history_length: this.data.conversationHistoryLength ?? null
636
+ };
637
+ }
638
+ };
639
+ function createServerRunEventData(server, transport) {
640
+ const toolRegistrations = Array.from(server.registrations.tools.values());
641
+ const promptRegistrations = Array.from(server.registrations.prompts.values());
642
+ const resourceRegistrations = Array.from(
643
+ server.registrations.resources.values()
644
+ );
645
+ const templateRegistrations = Array.from(
646
+ server.registrations.resourceTemplates.values()
647
+ );
648
+ const allResources = resourceRegistrations.map((r) => ({
649
+ name: r.config.name,
650
+ title: r.config.title ?? null,
651
+ description: r.config.description ?? null,
652
+ uri: r.config.uri ?? null,
653
+ mime_type: r.config.mimeType ?? null
654
+ }));
655
+ const appsSdkResources = allResources.filter(
656
+ (r) => r.mime_type === "text/html+skybridge"
657
+ );
658
+ const mcpUiResources = allResources.filter(
659
+ (r) => r.mime_type === "text/uri-list" || r.mime_type === "text/html"
660
+ );
661
+ const mcpAppsResources = allResources.filter(
662
+ (r) => r.mime_type === "text/html+mcp"
663
+ );
664
+ return {
665
+ transport,
666
+ toolsNumber: server.registeredTools.length,
667
+ resourcesNumber: server.registeredResources.length,
668
+ promptsNumber: server.registeredPrompts.length,
669
+ auth: !!server.oauthProvider,
670
+ name: server.config.name,
671
+ description: server.config.description ?? null,
672
+ baseUrl: server.serverBaseUrl ?? null,
673
+ toolNames: server.registeredTools.length > 0 ? server.registeredTools : null,
674
+ resourceNames: server.registeredResources.length > 0 ? server.registeredResources : null,
675
+ promptNames: server.registeredPrompts.length > 0 ? server.registeredPrompts : null,
676
+ tools: toolRegistrations.length > 0 ? toolRegistrations.map((r) => ({
677
+ name: r.config.name,
678
+ title: r.config.title ?? null,
679
+ description: r.config.description ?? null,
680
+ input_schema: r.config.schema ? JSON.stringify(r.config.schema) : null,
681
+ output_schema: r.config.outputSchema ? JSON.stringify(r.config.outputSchema) : null
682
+ })) : null,
683
+ resources: allResources.length > 0 ? allResources : null,
684
+ prompts: promptRegistrations.length > 0 ? promptRegistrations.map((r) => ({
685
+ name: r.config.name,
686
+ title: r.config.title ?? null,
687
+ description: r.config.description ?? null,
688
+ args: r.config.args ? JSON.stringify(r.config.args) : null
689
+ })) : null,
690
+ templates: templateRegistrations.length > 0 ? templateRegistrations.map((r) => ({
691
+ name: r.config.name,
692
+ title: r.config.title ?? null,
693
+ description: r.config.description ?? null
694
+ })) : null,
695
+ capabilities: {
696
+ logging: true,
697
+ resources: { subscribe: true, listChanged: true }
698
+ },
699
+ appsSdkResources: appsSdkResources.length > 0 ? appsSdkResources : null,
700
+ appsSdkResourcesNumber: appsSdkResources.length,
701
+ mcpUiResources: mcpUiResources.length > 0 ? mcpUiResources : null,
702
+ mcpUiResourcesNumber: mcpUiResources.length,
703
+ mcpAppsResources: mcpAppsResources.length > 0 ? mcpAppsResources : null,
704
+ mcpAppsResourcesNumber: mcpAppsResources.length
705
+ };
706
+ }
707
+ __name(createServerRunEventData, "createServerRunEventData");
708
+ var ServerRunEvent = class extends BaseTelemetryEvent {
709
+ constructor(data) {
710
+ super();
711
+ this.data = data;
712
+ }
713
+ static {
714
+ __name(this, "ServerRunEvent");
715
+ }
716
+ get name() {
717
+ return "server_run";
718
+ }
719
+ get properties() {
720
+ return {
721
+ transport: this.data.transport,
722
+ tools_number: this.data.toolsNumber,
723
+ resources_number: this.data.resourcesNumber,
724
+ prompts_number: this.data.promptsNumber,
725
+ auth: this.data.auth,
726
+ name: this.data.name,
727
+ description: this.data.description ?? null,
728
+ base_url: this.data.baseUrl ?? null,
729
+ tool_names: this.data.toolNames ?? null,
730
+ resource_names: this.data.resourceNames ?? null,
731
+ prompt_names: this.data.promptNames ?? null,
732
+ tools: this.data.tools ?? null,
733
+ resources: this.data.resources ?? null,
734
+ prompts: this.data.prompts ?? null,
735
+ templates: this.data.templates ?? null,
736
+ capabilities: this.data.capabilities ? JSON.stringify(this.data.capabilities) : null,
737
+ apps_sdk_resources: this.data.appsSdkResources ? JSON.stringify(this.data.appsSdkResources) : null,
738
+ apps_sdk_resources_number: this.data.appsSdkResourcesNumber ?? 0,
739
+ mcp_ui_resources: this.data.mcpUiResources ? JSON.stringify(this.data.mcpUiResources) : null,
740
+ mcp_ui_resources_number: this.data.mcpUiResourcesNumber ?? 0,
741
+ mcp_apps_resources: this.data.mcpAppsResources ? JSON.stringify(this.data.mcpAppsResources) : null,
742
+ mcp_apps_resources_number: this.data.mcpAppsResourcesNumber ?? 0
743
+ };
744
+ }
745
+ };
746
+ var ServerInitializeEvent = class extends BaseTelemetryEvent {
747
+ constructor(data) {
748
+ super();
749
+ this.data = data;
750
+ }
751
+ static {
752
+ __name(this, "ServerInitializeEvent");
753
+ }
754
+ get name() {
755
+ return "server_initialize_call";
756
+ }
757
+ get properties() {
758
+ return {
759
+ protocol_version: this.data.protocolVersion,
760
+ client_info: JSON.stringify(this.data.clientInfo),
761
+ client_capabilities: JSON.stringify(this.data.clientCapabilities),
762
+ session_id: this.data.sessionId ?? null
763
+ };
764
+ }
765
+ };
766
+ var ServerToolCallEvent = class extends BaseTelemetryEvent {
767
+ constructor(data) {
768
+ super();
769
+ this.data = data;
770
+ }
771
+ static {
772
+ __name(this, "ServerToolCallEvent");
773
+ }
774
+ get name() {
775
+ return "server_tool_call";
776
+ }
777
+ get properties() {
778
+ return {
779
+ tool_name: this.data.toolName,
780
+ length_input_argument: this.data.lengthInputArgument,
781
+ success: this.data.success,
782
+ error_type: this.data.errorType ?? null,
783
+ execution_time_ms: this.data.executionTimeMs ?? null
784
+ };
785
+ }
786
+ };
787
+ var ServerResourceCallEvent = class extends BaseTelemetryEvent {
788
+ constructor(data) {
789
+ super();
790
+ this.data = data;
791
+ }
792
+ static {
793
+ __name(this, "ServerResourceCallEvent");
794
+ }
795
+ get name() {
796
+ return "server_resource_call";
797
+ }
798
+ get properties() {
799
+ return {
800
+ name: this.data.name,
801
+ description: this.data.description,
802
+ contents: this.data.contents,
803
+ success: this.data.success,
804
+ error_type: this.data.errorType ?? null
805
+ };
806
+ }
807
+ };
808
+ var ServerPromptCallEvent = class extends BaseTelemetryEvent {
809
+ constructor(data) {
810
+ super();
811
+ this.data = data;
812
+ }
813
+ static {
814
+ __name(this, "ServerPromptCallEvent");
815
+ }
816
+ get name() {
817
+ return "server_prompt_call";
818
+ }
819
+ get properties() {
820
+ return {
821
+ name: this.data.name,
822
+ description: this.data.description,
823
+ success: this.data.success,
824
+ error_type: this.data.errorType ?? null
825
+ };
826
+ }
827
+ };
828
+ var ServerContextEvent = class extends BaseTelemetryEvent {
829
+ constructor(data) {
830
+ super();
831
+ this.data = data;
832
+ }
833
+ static {
834
+ __name(this, "ServerContextEvent");
835
+ }
836
+ get name() {
837
+ return `server_context_${this.data.contextType}`;
838
+ }
839
+ get properties() {
840
+ return {
841
+ context_type: this.data.contextType,
842
+ notification_type: this.data.notificationType ?? null
843
+ };
844
+ }
845
+ };
846
+ var MCPClientInitEvent = class extends BaseTelemetryEvent {
847
+ constructor(data) {
848
+ super();
849
+ this.data = data;
850
+ }
851
+ static {
852
+ __name(this, "MCPClientInitEvent");
853
+ }
854
+ get name() {
855
+ return "mcpclient_init";
856
+ }
857
+ get properties() {
858
+ return {
859
+ code_mode: this.data.codeMode,
860
+ sandbox: this.data.sandbox,
861
+ all_callbacks: this.data.allCallbacks,
862
+ verify: this.data.verify,
863
+ servers: this.data.servers,
864
+ num_servers: this.data.numServers,
865
+ is_browser: this.data.isBrowser
866
+ };
867
+ }
868
+ };
869
+ var ConnectorInitEvent = class extends BaseTelemetryEvent {
870
+ constructor(data) {
871
+ super();
872
+ this.data = data;
873
+ }
874
+ static {
875
+ __name(this, "ConnectorInitEvent");
876
+ }
877
+ get name() {
878
+ return "connector_init";
879
+ }
880
+ get properties() {
881
+ return {
882
+ connector_type: this.data.connectorType,
883
+ server_command: this.data.serverCommand ?? null,
884
+ server_args: this.data.serverArgs ?? null,
885
+ server_url: this.data.serverUrl ?? null,
886
+ public_identifier: this.data.publicIdentifier ?? null
887
+ };
888
+ }
889
+ };
890
+ var ClientAddServerEvent = class extends BaseTelemetryEvent {
891
+ constructor(data) {
892
+ super();
893
+ this.data = data;
894
+ }
895
+ static {
896
+ __name(this, "ClientAddServerEvent");
897
+ }
898
+ get name() {
899
+ return "client_add_server";
900
+ }
901
+ get properties() {
902
+ const { serverName, serverConfig } = this.data;
903
+ const url = serverConfig.url;
904
+ return {
905
+ server_name: serverName,
906
+ server_url_domain: url ? this._extractHostname(url) : null,
907
+ transport: serverConfig.transport ?? null,
908
+ has_auth: !!(serverConfig.authToken || serverConfig.authProvider)
909
+ };
910
+ }
911
+ _extractHostname(url) {
912
+ try {
913
+ return new URL(url).hostname;
914
+ } catch {
915
+ return null;
916
+ }
917
+ }
918
+ };
919
+ var ClientRemoveServerEvent = class extends BaseTelemetryEvent {
920
+ constructor(data) {
921
+ super();
922
+ this.data = data;
923
+ }
924
+ static {
925
+ __name(this, "ClientRemoveServerEvent");
926
+ }
927
+ get name() {
928
+ return "client_remove_server";
929
+ }
930
+ get properties() {
931
+ return {
932
+ server_name: this.data.serverName
933
+ };
934
+ }
935
+ };
936
+
937
+ // src/server/utils/runtime.ts
938
+ var isDeno = typeof globalThis.Deno !== "undefined";
939
+ function generateUUID() {
940
+ return globalThis.crypto.randomUUID();
941
+ }
942
+ __name(generateUUID, "generateUUID");
943
+
944
+ // src/version.ts
945
+ var VERSION = "1.11.0-canary.11";
946
+ function getPackageVersion() {
947
+ return VERSION;
948
+ }
949
+ __name(getPackageVersion, "getPackageVersion");
950
+
951
+ // src/telemetry/telemetry.ts
952
+ var USER_ID_STORAGE_KEY = "mcp_use_user_id";
953
+ function detectRuntimeEnvironment() {
954
+ try {
955
+ if (typeof globalThis.Bun !== "undefined") {
956
+ return "bun";
957
+ }
958
+ if (typeof globalThis.Deno !== "undefined") {
959
+ return "deno";
960
+ }
961
+ if (typeof navigator !== "undefined" && navigator.userAgent?.includes("Cloudflare-Workers")) {
962
+ return "cloudflare-workers";
963
+ }
964
+ if (typeof globalThis.EdgeRuntime !== "undefined") {
965
+ return "edge";
966
+ }
967
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
968
+ return "browser";
969
+ }
970
+ if (typeof process !== "undefined" && typeof process.versions?.node !== "undefined") {
971
+ return "node";
972
+ }
973
+ return "unknown";
974
+ } catch {
975
+ return "unknown";
976
+ }
977
+ }
978
+ __name(detectRuntimeEnvironment, "detectRuntimeEnvironment");
979
+ function getStorageCapability(env) {
980
+ switch (env) {
981
+ case "node":
982
+ case "bun":
983
+ return "filesystem";
984
+ case "browser":
985
+ try {
986
+ if (typeof localStorage !== "undefined") {
987
+ localStorage.setItem("__mcp_use_test__", "1");
988
+ localStorage.removeItem("__mcp_use_test__");
989
+ return "localStorage";
990
+ }
991
+ } catch {
992
+ }
993
+ return "session-only";
994
+ case "deno":
995
+ return "session-only";
996
+ default:
997
+ return "session-only";
998
+ }
999
+ }
1000
+ __name(getStorageCapability, "getStorageCapability");
1001
+ var cachedEnvironment = null;
1002
+ function getRuntimeEnvironment() {
1003
+ if (cachedEnvironment === null) {
1004
+ cachedEnvironment = detectRuntimeEnvironment();
1005
+ }
1006
+ return cachedEnvironment;
1007
+ }
1008
+ __name(getRuntimeEnvironment, "getRuntimeEnvironment");
1009
+ var ScarfEventLogger = class {
1010
+ static {
1011
+ __name(this, "ScarfEventLogger");
1012
+ }
1013
+ endpoint;
1014
+ timeout;
1015
+ constructor(endpoint, timeout = 3e3) {
1016
+ this.endpoint = endpoint;
1017
+ this.timeout = timeout;
1018
+ }
1019
+ async logEvent(properties) {
1020
+ try {
1021
+ const controller = new AbortController();
1022
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1023
+ const response = await fetch(this.endpoint, {
1024
+ method: "POST",
1025
+ headers: {
1026
+ "Content-Type": "application/json"
1027
+ },
1028
+ body: JSON.stringify(properties),
1029
+ signal: controller.signal
1030
+ });
1031
+ clearTimeout(timeoutId);
1032
+ if (!response.ok) {
1033
+ throw new Error(`HTTP error! status: ${response.status}`);
1034
+ }
1035
+ } catch (error) {
1036
+ logger.debug(`Failed to send Scarf event: ${error}`);
1037
+ }
1038
+ }
1039
+ };
1040
+ var Telemetry = class _Telemetry {
1041
+ static {
1042
+ __name(this, "Telemetry");
1043
+ }
1044
+ static instance = null;
1045
+ PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
1046
+ HOST = "https://eu.i.posthog.com";
1047
+ SCARF_GATEWAY_URL = "https://mcpuse.gateway.scarf.sh/events-ts";
1048
+ UNKNOWN_USER_ID = "UNKNOWN_USER_ID";
1049
+ _currUserId = null;
1050
+ _posthogNodeClient = null;
1051
+ _posthogBrowserClient = null;
1052
+ _posthogLoading = null;
1053
+ _scarfClient = null;
1054
+ _runtimeEnvironment;
1055
+ _storageCapability;
1056
+ _source;
1057
+ // Node.js specific paths (lazily computed)
1058
+ _userIdPath = null;
1059
+ _versionDownloadPath = null;
1060
+ constructor() {
1061
+ this._runtimeEnvironment = getRuntimeEnvironment();
1062
+ this._storageCapability = getStorageCapability(this._runtimeEnvironment);
1063
+ this._source = typeof process !== "undefined" && process.env?.MCP_USE_TELEMETRY_SOURCE || this._runtimeEnvironment;
1064
+ const telemetryDisabled = this._checkTelemetryDisabled();
1065
+ const canSupportTelemetry = this._runtimeEnvironment !== "unknown";
1066
+ if (telemetryDisabled) {
1067
+ this._posthogNodeClient = null;
1068
+ this._posthogBrowserClient = null;
1069
+ this._scarfClient = null;
1070
+ logger.debug("Telemetry disabled via environment/localStorage");
1071
+ } else if (!canSupportTelemetry) {
1072
+ this._posthogNodeClient = null;
1073
+ this._posthogBrowserClient = null;
1074
+ this._scarfClient = null;
1075
+ logger.debug(
1076
+ `Telemetry disabled - unknown environment: ${this._runtimeEnvironment}`
1077
+ );
1078
+ } else {
1079
+ logger.info(
1080
+ "Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable."
1081
+ );
1082
+ this._posthogLoading = this._initPostHog();
1083
+ try {
1084
+ this._scarfClient = new ScarfEventLogger(this.SCARF_GATEWAY_URL, 3e3);
1085
+ } catch (e) {
1086
+ logger.warn(`Failed to initialize Scarf telemetry: ${e}`);
1087
+ this._scarfClient = null;
1088
+ }
1089
+ }
1090
+ }
1091
+ _checkTelemetryDisabled() {
1092
+ if (typeof process !== "undefined" && process.env?.MCP_USE_ANONYMIZED_TELEMETRY?.toLowerCase() === "false") {
1093
+ return true;
1094
+ }
1095
+ if (typeof localStorage !== "undefined" && localStorage.getItem("MCP_USE_ANONYMIZED_TELEMETRY") === "false") {
1096
+ return true;
1097
+ }
1098
+ return false;
1099
+ }
1100
+ async _initPostHog() {
1101
+ const isBrowser = this._runtimeEnvironment === "browser";
1102
+ if (isBrowser) {
1103
+ await this._initPostHogBrowser();
1104
+ } else {
1105
+ await this._initPostHogNode();
1106
+ }
1107
+ }
1108
+ async _initPostHogBrowser() {
1109
+ try {
1110
+ const posthogModule = await import("posthog-js");
1111
+ const posthog = posthogModule.default || posthogModule.posthog;
1112
+ if (!posthog || typeof posthog.init !== "function") {
1113
+ throw new Error("posthog-js module did not export expected interface");
1114
+ }
1115
+ posthog.init(this.PROJECT_API_KEY, {
1116
+ api_host: this.HOST,
1117
+ persistence: "localStorage",
1118
+ autocapture: false,
1119
+ // We only want explicit captures
1120
+ capture_pageview: false,
1121
+ // We don't want automatic pageview tracking
1122
+ disable_session_recording: true,
1123
+ // No session recording
1124
+ loaded: /* @__PURE__ */ __name(() => {
1125
+ logger.debug("PostHog browser client initialized");
1126
+ }, "loaded")
1127
+ });
1128
+ this._posthogBrowserClient = posthog;
1129
+ } catch (e) {
1130
+ logger.warn(`Failed to initialize PostHog browser telemetry: ${e}`);
1131
+ this._posthogBrowserClient = null;
1132
+ }
1133
+ }
1134
+ async _initPostHogNode() {
1135
+ try {
1136
+ const { PostHog } = await import("posthog-node");
1137
+ const isServerlessEnvironment = [
1138
+ "cloudflare-workers",
1139
+ "edge",
1140
+ "deno"
1141
+ ].includes(this._runtimeEnvironment);
1142
+ const posthogOptions = {
1143
+ host: this.HOST,
1144
+ disableGeoip: false
1145
+ };
1146
+ if (isServerlessEnvironment) {
1147
+ posthogOptions.flushAt = 1;
1148
+ posthogOptions.flushInterval = 0;
1149
+ }
1150
+ this._posthogNodeClient = new PostHog(
1151
+ this.PROJECT_API_KEY,
1152
+ posthogOptions
1153
+ );
1154
+ logger.debug("PostHog Node.js client initialized");
1155
+ } catch (e) {
1156
+ logger.warn(`Failed to initialize PostHog Node.js telemetry: ${e}`);
1157
+ this._posthogNodeClient = null;
1158
+ }
1159
+ }
1160
+ /**
1161
+ * Get the detected runtime environment
1162
+ */
1163
+ get runtimeEnvironment() {
1164
+ return this._runtimeEnvironment;
1165
+ }
1166
+ /**
1167
+ * Get the storage capability for this environment
1168
+ */
1169
+ get storageCapability() {
1170
+ return this._storageCapability;
1171
+ }
1172
+ static getInstance() {
1173
+ if (!_Telemetry.instance) {
1174
+ _Telemetry.instance = new _Telemetry();
1175
+ }
1176
+ return _Telemetry.instance;
1177
+ }
1178
+ /**
1179
+ * Set the source identifier for telemetry events.
1180
+ * This allows tracking usage from different applications.
1181
+ * @param source - The source identifier (e.g., "my-app", "cli", "vs-code-extension")
1182
+ */
1183
+ setSource(source) {
1184
+ this._source = source;
1185
+ logger.debug(`Telemetry source set to: ${source}`);
1186
+ }
1187
+ /**
1188
+ * Get the current source identifier.
1189
+ */
1190
+ getSource() {
1191
+ return this._source;
1192
+ }
1193
+ /**
1194
+ * Check if telemetry is enabled.
1195
+ */
1196
+ get isEnabled() {
1197
+ return this._posthogNodeClient !== null || this._posthogBrowserClient !== null || this._scarfClient !== null;
1198
+ }
1199
+ get userId() {
1200
+ if (this._currUserId) {
1201
+ return this._currUserId;
1202
+ }
1203
+ try {
1204
+ switch (this._storageCapability) {
1205
+ case "filesystem":
1206
+ this._currUserId = this._getUserIdFromFilesystem();
1207
+ break;
1208
+ case "localStorage":
1209
+ this._currUserId = this._getUserIdFromLocalStorage();
1210
+ break;
1211
+ case "session-only":
1212
+ default:
1213
+ this._currUserId = `session-${generateUUID()}`;
1214
+ logger.debug(
1215
+ `Using session-based user ID (${this._runtimeEnvironment} environment)`
1216
+ );
1217
+ break;
1218
+ }
1219
+ if (this._storageCapability === "filesystem" && this._currUserId) {
1220
+ this._trackPackageDownloadInternal(this._currUserId, {
1221
+ triggered_by: "user_id_property"
1222
+ }).catch((e) => logger.debug(`Failed to track package download: ${e}`));
1223
+ }
1224
+ } catch (e) {
1225
+ logger.debug(`Failed to get/create user ID: ${e}`);
1226
+ this._currUserId = this.UNKNOWN_USER_ID;
1227
+ }
1228
+ return this._currUserId;
1229
+ }
1230
+ /**
1231
+ * Get or create user ID from filesystem (Node.js/Bun)
1232
+ */
1233
+ _getUserIdFromFilesystem() {
1234
+ const fs2 = require("fs");
1235
+ const os = require("os");
1236
+ const path2 = require("path");
1237
+ if (!this._userIdPath) {
1238
+ this._userIdPath = path2.join(
1239
+ this._getCacheHome(os, path2),
1240
+ "mcp_use_3",
1241
+ "telemetry_user_id"
1242
+ );
1243
+ }
1244
+ const isFirstTime = !fs2.existsSync(this._userIdPath);
1245
+ if (isFirstTime) {
1246
+ logger.debug(`Creating user ID path: ${this._userIdPath}`);
1247
+ fs2.mkdirSync(path2.dirname(this._userIdPath), { recursive: true });
1248
+ const newUserId = generateUUID();
1249
+ fs2.writeFileSync(this._userIdPath, newUserId);
1250
+ logger.debug(`User ID path created: ${this._userIdPath}`);
1251
+ return newUserId;
1252
+ }
1253
+ return fs2.readFileSync(this._userIdPath, "utf-8").trim();
1254
+ }
1255
+ /**
1256
+ * Get or create user ID from localStorage (Browser)
1257
+ */
1258
+ _getUserIdFromLocalStorage() {
1259
+ try {
1260
+ let userId = localStorage.getItem(USER_ID_STORAGE_KEY);
1261
+ if (!userId) {
1262
+ userId = generateUUID();
1263
+ localStorage.setItem(USER_ID_STORAGE_KEY, userId);
1264
+ logger.debug(`Created new browser user ID`);
1265
+ }
1266
+ return userId;
1267
+ } catch (e) {
1268
+ logger.debug(`localStorage access failed: ${e}`);
1269
+ return `session-${generateUUID()}`;
1270
+ }
1271
+ }
1272
+ _getCacheHome(os, path2) {
1273
+ const envVar = process.env.XDG_CACHE_HOME;
1274
+ if (envVar && path2.isAbsolute(envVar)) {
1275
+ return envVar;
1276
+ }
1277
+ const platform = process.platform;
1278
+ const homeDir = os.homedir();
1279
+ if (platform === "win32") {
1280
+ const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
1281
+ if (appdata) {
1282
+ return appdata;
1283
+ }
1284
+ return path2.join(homeDir, "AppData", "Local");
1285
+ } else if (platform === "darwin") {
1286
+ return path2.join(homeDir, "Library", "Caches");
1287
+ } else {
1288
+ return path2.join(homeDir, ".cache");
1289
+ }
1290
+ }
1291
+ async capture(event) {
1292
+ if (this._posthogLoading) {
1293
+ await this._posthogLoading;
1294
+ }
1295
+ if (!this._posthogNodeClient && !this._posthogBrowserClient && !this._scarfClient) {
1296
+ return;
1297
+ }
1298
+ const properties = { ...event.properties };
1299
+ properties.mcp_use_version = getPackageVersion();
1300
+ properties.language = "typescript";
1301
+ properties.source = this._source;
1302
+ properties.runtime = this._runtimeEnvironment;
1303
+ if (this._posthogNodeClient) {
1304
+ try {
1305
+ logger.debug(`CAPTURE: PostHog Node Event ${event.name}`);
1306
+ this._posthogNodeClient.capture({
1307
+ distinctId: this.userId,
1308
+ event: event.name,
1309
+ properties
1310
+ });
1311
+ } catch (e) {
1312
+ logger.debug(`Failed to track PostHog Node event ${event.name}: ${e}`);
1313
+ }
1314
+ }
1315
+ if (this._posthogBrowserClient) {
1316
+ try {
1317
+ logger.debug(`CAPTURE: PostHog Browser Event ${event.name}`);
1318
+ this._posthogBrowserClient.capture(event.name, {
1319
+ ...properties,
1320
+ distinct_id: this.userId
1321
+ });
1322
+ } catch (e) {
1323
+ logger.debug(
1324
+ `Failed to track PostHog Browser event ${event.name}: ${e}`
1325
+ );
1326
+ }
1327
+ }
1328
+ if (this._scarfClient) {
1329
+ try {
1330
+ const scarfProperties = {
1331
+ ...properties,
1332
+ user_id: this.userId,
1333
+ event: event.name
1334
+ };
1335
+ await this._scarfClient.logEvent(scarfProperties);
1336
+ } catch (e) {
1337
+ logger.debug(`Failed to track Scarf event ${event.name}: ${e}`);
1338
+ }
1339
+ }
1340
+ }
1341
+ // ============================================================================
1342
+ // Package Download Tracking (Node.js only)
1343
+ // ============================================================================
1344
+ /**
1345
+ * Track package download event.
1346
+ * This is a public wrapper that safely accesses userId.
1347
+ */
1348
+ async trackPackageDownload(properties) {
1349
+ return this._trackPackageDownloadInternal(this.userId, properties);
1350
+ }
1351
+ /**
1352
+ * Internal method to track package download with explicit userId.
1353
+ */
1354
+ async _trackPackageDownloadInternal(userId, properties) {
1355
+ if (!this._scarfClient) {
1356
+ return;
1357
+ }
1358
+ if (this._storageCapability !== "filesystem") {
1359
+ return;
1360
+ }
1361
+ try {
1362
+ const fs2 = require("fs");
1363
+ const path2 = require("path");
1364
+ const os = require("os");
1365
+ if (!this._versionDownloadPath) {
1366
+ this._versionDownloadPath = path2.join(
1367
+ this._getCacheHome(os, path2),
1368
+ "mcp_use",
1369
+ "download_version"
1370
+ );
1371
+ }
1372
+ const currentVersion = getPackageVersion();
1373
+ let shouldTrack = false;
1374
+ let firstDownload = false;
1375
+ if (!fs2.existsSync(this._versionDownloadPath)) {
1376
+ shouldTrack = true;
1377
+ firstDownload = true;
1378
+ fs2.mkdirSync(path2.dirname(this._versionDownloadPath), {
1379
+ recursive: true
1380
+ });
1381
+ fs2.writeFileSync(this._versionDownloadPath, currentVersion);
1382
+ } else {
1383
+ const savedVersion = fs2.readFileSync(this._versionDownloadPath, "utf-8").trim();
1384
+ if (currentVersion > savedVersion) {
1385
+ shouldTrack = true;
1386
+ firstDownload = false;
1387
+ fs2.writeFileSync(this._versionDownloadPath, currentVersion);
1388
+ }
1389
+ }
1390
+ if (shouldTrack) {
1391
+ logger.debug(
1392
+ `Tracking package download event with properties: ${JSON.stringify(properties)}`
1393
+ );
1394
+ const eventProperties = { ...properties || {} };
1395
+ eventProperties.mcp_use_version = currentVersion;
1396
+ eventProperties.user_id = userId;
1397
+ eventProperties.event = "package_download";
1398
+ eventProperties.first_download = firstDownload;
1399
+ eventProperties.language = "typescript";
1400
+ eventProperties.source = this._source;
1401
+ eventProperties.runtime = this._runtimeEnvironment;
1402
+ await this._scarfClient.logEvent(eventProperties);
1403
+ }
1404
+ } catch (e) {
1405
+ logger.debug(`Failed to track Scarf package_download event: ${e}`);
1406
+ }
1407
+ }
1408
+ // ============================================================================
1409
+ // Agent Events
1410
+ // ============================================================================
1411
+ async trackAgentExecution(data) {
1412
+ if (!this.isEnabled) return;
1413
+ const event = new MCPAgentExecutionEvent(data);
1414
+ await this.capture(event);
1415
+ }
1416
+ // ============================================================================
1417
+ // Server Events
1418
+ // ============================================================================
1419
+ /**
1420
+ * Track server run event directly from an MCPServer instance.
1421
+ */
1422
+ async trackServerRunFromServer(server, transport) {
1423
+ if (!this.isEnabled) return;
1424
+ const data = createServerRunEventData(server, transport);
1425
+ const event = new ServerRunEvent(data);
1426
+ await this.capture(event);
1427
+ }
1428
+ async trackServerInitialize(data) {
1429
+ if (!this.isEnabled) return;
1430
+ const event = new ServerInitializeEvent(data);
1431
+ await this.capture(event);
1432
+ }
1433
+ async trackServerToolCall(data) {
1434
+ if (!this.isEnabled) return;
1435
+ const event = new ServerToolCallEvent(data);
1436
+ await this.capture(event);
1437
+ }
1438
+ async trackServerResourceCall(data) {
1439
+ if (!this.isEnabled) return;
1440
+ const event = new ServerResourceCallEvent(data);
1441
+ await this.capture(event);
1442
+ }
1443
+ async trackServerPromptCall(data) {
1444
+ if (!this.isEnabled) return;
1445
+ const event = new ServerPromptCallEvent(data);
1446
+ await this.capture(event);
1447
+ }
1448
+ async trackServerContext(data) {
1449
+ if (!this.isEnabled) return;
1450
+ const event = new ServerContextEvent(data);
1451
+ await this.capture(event);
1452
+ }
1453
+ // ============================================================================
1454
+ // Client Events
1455
+ // ============================================================================
1456
+ async trackMCPClientInit(data) {
1457
+ if (!this.isEnabled) return;
1458
+ const event = new MCPClientInitEvent(data);
1459
+ await this.capture(event);
1460
+ }
1461
+ async trackConnectorInit(data) {
1462
+ if (!this.isEnabled) return;
1463
+ const event = new ConnectorInitEvent(data);
1464
+ await this.capture(event);
1465
+ }
1466
+ async trackClientAddServer(serverName, serverConfig) {
1467
+ if (!this.isEnabled) return;
1468
+ const event = new ClientAddServerEvent({ serverName, serverConfig });
1469
+ await this.capture(event);
1470
+ }
1471
+ async trackClientRemoveServer(serverName) {
1472
+ if (!this.isEnabled) return;
1473
+ const event = new ClientRemoveServerEvent({ serverName });
1474
+ await this.capture(event);
1475
+ }
1476
+ // ============================================================================
1477
+ // React Hook / Browser specific events
1478
+ // ============================================================================
1479
+ async trackUseMcpConnection(data) {
1480
+ if (!this.isEnabled) return;
1481
+ await this.capture({
1482
+ name: "usemcp_connection",
1483
+ properties: {
1484
+ url_domain: new URL(data.url).hostname,
1485
+ // Only domain for privacy
1486
+ transport_type: data.transportType,
1487
+ success: data.success,
1488
+ error_type: data.errorType ?? null,
1489
+ connection_time_ms: data.connectionTimeMs ?? null,
1490
+ has_oauth: data.hasOAuth,
1491
+ has_sampling: data.hasSampling,
1492
+ has_elicitation: data.hasElicitation
1493
+ }
1494
+ });
1495
+ }
1496
+ async trackUseMcpToolCall(data) {
1497
+ if (!this.isEnabled) return;
1498
+ await this.capture({
1499
+ name: "usemcp_tool_call",
1500
+ properties: {
1501
+ tool_name: data.toolName,
1502
+ success: data.success,
1503
+ error_type: data.errorType ?? null,
1504
+ execution_time_ms: data.executionTimeMs ?? null
1505
+ }
1506
+ });
1507
+ }
1508
+ async trackUseMcpResourceRead(data) {
1509
+ if (!this.isEnabled) return;
1510
+ await this.capture({
1511
+ name: "usemcp_resource_read",
1512
+ properties: {
1513
+ resource_uri_scheme: data.resourceUri.split(":")[0],
1514
+ // Only scheme for privacy
1515
+ success: data.success,
1516
+ error_type: data.errorType ?? null
1517
+ }
1518
+ });
1519
+ }
1520
+ // ============================================================================
1521
+ // Browser-specific Methods
1522
+ // ============================================================================
1523
+ /**
1524
+ * Identify the current user (useful for linking sessions)
1525
+ * Browser only - no-op in Node.js
1526
+ */
1527
+ identify(userId, properties) {
1528
+ if (this._posthogBrowserClient) {
1529
+ try {
1530
+ this._posthogBrowserClient.identify(userId, properties);
1531
+ } catch (e) {
1532
+ logger.debug(`Failed to identify user: ${e}`);
1533
+ }
1534
+ }
1535
+ }
1536
+ /**
1537
+ * Reset the user identity (useful for logout)
1538
+ * Browser only - no-op in Node.js
1539
+ */
1540
+ reset() {
1541
+ if (this._posthogBrowserClient) {
1542
+ try {
1543
+ this._posthogBrowserClient.reset();
1544
+ } catch (e) {
1545
+ logger.debug(`Failed to reset user: ${e}`);
1546
+ }
1547
+ }
1548
+ this._currUserId = null;
1549
+ }
1550
+ // ============================================================================
1551
+ // Node.js-specific Methods
1552
+ // ============================================================================
1553
+ /**
1554
+ * Flush the telemetry queue (Node.js only)
1555
+ */
1556
+ flush() {
1557
+ if (this._posthogNodeClient) {
1558
+ try {
1559
+ this._posthogNodeClient.flush();
1560
+ logger.debug("PostHog client telemetry queue flushed");
1561
+ } catch (e) {
1562
+ logger.debug(`Failed to flush PostHog client: ${e}`);
1563
+ }
1564
+ }
1565
+ }
1566
+ /**
1567
+ * Shutdown the telemetry client (Node.js only)
1568
+ */
1569
+ shutdown() {
1570
+ if (this._posthogNodeClient) {
1571
+ try {
1572
+ this._posthogNodeClient.shutdown();
1573
+ logger.debug("PostHog client shutdown successfully");
1574
+ } catch (e) {
1575
+ logger.debug(`Error shutting down PostHog client: ${e}`);
1576
+ }
1577
+ }
1578
+ }
1579
+ };
1580
+ var Tel = Telemetry;
1581
+
1582
+ // src/client/base.ts
1583
+ var BaseMCPClient = class {
1584
+ static {
1585
+ __name(this, "BaseMCPClient");
1586
+ }
1587
+ config = {};
1588
+ sessions = {};
1589
+ activeSessions = [];
1590
+ constructor(config) {
1591
+ if (config) {
1592
+ this.config = config;
1593
+ }
1594
+ }
1595
+ static fromDict(_cfg) {
1596
+ throw new Error("fromDict must be implemented by concrete class");
1597
+ }
1598
+ addServer(name, serverConfig) {
1599
+ this.config.mcpServers = this.config.mcpServers || {};
1600
+ this.config.mcpServers[name] = serverConfig;
1601
+ Tel.getInstance().trackClientAddServer(name, serverConfig);
1602
+ }
1603
+ removeServer(name) {
1604
+ if (this.config.mcpServers?.[name]) {
1605
+ delete this.config.mcpServers[name];
1606
+ this.activeSessions = this.activeSessions.filter((n) => n !== name);
1607
+ Tel.getInstance().trackClientRemoveServer(name);
1608
+ }
1609
+ }
1610
+ getServerNames() {
1611
+ return Object.keys(this.config.mcpServers ?? {});
1612
+ }
1613
+ getServerConfig(name) {
1614
+ return this.config.mcpServers?.[name];
1615
+ }
1616
+ getConfig() {
1617
+ return this.config ?? {};
1618
+ }
1619
+ async createSession(serverName, autoInitialize = true) {
1620
+ const servers = this.config.mcpServers ?? {};
1621
+ if (Object.keys(servers).length === 0) {
1622
+ logger.warn("No MCP servers defined in config");
1623
+ }
1624
+ if (!servers[serverName]) {
1625
+ throw new Error(`Server '${serverName}' not found in config`);
1626
+ }
1627
+ const connector = this.createConnectorFromConfig(servers[serverName]);
1628
+ const session = new MCPSession(connector);
1629
+ if (autoInitialize) {
1630
+ await session.initialize();
1631
+ }
1632
+ this.sessions[serverName] = session;
1633
+ if (!this.activeSessions.includes(serverName)) {
1634
+ this.activeSessions.push(serverName);
1635
+ }
1636
+ return session;
1637
+ }
1638
+ async createAllSessions(autoInitialize = true) {
1639
+ const servers = this.config.mcpServers ?? {};
1640
+ if (Object.keys(servers).length === 0) {
1641
+ logger.warn("No MCP servers defined in config");
1642
+ }
1643
+ for (const name of Object.keys(servers)) {
1644
+ await this.createSession(name, autoInitialize);
1645
+ }
1646
+ return this.sessions;
1647
+ }
1648
+ getSession(serverName) {
1649
+ const session = this.sessions[serverName];
1650
+ if (!session) {
1651
+ return null;
1652
+ }
1653
+ return session;
1654
+ }
1655
+ requireSession(serverName) {
1656
+ const session = this.sessions[serverName];
1657
+ if (!session) {
1658
+ throw new Error(
1659
+ `Session '${serverName}' not found. Available sessions: ${this.activeSessions.join(", ") || "none"}`
1660
+ );
1661
+ }
1662
+ return session;
1663
+ }
1664
+ getAllActiveSessions() {
1665
+ return Object.fromEntries(
1666
+ this.activeSessions.map((n) => [n, this.sessions[n]])
1667
+ );
1668
+ }
1669
+ async closeSession(serverName) {
1670
+ const session = this.sessions[serverName];
1671
+ if (!session) {
1672
+ logger.warn(
1673
+ `No session exists for server ${serverName}, nothing to close`
1674
+ );
1675
+ return;
1676
+ }
1677
+ try {
1678
+ logger.debug(`Closing session for server ${serverName}`);
1679
+ await session.disconnect();
1680
+ } catch (e) {
1681
+ logger.error(`Error closing session for server '${serverName}': ${e}`);
1682
+ } finally {
1683
+ delete this.sessions[serverName];
1684
+ this.activeSessions = this.activeSessions.filter((n) => n !== serverName);
1685
+ }
1686
+ }
1687
+ async closeAllSessions() {
1688
+ const serverNames = Object.keys(this.sessions);
1689
+ const errors = [];
1690
+ for (const serverName of serverNames) {
1691
+ try {
1692
+ logger.debug(`Closing session for server ${serverName}`);
1693
+ await this.closeSession(serverName);
1694
+ } catch (e) {
1695
+ const errorMsg = `Failed to close session for server '${serverName}': ${e}`;
1696
+ logger.error(errorMsg);
1697
+ errors.push(errorMsg);
1698
+ }
1699
+ }
1700
+ if (errors.length) {
1701
+ logger.error(
1702
+ `Encountered ${errors.length} errors while closing sessions`
1703
+ );
1704
+ } else {
1705
+ logger.debug("All sessions closed successfully");
1706
+ }
1707
+ }
1708
+ };
1709
+
1710
+ // src/client/executors/base.ts
1711
+ var BaseCodeExecutor = class {
1712
+ static {
1713
+ __name(this, "BaseCodeExecutor");
1714
+ }
1715
+ client;
1716
+ _connecting = false;
1717
+ constructor(client) {
1718
+ this.client = client;
1719
+ }
1720
+ /**
1721
+ * Ensure all configured MCP servers are connected before execution.
1722
+ * Prevents race conditions with a connection lock.
1723
+ */
1724
+ async ensureServersConnected() {
1725
+ const configuredServers = this.client.getServerNames();
1726
+ const activeSessions = Object.keys(this.client.getAllActiveSessions());
1727
+ const missingServers = configuredServers.filter(
1728
+ (s) => !activeSessions.includes(s)
1729
+ );
1730
+ if (missingServers.length > 0 && !this._connecting) {
1731
+ this._connecting = true;
1732
+ try {
1733
+ logger.debug(
1734
+ `Connecting to configured servers for code execution: ${missingServers.join(", ")}`
1735
+ );
1736
+ await this.client.createAllSessions();
1737
+ } finally {
1738
+ this._connecting = false;
1739
+ }
1740
+ } else if (missingServers.length > 0 && this._connecting) {
1741
+ logger.debug("Waiting for ongoing server connection...");
1742
+ const startWait = Date.now();
1743
+ while (this._connecting && Date.now() - startWait < 5e3) {
1744
+ await new Promise((resolve) => setTimeout(resolve, 100));
1745
+ }
1746
+ }
1747
+ }
1748
+ /**
1749
+ * Get tool namespace information from all active MCP sessions.
1750
+ * Filters out the internal code_mode server.
1751
+ */
1752
+ getToolNamespaces() {
1753
+ const namespaces = [];
1754
+ const activeSessions = this.client.getAllActiveSessions();
1755
+ for (const [serverName, session] of Object.entries(activeSessions)) {
1756
+ if (serverName === "code_mode") continue;
1757
+ try {
1758
+ const connector = session.connector;
1759
+ let tools;
1760
+ try {
1761
+ tools = connector.tools;
1762
+ } catch (e) {
1763
+ logger.warn(`Tools not available for server ${serverName}: ${e}`);
1764
+ continue;
1765
+ }
1766
+ if (!tools || tools.length === 0) continue;
1767
+ namespaces.push({ serverName, tools, session });
1768
+ } catch (e) {
1769
+ logger.warn(`Failed to load tools for server ${serverName}: ${e}`);
1770
+ }
1771
+ }
1772
+ return namespaces;
1773
+ }
1774
+ /**
1775
+ * Create a search function for discovering available MCP tools.
1776
+ * Used by code execution environments to find tools at runtime.
1777
+ */
1778
+ createSearchToolsFunction() {
1779
+ return async (query = "", detailLevel = "full") => {
1780
+ const allTools = [];
1781
+ const allNamespaces = /* @__PURE__ */ new Set();
1782
+ const queryLower = query.toLowerCase();
1783
+ const activeSessions = this.client.getAllActiveSessions();
1784
+ for (const [serverName, session] of Object.entries(activeSessions)) {
1785
+ if (serverName === "code_mode") continue;
1786
+ try {
1787
+ const tools = session.connector.tools;
1788
+ if (tools && tools.length > 0) {
1789
+ allNamespaces.add(serverName);
1790
+ }
1791
+ for (const tool of tools) {
1792
+ if (detailLevel === "names") {
1793
+ allTools.push({ name: tool.name, server: serverName });
1794
+ } else if (detailLevel === "descriptions") {
1795
+ allTools.push({
1796
+ name: tool.name,
1797
+ server: serverName,
1798
+ description: tool.description
1799
+ });
1800
+ } else {
1801
+ allTools.push({
1802
+ name: tool.name,
1803
+ server: serverName,
1804
+ description: tool.description,
1805
+ input_schema: tool.inputSchema
1806
+ });
1807
+ }
1808
+ }
1809
+ } catch (e) {
1810
+ logger.warn(`Failed to search tools in server ${serverName}: ${e}`);
1811
+ }
1812
+ }
1813
+ let filteredTools = allTools;
1814
+ if (query) {
1815
+ filteredTools = allTools.filter((tool) => {
1816
+ const nameMatch = tool.name.toLowerCase().includes(queryLower);
1817
+ const descMatch = tool.description?.toLowerCase().includes(queryLower);
1818
+ const serverMatch = tool.server.toLowerCase().includes(queryLower);
1819
+ return nameMatch || descMatch || serverMatch;
1820
+ });
1821
+ }
1822
+ return {
1823
+ meta: {
1824
+ total_tools: allTools.length,
1825
+ namespaces: Array.from(allNamespaces).sort(),
1826
+ result_count: filteredTools.length
1827
+ },
1828
+ results: filteredTools
1829
+ };
1830
+ };
1831
+ }
1832
+ };
1833
+
1834
+ // src/client/executors/e2b.ts
1835
+ var E2BCodeExecutor = class extends BaseCodeExecutor {
1836
+ static {
1837
+ __name(this, "E2BCodeExecutor");
1838
+ }
1839
+ e2bApiKey;
1840
+ codeExecSandbox = null;
1841
+ SandboxClass = null;
1842
+ timeoutMs;
1843
+ constructor(client, options) {
1844
+ super(client);
1845
+ this.e2bApiKey = options.apiKey;
1846
+ this.timeoutMs = options.timeoutMs ?? 3e5;
1847
+ }
1848
+ /**
1849
+ * Lazy load E2B Sandbox class.
1850
+ * This allows the library to work without E2B installed.
1851
+ */
1852
+ async ensureSandboxClass() {
1853
+ if (this.SandboxClass) return;
1854
+ try {
1855
+ const e2b = await import("@e2b/code-interpreter");
1856
+ this.SandboxClass = e2b.Sandbox;
1857
+ } catch (error) {
1858
+ throw new Error(
1859
+ "@e2b/code-interpreter is not installed. The E2B code executor requires this optional dependency. Install it with: yarn add @e2b/code-interpreter"
1860
+ );
1861
+ }
1862
+ }
1863
+ /**
1864
+ * Get or create a dedicated sandbox for code execution.
1865
+ */
1866
+ async getOrCreateCodeExecSandbox() {
1867
+ if (this.codeExecSandbox) return this.codeExecSandbox;
1868
+ await this.ensureSandboxClass();
1869
+ logger.debug("Starting E2B sandbox for code execution...");
1870
+ this.codeExecSandbox = await this.SandboxClass.create("base", {
1871
+ apiKey: this.e2bApiKey,
1872
+ timeoutMs: this.timeoutMs
1873
+ });
1874
+ return this.codeExecSandbox;
1875
+ }
1876
+ /**
1877
+ * Generate the shim code that exposes tools to the sandbox environment.
1878
+ * Creates a bridge that intercepts tool calls and sends them back to host.
1879
+ */
1880
+ generateShim(tools) {
1881
+ let shim = `
1882
+ // MCP Bridge Shim
1883
+ global.__callMcpTool = async (server, tool, args) => {
1884
+ const id = Math.random().toString(36).substring(7);
1885
+ console.log(JSON.stringify({
1886
+ type: '__MCP_TOOL_CALL__',
1887
+ id,
1888
+ server,
1889
+ tool,
1890
+ args
1891
+ }));
1892
+
1893
+ const resultPath = \`/tmp/mcp_result_\${id}.json\`;
1894
+ const fs = require('fs');
1895
+
1896
+ // Poll for result file
1897
+ let attempts = 0;
1898
+ while (attempts < 300) { // 30 seconds timeout
1899
+ if (fs.existsSync(resultPath)) {
1900
+ const content = fs.readFileSync(resultPath, 'utf8');
1901
+ const result = JSON.parse(content);
1902
+ fs.unlinkSync(resultPath); // Clean up
1903
+
1904
+ if (result.error) {
1905
+ throw new Error(result.error);
1906
+ }
1907
+ return result.data;
1908
+ }
1909
+ await new Promise(resolve => setTimeout(resolve, 100));
1910
+ attempts++;
1911
+ }
1912
+ throw new Error('Tool execution timed out');
1913
+ };
1914
+
1915
+ // Global search_tools helper
1916
+ global.search_tools = async (query, detailLevel = 'full') => {
1917
+ const allTools = ${JSON.stringify(
1918
+ Object.entries(tools).flatMap(
1919
+ ([server, serverTools]) => serverTools.map((tool) => ({
1920
+ name: tool.name,
1921
+ description: tool.description,
1922
+ server,
1923
+ input_schema: tool.inputSchema
1924
+ }))
1925
+ )
1926
+ )};
1927
+
1928
+ const filtered = allTools.filter(tool => {
1929
+ if (!query) return true;
1930
+ const q = query.toLowerCase();
1931
+ return tool.name.toLowerCase().includes(q) ||
1932
+ (tool.description && tool.description.toLowerCase().includes(q));
1933
+ });
1934
+
1935
+ if (detailLevel === 'names') {
1936
+ return filtered.map(t => ({ name: t.name, server: t.server }));
1937
+ } else if (detailLevel === 'descriptions') {
1938
+ return filtered.map(t => ({ name: t.name, server: t.server, description: t.description }));
1939
+ }
1940
+ return filtered;
1941
+ };
1942
+ `;
1943
+ for (const [serverName, serverTools] of Object.entries(tools)) {
1944
+ if (!serverTools || serverTools.length === 0) continue;
1945
+ const safeServerName = serverName.replace(/[^a-zA-Z0-9_]/g, "_");
1946
+ shim += `
1947
+ global['${serverName}'] = {`;
1948
+ for (const tool of serverTools) {
1949
+ shim += `
1950
+ '${tool.name}': async (args) => await global.__callMcpTool('${serverName}', '${tool.name}', args),`;
1951
+ }
1952
+ shim += `
1953
+ };
1954
+
1955
+ // Also expose as safe name if different
1956
+ if ('${safeServerName}' !== '${serverName}') {
1957
+ global['${safeServerName}'] = global['${serverName}'];
1958
+ }
1959
+ `;
1960
+ }
1961
+ return shim;
1962
+ }
1963
+ /**
1964
+ * Build the tool catalog for the shim.
1965
+ * Returns a map of server names to their available tools.
1966
+ */
1967
+ buildToolCatalog() {
1968
+ const catalog = {};
1969
+ const namespaces = this.getToolNamespaces();
1970
+ for (const { serverName, tools } of namespaces) {
1971
+ catalog[serverName] = tools;
1972
+ }
1973
+ return catalog;
1974
+ }
1975
+ /**
1976
+ * Execute JavaScript/TypeScript code in an E2B sandbox with MCP tool access.
1977
+ * Tool calls are proxied back to the host via the bridge pattern.
1978
+ *
1979
+ * @param code - Code to execute
1980
+ * @param timeout - Execution timeout in milliseconds (default: 30000)
1981
+ */
1982
+ async execute(code, timeout = 3e4) {
1983
+ const startTime = Date.now();
1984
+ let result = null;
1985
+ let error = null;
1986
+ let logs = [];
1987
+ try {
1988
+ await this.ensureServersConnected();
1989
+ const sandbox = await this.getOrCreateCodeExecSandbox();
1990
+ const toolCatalog = this.buildToolCatalog();
1991
+ const shim = this.generateShim(toolCatalog);
1992
+ const wrappedCode = `
1993
+ ${shim}
1994
+
1995
+ (async () => {
1996
+ try {
1997
+ const func = async () => {
1998
+ ${code}
1999
+ };
2000
+ const result = await func();
2001
+ console.log('__MCP_RESULT_START__');
2002
+ console.log(JSON.stringify(result));
2003
+ console.log('__MCP_RESULT_END__');
2004
+ } catch (e) {
2005
+ console.error(e);
2006
+ process.exit(1);
2007
+ }
2008
+ })();
2009
+ `;
2010
+ const filename = `exec_${Date.now()}.js`;
2011
+ await sandbox.files.write(filename, wrappedCode);
2012
+ const execution = await sandbox.commands.run(`node ${filename}`, {
2013
+ timeoutMs: timeout,
2014
+ onStdout: /* @__PURE__ */ __name(async (data) => {
2015
+ try {
2016
+ const lines = data.split("\n");
2017
+ for (const line of lines) {
2018
+ if (line.trim().startsWith('{"type":"__MCP_TOOL_CALL__"')) {
2019
+ const call = JSON.parse(line);
2020
+ if (call.type === "__MCP_TOOL_CALL__") {
2021
+ try {
2022
+ logger.debug(
2023
+ `[E2B Bridge] Calling tool ${call.server}.${call.tool}`
2024
+ );
2025
+ const activeSessions = this.client.getAllActiveSessions();
2026
+ const session = activeSessions[call.server];
2027
+ if (!session) {
2028
+ throw new Error(`Server ${call.server} not found`);
2029
+ }
2030
+ const toolResult = await session.connector.callTool(
2031
+ call.tool,
2032
+ call.args
2033
+ );
2034
+ let extractedResult = toolResult;
2035
+ if (toolResult.content && toolResult.content.length > 0) {
2036
+ const item = toolResult.content[0];
2037
+ if (item.type === "text") {
2038
+ try {
2039
+ extractedResult = JSON.parse(item.text);
2040
+ } catch {
2041
+ extractedResult = item.text;
2042
+ }
2043
+ } else {
2044
+ extractedResult = item;
2045
+ }
2046
+ }
2047
+ const resultPath = `/tmp/mcp_result_${call.id}.json`;
2048
+ await sandbox.files.write(
2049
+ resultPath,
2050
+ JSON.stringify({ data: extractedResult })
2051
+ );
2052
+ } catch (err) {
2053
+ logger.error(
2054
+ `[E2B Bridge] Tool execution failed: ${err.message}`
2055
+ );
2056
+ const resultPath = `/tmp/mcp_result_${call.id}.json`;
2057
+ await sandbox.files.write(
2058
+ resultPath,
2059
+ JSON.stringify({
2060
+ error: err.message || String(err)
2061
+ })
2062
+ );
2063
+ }
2064
+ }
2065
+ }
2066
+ }
2067
+ } catch (e) {
2068
+ }
2069
+ }, "onStdout")
2070
+ });
2071
+ logs = [execution.stdout, execution.stderr].filter(Boolean);
2072
+ if (execution.exitCode !== 0) {
2073
+ error = execution.stderr || "Execution failed";
2074
+ } else {
2075
+ const stdout = execution.stdout;
2076
+ const startMarker = "__MCP_RESULT_START__";
2077
+ const endMarker = "__MCP_RESULT_END__";
2078
+ const startIndex = stdout.indexOf(startMarker);
2079
+ const endIndex = stdout.indexOf(endMarker);
2080
+ if (startIndex !== -1 && endIndex !== -1) {
2081
+ const jsonStr = stdout.substring(startIndex + startMarker.length, endIndex).trim();
2082
+ try {
2083
+ result = JSON.parse(jsonStr);
2084
+ } catch (e) {
2085
+ result = jsonStr;
2086
+ }
2087
+ logs = logs.map((log) => {
2088
+ let cleaned = log.replace(
2089
+ new RegExp(startMarker + "[\\s\\S]*?" + endMarker),
2090
+ "[Result captured]"
2091
+ );
2092
+ cleaned = cleaned.split("\n").filter((l) => !l.includes("__MCP_TOOL_CALL__")).join("\n");
2093
+ return cleaned;
2094
+ });
2095
+ }
2096
+ }
2097
+ } catch (e) {
2098
+ error = e.message || String(e);
2099
+ if (error && (error.includes("timeout") || error.includes("timed out"))) {
2100
+ error = "Script execution timed out";
2101
+ }
2102
+ }
2103
+ return {
2104
+ result,
2105
+ logs,
2106
+ error,
2107
+ execution_time: (Date.now() - startTime) / 1e3
2108
+ };
2109
+ }
2110
+ /**
2111
+ * Clean up the E2B sandbox.
2112
+ * Should be called when the executor is no longer needed.
2113
+ */
2114
+ async cleanup() {
2115
+ if (this.codeExecSandbox) {
2116
+ try {
2117
+ await this.codeExecSandbox.kill();
2118
+ this.codeExecSandbox = null;
2119
+ logger.debug("E2B code execution sandbox stopped");
2120
+ } catch (error) {
2121
+ logger.error("Failed to stop E2B code execution sandbox:", error);
2122
+ }
2123
+ }
2124
+ }
2125
+ };
2126
+
2127
+ // src/client/executors/vm.ts
2128
+ var vm = null;
2129
+ var vmCheckAttempted = false;
2130
+ function getVMModuleName() {
2131
+ return ["node", "vm"].join(":");
2132
+ }
2133
+ __name(getVMModuleName, "getVMModuleName");
2134
+ function tryLoadVM() {
2135
+ if (vmCheckAttempted) {
2136
+ return vm !== null;
2137
+ }
2138
+ vmCheckAttempted = true;
2139
+ try {
2140
+ const nodeRequire = typeof require !== "undefined" ? require : null;
2141
+ if (nodeRequire) {
2142
+ vm = nodeRequire(getVMModuleName());
2143
+ return true;
2144
+ }
2145
+ } catch (error) {
2146
+ logger.debug("node:vm module not available via require");
2147
+ }
2148
+ return false;
2149
+ }
2150
+ __name(tryLoadVM, "tryLoadVM");
2151
+ async function tryLoadVMAsync() {
2152
+ if (vm !== null) {
2153
+ return true;
2154
+ }
2155
+ if (!vmCheckAttempted) {
2156
+ if (tryLoadVM()) {
2157
+ return true;
2158
+ }
2159
+ }
2160
+ try {
2161
+ vm = await import(
2162
+ /* @vite-ignore */
2163
+ getVMModuleName()
2164
+ );
2165
+ return true;
2166
+ } catch (error) {
2167
+ logger.debug(
2168
+ "node:vm module not available in this environment (e.g., Deno)"
2169
+ );
2170
+ return false;
2171
+ }
2172
+ }
2173
+ __name(tryLoadVMAsync, "tryLoadVMAsync");
2174
+ function isVMAvailable() {
2175
+ tryLoadVM();
2176
+ return vm !== null;
2177
+ }
2178
+ __name(isVMAvailable, "isVMAvailable");
2179
+ var VMCodeExecutor = class extends BaseCodeExecutor {
2180
+ static {
2181
+ __name(this, "VMCodeExecutor");
2182
+ }
2183
+ defaultTimeout;
2184
+ memoryLimitMb;
2185
+ constructor(client, options) {
2186
+ super(client);
2187
+ this.defaultTimeout = options?.timeoutMs ?? 3e4;
2188
+ this.memoryLimitMb = options?.memoryLimitMb;
2189
+ tryLoadVM();
2190
+ }
2191
+ /**
2192
+ * Ensure VM module is loaded before execution
2193
+ */
2194
+ async ensureVMLoaded() {
2195
+ if (vm !== null) {
2196
+ return;
2197
+ }
2198
+ const loaded = await tryLoadVMAsync();
2199
+ if (!loaded) {
2200
+ throw new Error(
2201
+ "node:vm module is not available in this environment. Please use E2B executor instead or run in a Node.js environment."
2202
+ );
2203
+ }
2204
+ }
2205
+ /**
2206
+ * Execute JavaScript/TypeScript code with access to MCP tools.
2207
+ *
2208
+ * @param code - Code to execute
2209
+ * @param timeout - Execution timeout in milliseconds (default: configured timeout or 30000)
2210
+ */
2211
+ async execute(code, timeout) {
2212
+ const effectiveTimeout = timeout ?? this.defaultTimeout;
2213
+ await this.ensureVMLoaded();
2214
+ await this.ensureServersConnected();
2215
+ const logs = [];
2216
+ const startTime = Date.now();
2217
+ let result = null;
2218
+ let error = null;
2219
+ try {
2220
+ const context = await this._buildContext(logs);
2221
+ const wrappedCode = `
2222
+ (async () => {
2223
+ try {
2224
+ ${code}
2225
+ } catch (e) {
2226
+ throw e;
2227
+ }
2228
+ })()
2229
+ `;
2230
+ const script = new vm.Script(wrappedCode, {
2231
+ filename: "agent_code.js"
2232
+ });
2233
+ const promise = script.runInNewContext(context, {
2234
+ timeout: effectiveTimeout,
2235
+ displayErrors: true
2236
+ });
2237
+ result = await promise;
2238
+ } catch (e) {
2239
+ error = e.message || String(e);
2240
+ if (e.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || e.message === "Script execution timed out." || typeof error === "string" && (error.includes("timed out") || error.includes("timeout"))) {
2241
+ error = "Script execution timed out";
2242
+ }
2243
+ if (e.stack) {
2244
+ logger.debug(`Code execution error stack: ${e.stack}`);
2245
+ }
2246
+ }
2247
+ const executionTime = (Date.now() - startTime) / 1e3;
2248
+ return {
2249
+ result,
2250
+ logs,
2251
+ error,
2252
+ execution_time: executionTime
2253
+ };
2254
+ }
2255
+ /**
2256
+ * Build the VM execution context with MCP tools and standard globals.
2257
+ *
2258
+ * @param logs - Array to capture console output
2259
+ */
2260
+ async _buildContext(logs) {
2261
+ const logHandler = /* @__PURE__ */ __name((...args) => {
2262
+ logs.push(
2263
+ args.map(
2264
+ (arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
2265
+ ).join(" ")
2266
+ );
2267
+ }, "logHandler");
2268
+ const sandbox = {
2269
+ console: {
2270
+ log: logHandler,
2271
+ error: /* @__PURE__ */ __name((...args) => {
2272
+ logHandler("[ERROR]", ...args);
2273
+ }, "error"),
2274
+ warn: /* @__PURE__ */ __name((...args) => {
2275
+ logHandler("[WARN]", ...args);
2276
+ }, "warn"),
2277
+ info: logHandler,
2278
+ debug: logHandler
2279
+ },
2280
+ // Standard globals
2281
+ Object,
2282
+ Array,
2283
+ String,
2284
+ Number,
2285
+ Boolean,
2286
+ Date,
2287
+ Math,
2288
+ JSON,
2289
+ RegExp,
2290
+ Map,
2291
+ Set,
2292
+ Promise,
2293
+ parseInt,
2294
+ parseFloat,
2295
+ isNaN,
2296
+ isFinite,
2297
+ encodeURI,
2298
+ decodeURI,
2299
+ encodeURIComponent,
2300
+ decodeURIComponent,
2301
+ setTimeout,
2302
+ clearTimeout,
2303
+ // Helper for tools
2304
+ search_tools: this.createSearchToolsFunction(),
2305
+ __tool_namespaces: []
2306
+ };
2307
+ const toolNamespaces = {};
2308
+ const namespaceInfos = this.getToolNamespaces();
2309
+ for (const { serverName, tools, session } of namespaceInfos) {
2310
+ const serverNamespace = {};
2311
+ for (const tool of tools) {
2312
+ const toolName = tool.name;
2313
+ serverNamespace[toolName] = async (args) => {
2314
+ const result = await session.connector.callTool(toolName, args || {});
2315
+ if (result.content && result.content.length > 0) {
2316
+ const item = result.content[0];
2317
+ if (item.type === "text") {
2318
+ try {
2319
+ return JSON.parse(item.text);
2320
+ } catch {
2321
+ return item.text;
2322
+ }
2323
+ }
2324
+ return item;
2325
+ }
2326
+ return result;
2327
+ };
2328
+ }
2329
+ sandbox[serverName] = serverNamespace;
2330
+ toolNamespaces[serverName] = true;
2331
+ }
2332
+ sandbox.__tool_namespaces = Object.keys(toolNamespaces);
2333
+ return vm.createContext(sandbox);
2334
+ }
2335
+ /**
2336
+ * Clean up resources.
2337
+ * VM executor doesn't need cleanup, but method kept for interface consistency.
2338
+ */
2339
+ async cleanup() {
2340
+ }
2341
+ };
2342
+
2343
+ // src/connectors/base.ts
2344
+ var import_types = require("@mcp-use/modelcontextprotocol-sdk/types.js");
2345
+ var BaseConnector = class {
2346
+ static {
2347
+ __name(this, "BaseConnector");
2348
+ }
2349
+ client = null;
2350
+ connectionManager = null;
2351
+ toolsCache = null;
2352
+ capabilitiesCache = null;
2353
+ serverInfoCache = null;
2354
+ connected = false;
2355
+ opts;
2356
+ notificationHandlers = [];
2357
+ rootsCache = [];
2358
+ constructor(opts = {}) {
2359
+ this.opts = opts;
2360
+ if (opts.roots) {
2361
+ this.rootsCache = [...opts.roots];
2362
+ }
2363
+ }
2364
+ /**
2365
+ * Track connector initialization event
2366
+ * Should be called by subclasses after successful connection
2367
+ */
2368
+ trackConnectorInit(data) {
2369
+ const connectorType = this.constructor.name;
2370
+ Telemetry.getInstance().trackConnectorInit({
2371
+ connectorType,
2372
+ ...data
2373
+ }).catch((e) => logger.debug(`Failed to track connector init: ${e}`));
2374
+ }
2375
+ /**
2376
+ * Register a handler for server notifications
2377
+ *
2378
+ * @param handler - Function to call when a notification is received
2379
+ *
2380
+ * @example
2381
+ * ```typescript
2382
+ * connector.onNotification((notification) => {
2383
+ * console.log(`Received: ${notification.method}`, notification.params);
2384
+ * });
2385
+ * ```
2386
+ */
2387
+ onNotification(handler) {
2388
+ this.notificationHandlers.push(handler);
2389
+ if (this.client) {
2390
+ this.setupNotificationHandler();
2391
+ }
2392
+ }
2393
+ /**
2394
+ * Internal: wire notification handlers to the SDK client
2395
+ * Includes automatic handling for list_changed notifications per MCP spec
2396
+ */
2397
+ setupNotificationHandler() {
2398
+ if (!this.client) return;
2399
+ this.client.fallbackNotificationHandler = async (notification) => {
2400
+ switch (notification.method) {
2401
+ case "notifications/tools/list_changed":
2402
+ await this.refreshToolsCache();
2403
+ break;
2404
+ case "notifications/resources/list_changed":
2405
+ await this.onResourcesListChanged();
2406
+ break;
2407
+ case "notifications/prompts/list_changed":
2408
+ await this.onPromptsListChanged();
2409
+ break;
2410
+ default:
2411
+ break;
2412
+ }
2413
+ for (const handler of this.notificationHandlers) {
2414
+ try {
2415
+ await handler(notification);
2416
+ } catch (err) {
2417
+ logger.error("Error in notification handler:", err);
2418
+ }
2419
+ }
2420
+ };
2421
+ }
2422
+ /**
2423
+ * Auto-refresh tools cache when server sends tools/list_changed notification
2424
+ */
2425
+ async refreshToolsCache() {
2426
+ if (!this.client) return;
2427
+ try {
2428
+ logger.debug(
2429
+ "[Auto] Refreshing tools cache due to list_changed notification"
2430
+ );
2431
+ const result = await this.client.listTools();
2432
+ this.toolsCache = result.tools ?? [];
2433
+ logger.debug(
2434
+ `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
2435
+ );
2436
+ } catch (err) {
2437
+ logger.warn("[Auto] Failed to refresh tools cache:", err);
2438
+ }
2439
+ }
2440
+ /**
2441
+ * Called when server sends resources/list_changed notification
2442
+ * Resources aren't cached by default, but we log for user awareness
2443
+ */
2444
+ async onResourcesListChanged() {
2445
+ logger.debug(
2446
+ "[Auto] Resources list changed - clients should re-fetch if needed"
2447
+ );
2448
+ }
2449
+ /**
2450
+ * Called when server sends prompts/list_changed notification
2451
+ * Prompts aren't cached by default, but we log for user awareness
2452
+ */
2453
+ async onPromptsListChanged() {
2454
+ logger.debug(
2455
+ "[Auto] Prompts list changed - clients should re-fetch if needed"
2456
+ );
2457
+ }
2458
+ /**
2459
+ * Set roots and notify the server.
2460
+ * Roots represent directories or files that the client has access to.
2461
+ *
2462
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
2463
+ *
2464
+ * @example
2465
+ * ```typescript
2466
+ * await connector.setRoots([
2467
+ * { uri: "file:///home/user/project", name: "My Project" },
2468
+ * { uri: "file:///home/user/data" }
2469
+ * ]);
2470
+ * ```
2471
+ */
2472
+ async setRoots(roots) {
2473
+ this.rootsCache = [...roots];
2474
+ if (this.client) {
2475
+ logger.debug(
2476
+ `Sending roots/list_changed notification with ${roots.length} root(s)`
2477
+ );
2478
+ await this.client.sendRootsListChanged();
2479
+ }
2480
+ }
2481
+ /**
2482
+ * Get the current roots.
2483
+ */
2484
+ getRoots() {
2485
+ return [...this.rootsCache];
2486
+ }
2487
+ /**
2488
+ * Internal: set up roots/list request handler.
2489
+ * This is called after the client connects to register the handler for server requests.
2490
+ */
2491
+ setupRootsHandler() {
2492
+ if (!this.client) return;
2493
+ this.client.setRequestHandler(
2494
+ import_types.ListRootsRequestSchema,
2495
+ async (_request, _extra) => {
2496
+ logger.debug(
2497
+ `Server requested roots list, returning ${this.rootsCache.length} root(s)`
2498
+ );
2499
+ return { roots: this.rootsCache };
2500
+ }
2501
+ );
2502
+ }
2503
+ /**
2504
+ * Internal: set up sampling/createMessage request handler.
2505
+ * This is called after the client connects to register the handler for sampling requests.
2506
+ */
2507
+ setupSamplingHandler() {
2508
+ if (!this.client) {
2509
+ logger.debug("setupSamplingHandler: No client available");
2510
+ return;
2511
+ }
2512
+ if (!this.opts.samplingCallback) {
2513
+ logger.debug("setupSamplingHandler: No sampling callback provided");
2514
+ return;
2515
+ }
2516
+ logger.debug("setupSamplingHandler: Setting up sampling request handler");
2517
+ this.client.setRequestHandler(
2518
+ import_types.CreateMessageRequestSchema,
2519
+ async (request, _extra) => {
2520
+ logger.debug("Server requested sampling, forwarding to callback");
2521
+ return await this.opts.samplingCallback(request.params);
2522
+ }
2523
+ );
2524
+ logger.debug(
2525
+ "setupSamplingHandler: Sampling handler registered successfully"
2526
+ );
2527
+ }
2528
+ /**
2529
+ * Internal: set up elicitation/create request handler.
2530
+ * This is called after the client connects to register the handler for elicitation requests.
2531
+ */
2532
+ setupElicitationHandler() {
2533
+ if (!this.client) {
2534
+ logger.debug("setupElicitationHandler: No client available");
2535
+ return;
2536
+ }
2537
+ if (!this.opts.elicitationCallback) {
2538
+ logger.debug("setupElicitationHandler: No elicitation callback provided");
2539
+ return;
2540
+ }
2541
+ logger.debug(
2542
+ "setupElicitationHandler: Setting up elicitation request handler"
2543
+ );
2544
+ this.client.setRequestHandler(
2545
+ import_types.ElicitRequestSchema,
2546
+ async (request, _extra) => {
2547
+ logger.debug("Server requested elicitation, forwarding to callback");
2548
+ return await this.opts.elicitationCallback(request.params);
2549
+ }
2550
+ );
2551
+ logger.debug(
2552
+ "setupElicitationHandler: Elicitation handler registered successfully"
2553
+ );
2554
+ }
2555
+ /** Disconnect and release resources. */
2556
+ async disconnect() {
2557
+ if (!this.connected) {
2558
+ logger.debug("Not connected to MCP implementation");
2559
+ return;
2560
+ }
2561
+ logger.debug("Disconnecting from MCP implementation");
2562
+ await this.cleanupResources();
2563
+ this.connected = false;
2564
+ logger.debug("Disconnected from MCP implementation");
2565
+ }
2566
+ /** Check if the client is connected */
2567
+ get isClientConnected() {
2568
+ return this.client != null;
2569
+ }
2570
+ /**
2571
+ * Initialise the MCP session **after** `connect()` has succeeded.
2572
+ *
2573
+ * In the SDK, `Client.connect(transport)` automatically performs the
2574
+ * protocol‑level `initialize` handshake, so we only need to cache the list of
2575
+ * tools and expose some server info.
2576
+ */
2577
+ async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
2578
+ if (!this.client) {
2579
+ throw new Error("MCP client is not connected");
2580
+ }
2581
+ logger.debug("Caching server capabilities & tools");
2582
+ const capabilities = this.client.getServerCapabilities();
2583
+ this.capabilitiesCache = capabilities || null;
2584
+ const serverInfo = this.client.getServerVersion();
2585
+ this.serverInfoCache = serverInfo || null;
2586
+ const listToolsRes = await this.client.listTools(
2587
+ void 0,
2588
+ defaultRequestOptions
2589
+ );
2590
+ this.toolsCache = listToolsRes.tools ?? [];
2591
+ logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
2592
+ logger.debug("Server capabilities:", capabilities);
2593
+ logger.debug("Server info:", serverInfo);
2594
+ return capabilities;
2595
+ }
2596
+ /** Lazily expose the cached tools list. */
2597
+ get tools() {
2598
+ if (!this.toolsCache) {
2599
+ throw new Error("MCP client is not initialized; call initialize() first");
2600
+ }
2601
+ return this.toolsCache;
2602
+ }
2603
+ /** Expose cached server capabilities. */
2604
+ get serverCapabilities() {
2605
+ return this.capabilitiesCache || {};
2606
+ }
2607
+ /** Expose cached server info. */
2608
+ get serverInfo() {
2609
+ return this.serverInfoCache;
2610
+ }
2611
+ /** Call a tool on the server. */
2612
+ async callTool(name, args, options) {
2613
+ if (!this.client) {
2614
+ throw new Error("MCP client is not connected");
2615
+ }
2616
+ const enhancedOptions = options ? { ...options } : void 0;
2617
+ if (enhancedOptions?.resetTimeoutOnProgress && !enhancedOptions.onprogress) {
2618
+ enhancedOptions.onprogress = () => {
2619
+ };
2620
+ logger.debug(
2621
+ `[BaseConnector] Added onprogress callback for tool '${name}' to enable progressToken`
2622
+ );
2623
+ }
2624
+ logger.debug(`Calling tool '${name}' with args`, args);
2625
+ const res = await this.client.callTool(
2626
+ { name, arguments: args },
2627
+ void 0,
2628
+ enhancedOptions
2629
+ );
2630
+ logger.debug(`Tool '${name}' returned`, res);
2631
+ return res;
2632
+ }
2633
+ /**
2634
+ * List all available tools from the MCP server.
2635
+ * This method fetches fresh tools from the server, unlike the `tools` getter which returns cached tools.
2636
+ *
2637
+ * @param options - Optional request options
2638
+ * @returns Array of available tools
2639
+ */
2640
+ async listTools(options) {
2641
+ if (!this.client) {
2642
+ throw new Error("MCP client is not connected");
2643
+ }
2644
+ const result = await this.client.listTools(void 0, options);
2645
+ return result.tools ?? [];
2646
+ }
2647
+ /**
2648
+ * List resources from the server with optional pagination
2649
+ *
2650
+ * @param cursor - Optional cursor for pagination
2651
+ * @param options - Request options
2652
+ * @returns Resource list with optional nextCursor for pagination
2653
+ */
2654
+ async listResources(cursor, options) {
2655
+ if (!this.client) {
2656
+ throw new Error("MCP client is not connected");
2657
+ }
2658
+ logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
2659
+ return await this.client.listResources({ cursor }, options);
2660
+ }
2661
+ /**
2662
+ * List all resources from the server, automatically handling pagination
2663
+ *
2664
+ * @param options - Request options
2665
+ * @returns Complete list of all resources
2666
+ */
2667
+ async listAllResources(options) {
2668
+ if (!this.client) {
2669
+ throw new Error("MCP client is not connected");
2670
+ }
2671
+ if (!this.capabilitiesCache?.resources) {
2672
+ logger.debug("Server does not advertise resources capability, skipping");
2673
+ return { resources: [] };
2674
+ }
2675
+ try {
2676
+ logger.debug("Listing all resources (with auto-pagination)");
2677
+ const allResources = [];
2678
+ let cursor = void 0;
2679
+ do {
2680
+ const result = await this.client.listResources({ cursor }, options);
2681
+ allResources.push(...result.resources || []);
2682
+ cursor = result.nextCursor;
2683
+ } while (cursor);
2684
+ return { resources: allResources };
2685
+ } catch (err) {
2686
+ const error = err;
2687
+ if (error.code === -32601) {
2688
+ logger.debug("Server advertised resources but method not found");
2689
+ return { resources: [] };
2690
+ }
2691
+ throw err;
2692
+ }
2693
+ }
2694
+ /**
2695
+ * List resource templates from the server
2696
+ *
2697
+ * @param options - Request options
2698
+ * @returns List of available resource templates
2699
+ */
2700
+ async listResourceTemplates(options) {
2701
+ if (!this.client) {
2702
+ throw new Error("MCP client is not connected");
2703
+ }
2704
+ logger.debug("Listing resource templates");
2705
+ return await this.client.listResourceTemplates(void 0, options);
2706
+ }
2707
+ /** Read a resource by URI. */
2708
+ async readResource(uri, options) {
2709
+ if (!this.client) {
2710
+ throw new Error("MCP client is not connected");
2711
+ }
2712
+ logger.debug(`Reading resource ${uri}`);
2713
+ const res = await this.client.readResource({ uri }, options);
2714
+ return res;
2715
+ }
2716
+ /**
2717
+ * Subscribe to resource updates
2718
+ *
2719
+ * @param uri - URI of the resource to subscribe to
2720
+ * @param options - Request options
2721
+ */
2722
+ async subscribeToResource(uri, options) {
2723
+ if (!this.client) {
2724
+ throw new Error("MCP client is not connected");
2725
+ }
2726
+ logger.debug(`Subscribing to resource: ${uri}`);
2727
+ return await this.client.subscribeResource({ uri }, options);
2728
+ }
2729
+ /**
2730
+ * Unsubscribe from resource updates
2731
+ *
2732
+ * @param uri - URI of the resource to unsubscribe from
2733
+ * @param options - Request options
2734
+ */
2735
+ async unsubscribeFromResource(uri, options) {
2736
+ if (!this.client) {
2737
+ throw new Error("MCP client is not connected");
2738
+ }
2739
+ logger.debug(`Unsubscribing from resource: ${uri}`);
2740
+ return await this.client.unsubscribeResource({ uri }, options);
2741
+ }
2742
+ async listPrompts() {
2743
+ if (!this.client) {
2744
+ throw new Error("MCP client is not connected");
2745
+ }
2746
+ if (!this.capabilitiesCache?.prompts) {
2747
+ logger.debug("Server does not advertise prompts capability, skipping");
2748
+ return { prompts: [] };
2749
+ }
2750
+ try {
2751
+ logger.debug("Listing prompts");
2752
+ return await this.client.listPrompts();
2753
+ } catch (err) {
2754
+ const error = err;
2755
+ if (error.code === -32601) {
2756
+ logger.debug("Server advertised prompts but method not found");
2757
+ return { prompts: [] };
2758
+ }
2759
+ throw err;
2760
+ }
2761
+ }
2762
+ async getPrompt(name, args) {
2763
+ if (!this.client) {
2764
+ throw new Error("MCP client is not connected");
2765
+ }
2766
+ logger.debug(`Getting prompt ${name}`);
2767
+ return await this.client.getPrompt({ name, arguments: args });
2768
+ }
2769
+ /** Send a raw request through the client. */
2770
+ async request(method, params = null, options) {
2771
+ if (!this.client) {
2772
+ throw new Error("MCP client is not connected");
2773
+ }
2774
+ logger.debug(`Sending raw request '${method}' with params`, params);
2775
+ return await this.client.request(
2776
+ { method, params: params ?? {} },
2777
+ void 0,
2778
+ options
2779
+ );
2780
+ }
2781
+ /**
2782
+ * Helper to tear down the client & connection manager safely.
2783
+ */
2784
+ async cleanupResources() {
2785
+ const issues = [];
2786
+ if (this.client) {
2787
+ try {
2788
+ if (typeof this.client.close === "function") {
2789
+ await this.client.close();
2790
+ }
2791
+ } catch (e) {
2792
+ const msg = `Error closing client: ${e}`;
2793
+ logger.warn(msg);
2794
+ issues.push(msg);
2795
+ } finally {
2796
+ this.client = null;
2797
+ }
2798
+ }
2799
+ if (this.connectionManager) {
2800
+ try {
2801
+ await this.connectionManager.stop();
2802
+ } catch (e) {
2803
+ const msg = `Error stopping connection manager: ${e}`;
2804
+ logger.warn(msg);
2805
+ issues.push(msg);
2806
+ } finally {
2807
+ this.connectionManager = null;
2808
+ }
2809
+ }
2810
+ this.toolsCache = null;
2811
+ if (issues.length) {
2812
+ logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
2813
+ }
2814
+ }
2815
+ };
2816
+
2817
+ // src/client/connectors/codeMode.ts
2818
+ var CodeModeConnector = class extends BaseConnector {
2819
+ static {
2820
+ __name(this, "CodeModeConnector");
2821
+ }
2822
+ mcpClient;
2823
+ _tools;
2824
+ constructor(client) {
2825
+ super();
2826
+ this.mcpClient = client;
2827
+ this.connected = true;
2828
+ this._tools = this._createToolsList();
2829
+ }
2830
+ async connect() {
2831
+ this.connected = true;
2832
+ }
2833
+ async disconnect() {
2834
+ this.connected = false;
2835
+ }
2836
+ get publicIdentifier() {
2837
+ return { name: "code_mode", version: "1.0.0" };
2838
+ }
2839
+ _createToolsList() {
2840
+ return [
2841
+ {
2842
+ name: "execute_code",
2843
+ 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.",
2844
+ inputSchema: {
2845
+ type: "object",
2846
+ properties: {
2847
+ code: {
2848
+ type: "string",
2849
+ 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"
2850
+ },
2851
+ timeout: {
2852
+ type: "number",
2853
+ description: "Execution timeout in milliseconds",
2854
+ default: 3e4
2855
+ }
2856
+ },
2857
+ required: ["code"]
2858
+ }
2859
+ },
2860
+ {
2861
+ name: "search_tools",
2862
+ 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.",
2863
+ inputSchema: {
2864
+ type: "object",
2865
+ properties: {
2866
+ query: {
2867
+ type: "string",
2868
+ description: "Search query to filter tools by name or description",
2869
+ default: ""
2870
+ },
2871
+ detail_level: {
2872
+ type: "string",
2873
+ description: "Detail level: 'names', 'descriptions', or 'full'",
2874
+ enum: ["names", "descriptions", "full"],
2875
+ default: "full"
2876
+ }
2877
+ }
2878
+ }
2879
+ }
2880
+ ];
2881
+ }
2882
+ // Override tools getter to return static list immediately
2883
+ get tools() {
2884
+ return this._tools;
2885
+ }
2886
+ async initialize() {
2887
+ this.toolsCache = this._tools;
2888
+ return { capabilities: {}, version: "1.0.0" };
2889
+ }
2890
+ async callTool(name, args) {
2891
+ if (name === "execute_code") {
2892
+ const code = args.code;
2893
+ const timeout = args.timeout || 3e4;
2894
+ const result = await this.mcpClient.executeCode(code, timeout);
2895
+ return {
2896
+ content: [
2897
+ {
2898
+ type: "text",
2899
+ text: JSON.stringify(result)
2900
+ }
2901
+ ]
2902
+ };
2903
+ } else if (name === "search_tools") {
2904
+ const query = args.query || "";
2905
+ const detailLevel = args.detail_level;
2906
+ const result = await this.mcpClient.searchTools(
2907
+ query,
2908
+ detailLevel && detailLevel in ["names", "descriptions", "full"] ? detailLevel : "full"
2909
+ );
2910
+ return {
2911
+ content: [
2912
+ {
2913
+ type: "text",
2914
+ text: JSON.stringify(result)
2915
+ }
2916
+ ]
2917
+ };
2918
+ }
2919
+ throw new Error(`Unknown tool: ${name}`);
2920
+ }
2921
+ };
2922
+
2923
+ // src/config.ts
2924
+ var import_node_fs = require("fs");
2925
+
2926
+ // src/connectors/http.ts
2927
+ var import_client = require("@mcp-use/modelcontextprotocol-sdk/client/index.js");
2928
+ var import_streamableHttp = require("@mcp-use/modelcontextprotocol-sdk/client/streamableHttp.js");
2929
+
2930
+ // src/task_managers/sse.ts
2931
+ var import_sse = require("@mcp-use/modelcontextprotocol-sdk/client/sse.js");
2932
+
2933
+ // src/task_managers/base.ts
2934
+ var ConnectionManager = class {
2935
+ static {
2936
+ __name(this, "ConnectionManager");
2937
+ }
2938
+ _readyPromise;
2939
+ _readyResolver;
2940
+ _donePromise;
2941
+ _doneResolver;
2942
+ _exception = null;
2943
+ _connection = null;
2944
+ _task = null;
2945
+ _abortController = null;
2946
+ constructor() {
2947
+ this.reset();
2948
+ }
2949
+ /**
2950
+ * Start the connection manager and establish a connection.
2951
+ *
2952
+ * @returns The established connection.
2953
+ * @throws If the connection cannot be established.
2954
+ */
2955
+ async start() {
2956
+ this.reset();
2957
+ logger.debug(`Starting ${this.constructor.name}`);
2958
+ this._task = this.connectionTask();
2959
+ await this._readyPromise;
2960
+ if (this._exception) {
2961
+ throw this._exception;
2962
+ }
2963
+ if (this._connection === null) {
2964
+ throw new Error("Connection was not established");
2965
+ }
2966
+ return this._connection;
2967
+ }
2968
+ /**
2969
+ * Stop the connection manager and close the connection.
2970
+ */
2971
+ async stop() {
2972
+ if (this._task && this._abortController) {
2973
+ logger.debug(`Cancelling ${this.constructor.name} task`);
2974
+ this._abortController.abort();
2975
+ try {
2976
+ await this._task;
2977
+ } catch (e) {
2978
+ if (e instanceof Error && e.name === "AbortError") {
2979
+ logger.debug(`${this.constructor.name} task aborted successfully`);
2980
+ } else {
2981
+ logger.warn(`Error stopping ${this.constructor.name} task: ${e}`);
2982
+ }
2983
+ }
2984
+ }
2985
+ await this._donePromise;
2986
+ logger.debug(`${this.constructor.name} task completed`);
2987
+ }
2988
+ /**
2989
+ * Reset all internal state.
2990
+ */
2991
+ reset() {
2992
+ this._readyPromise = new Promise((res) => this._readyResolver = res);
2993
+ this._donePromise = new Promise((res) => this._doneResolver = res);
2994
+ this._exception = null;
2995
+ this._connection = null;
2996
+ this._task = null;
2997
+ this._abortController = new AbortController();
2998
+ }
2999
+ /**
3000
+ * The background task responsible for establishing and maintaining the
3001
+ * connection until it is cancelled.
3002
+ */
3003
+ async connectionTask() {
3004
+ logger.debug(`Running ${this.constructor.name} task`);
3005
+ try {
3006
+ this._connection = await this.establishConnection();
3007
+ logger.debug(`${this.constructor.name} connected successfully`);
3008
+ this._readyResolver();
3009
+ await this.waitForAbort();
3010
+ } catch (err) {
3011
+ this._exception = err;
3012
+ logger.error(`Error in ${this.constructor.name} task: ${err}`);
3013
+ this._readyResolver();
3014
+ } finally {
3015
+ if (this._connection !== null) {
3016
+ try {
3017
+ await this.closeConnection(this._connection);
3018
+ } catch (closeErr) {
3019
+ logger.warn(
3020
+ `Error closing connection in ${this.constructor.name}: ${closeErr}`
3021
+ );
3022
+ }
3023
+ this._connection = null;
3024
+ }
3025
+ this._doneResolver();
3026
+ }
3027
+ }
3028
+ /**
3029
+ * Helper that returns a promise which resolves when the abort signal fires.
3030
+ */
3031
+ async waitForAbort() {
3032
+ return new Promise((_resolve, _reject) => {
3033
+ if (!this._abortController) {
3034
+ return;
3035
+ }
3036
+ const signal = this._abortController.signal;
3037
+ if (signal.aborted) {
3038
+ _resolve();
3039
+ return;
3040
+ }
3041
+ const onAbort = /* @__PURE__ */ __name(() => {
3042
+ signal.removeEventListener("abort", onAbort);
3043
+ _resolve();
3044
+ }, "onAbort");
3045
+ signal.addEventListener("abort", onAbort);
3046
+ });
3047
+ }
3048
+ };
3049
+
3050
+ // src/task_managers/sse.ts
3051
+ var SseConnectionManager = class extends ConnectionManager {
3052
+ static {
3053
+ __name(this, "SseConnectionManager");
3054
+ }
3055
+ url;
3056
+ opts;
3057
+ _transport = null;
3058
+ reinitializing = false;
3059
+ /**
3060
+ * Create an SSE connection manager.
3061
+ *
3062
+ * @param url The SSE endpoint URL.
3063
+ * @param opts Optional transport options (auth, headers, etc.).
3064
+ */
3065
+ constructor(url, opts) {
3066
+ super();
3067
+ this.url = typeof url === "string" ? new URL(url) : url;
3068
+ this.opts = opts;
3069
+ }
3070
+ /**
3071
+ * Spawn a new `SSEClientTransport` and wrap it with 404 handling.
3072
+ * Per MCP spec, clients MUST re-initialize when receiving 404 for stale sessions.
3073
+ */
3074
+ async establishConnection() {
3075
+ const transport = new import_sse.SSEClientTransport(this.url, this.opts);
3076
+ const originalSend = transport.send.bind(transport);
3077
+ transport.send = async (message) => {
3078
+ const sendMessage = /* @__PURE__ */ __name(async (msg) => {
3079
+ if (Array.isArray(msg)) {
3080
+ for (const singleMsg of msg) {
3081
+ await originalSend(singleMsg);
3082
+ }
3083
+ } else {
3084
+ await originalSend(msg);
3085
+ }
3086
+ }, "sendMessage");
3087
+ try {
3088
+ await sendMessage(message);
3089
+ } catch (error) {
3090
+ if (error?.code === 404 && transport.sessionId && !this.reinitializing) {
3091
+ logger.warn(
3092
+ `[SSE] Session not found (404), re-initializing per MCP spec...`
3093
+ );
3094
+ this.reinitializing = true;
3095
+ try {
3096
+ transport.sessionId = void 0;
3097
+ await this.reinitialize(transport);
3098
+ logger.info(`[SSE] Re-initialization successful, retrying request`);
3099
+ await sendMessage(message);
3100
+ } finally {
3101
+ this.reinitializing = false;
3102
+ }
3103
+ } else {
3104
+ throw error;
3105
+ }
3106
+ }
3107
+ };
3108
+ this._transport = transport;
3109
+ logger.debug(`${this.constructor.name} connected successfully`);
3110
+ return transport;
3111
+ }
3112
+ /**
3113
+ * Re-initialize the transport with a new session
3114
+ * This is called when the server returns 404 for a stale session
3115
+ */
3116
+ async reinitialize(transport) {
3117
+ logger.debug(`[SSE] Re-initialization triggered`);
3118
+ }
3119
+ /**
3120
+ * Close the underlying transport and clean up resources.
3121
+ */
3122
+ async closeConnection(_connection) {
3123
+ if (this._transport) {
3124
+ try {
3125
+ await this._transport.close();
3126
+ } catch (e) {
3127
+ logger.warn(`Error closing SSE transport: ${e}`);
3128
+ } finally {
3129
+ this._transport = null;
3130
+ }
3131
+ }
3132
+ }
3133
+ };
3134
+
3135
+ // src/connectors/http.ts
3136
+ var HttpConnector = class extends BaseConnector {
3137
+ static {
3138
+ __name(this, "HttpConnector");
3139
+ }
3140
+ baseUrl;
3141
+ headers;
3142
+ timeout;
3143
+ sseReadTimeout;
3144
+ clientInfo;
3145
+ preferSse;
3146
+ transportType = null;
3147
+ streamableTransport = null;
3148
+ constructor(baseUrl, opts = {}) {
3149
+ super(opts);
3150
+ this.baseUrl = baseUrl.replace(/\/$/, "");
3151
+ this.headers = { ...opts.headers ?? {} };
3152
+ if (opts.authToken) {
3153
+ this.headers.Authorization = `Bearer ${opts.authToken}`;
3154
+ }
3155
+ this.timeout = opts.timeout ?? 3e4;
3156
+ this.sseReadTimeout = opts.sseReadTimeout ?? 3e5;
3157
+ this.clientInfo = opts.clientInfo ?? {
3158
+ name: "http-connector",
3159
+ version: "1.0.0"
3160
+ };
3161
+ this.preferSse = opts.preferSse ?? false;
3162
+ }
3163
+ /** Establish connection to the MCP implementation via HTTP (streamable or SSE). */
3164
+ async connect() {
3165
+ if (this.connected) {
3166
+ logger.debug("Already connected to MCP implementation");
3167
+ return;
3168
+ }
3169
+ const baseUrl = this.baseUrl;
3170
+ if (this.preferSse) {
3171
+ logger.debug(`Connecting to MCP implementation via HTTP/SSE: ${baseUrl}`);
3172
+ await this.connectWithSse(baseUrl);
3173
+ return;
3174
+ }
3175
+ logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
3176
+ try {
3177
+ logger.info("\u{1F504} Attempting streamable HTTP transport...");
3178
+ await this.connectWithStreamableHttp(baseUrl);
3179
+ logger.info("\u2705 Successfully connected via streamable HTTP");
3180
+ } catch (err) {
3181
+ let fallbackReason = "Unknown error";
3182
+ let is401Error = false;
3183
+ if (err instanceof import_streamableHttp.StreamableHTTPError) {
3184
+ const streamableErr = err;
3185
+ is401Error = streamableErr.code === 401;
3186
+ if (streamableErr.code === 400 && streamableErr.message.includes("Missing session ID")) {
3187
+ fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
3188
+ logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
3189
+ } else if (streamableErr.code === 404 || streamableErr.code === 405) {
3190
+ fallbackReason = `Server returned ${streamableErr.code} - server likely doesn't support streamable HTTP`;
3191
+ logger.debug(fallbackReason);
3192
+ } else {
3193
+ fallbackReason = `Server returned ${streamableErr.code}: ${streamableErr.message}`;
3194
+ logger.debug(fallbackReason);
3195
+ }
3196
+ } else if (err instanceof Error) {
3197
+ const errorStr = err.toString();
3198
+ const errorMsg = err.message || "";
3199
+ is401Error = errorStr.includes("401") || errorMsg.includes("Unauthorized");
3200
+ if (errorStr.includes("Missing session ID") || errorStr.includes("Bad Request: Missing session ID") || errorMsg.includes("FastMCP session ID error")) {
3201
+ fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
3202
+ logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
3203
+ } else if (errorStr.includes("405 Method Not Allowed") || errorStr.includes("404 Not Found")) {
3204
+ fallbackReason = "Server doesn't support streamable HTTP (405/404)";
3205
+ logger.debug(fallbackReason);
3206
+ } else {
3207
+ fallbackReason = `Streamable HTTP failed: ${err.message}`;
3208
+ logger.debug(fallbackReason);
3209
+ }
3210
+ }
3211
+ if (is401Error) {
3212
+ logger.info("Authentication required - skipping SSE fallback");
3213
+ await this.cleanupResources();
3214
+ const authError = new Error("Authentication required");
3215
+ authError.code = 401;
3216
+ throw authError;
3217
+ }
3218
+ logger.info("\u{1F504} Falling back to SSE transport...");
3219
+ try {
3220
+ await this.connectWithSse(baseUrl);
3221
+ } catch (sseErr) {
3222
+ logger.error(`Failed to connect with both transports:`);
3223
+ logger.error(` Streamable HTTP: ${fallbackReason}`);
3224
+ logger.error(` SSE: ${sseErr}`);
3225
+ await this.cleanupResources();
3226
+ const sseIs401 = sseErr?.message?.includes("401") || sseErr?.message?.includes("Unauthorized");
3227
+ if (sseIs401) {
3228
+ const authError = new Error("Authentication required");
3229
+ authError.code = 401;
3230
+ throw authError;
3231
+ }
3232
+ throw new Error(
3233
+ "Could not connect to server with any available transport"
3234
+ );
3235
+ }
3236
+ }
3237
+ }
3238
+ async connectWithStreamableHttp(baseUrl) {
3239
+ try {
3240
+ const streamableTransport = new import_streamableHttp.StreamableHTTPClientTransport(
3241
+ new URL(baseUrl),
3242
+ {
3243
+ authProvider: this.opts.authProvider,
3244
+ // ← Pass OAuth provider to SDK
3245
+ requestInit: {
3246
+ headers: this.headers
3247
+ },
3248
+ // Pass through reconnection options
3249
+ reconnectionOptions: {
3250
+ maxReconnectionDelay: 3e4,
3251
+ initialReconnectionDelay: 1e3,
3252
+ reconnectionDelayGrowFactor: 1.5,
3253
+ maxRetries: 2
3254
+ }
3255
+ // Don't pass sessionId - let the SDK generate it automatically during connect()
3256
+ }
3257
+ );
3258
+ let transport = streamableTransport;
3259
+ if (this.opts.wrapTransport) {
3260
+ const serverId = this.baseUrl;
3261
+ transport = this.opts.wrapTransport(
3262
+ transport,
3263
+ serverId
3264
+ );
3265
+ }
3266
+ const clientOptions = {
3267
+ ...this.opts.clientOptions || {},
3268
+ capabilities: {
3269
+ ...this.opts.clientOptions?.capabilities || {},
3270
+ roots: { listChanged: true },
3271
+ // Always advertise roots capability
3272
+ // Add sampling capability if callback is provided
3273
+ ...this.opts.samplingCallback ? { sampling: {} } : {},
3274
+ // Add elicitation capability if callback is provided
3275
+ ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
3276
+ }
3277
+ };
3278
+ logger.debug(
3279
+ `Creating Client with capabilities:`,
3280
+ JSON.stringify(clientOptions.capabilities, null, 2)
3281
+ );
3282
+ this.client = new import_client.Client(this.clientInfo, clientOptions);
3283
+ this.setupRootsHandler();
3284
+ logger.debug("Roots handler registered before connect");
3285
+ try {
3286
+ await this.client.connect(transport, {
3287
+ timeout: Math.min(this.timeout, 3e3)
3288
+ });
3289
+ const sessionId = streamableTransport.sessionId;
3290
+ if (sessionId) {
3291
+ logger.debug(`Session ID obtained: ${sessionId}`);
3292
+ } else {
3293
+ logger.warn(
3294
+ "Session ID not available after connect - this may cause issues with SSE stream"
3295
+ );
3296
+ }
3297
+ } catch (connectErr) {
3298
+ if (connectErr instanceof Error) {
3299
+ const errMsg = connectErr.message || connectErr.toString();
3300
+ if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID") || errMsg.includes("Mcp-Session-Id header is required")) {
3301
+ const wrappedError = new Error(
3302
+ `Session ID error: ${errMsg}. The SDK should automatically extract session ID from initialize response.`
3303
+ );
3304
+ wrappedError.cause = connectErr;
3305
+ throw wrappedError;
3306
+ }
3307
+ }
3308
+ throw connectErr;
3309
+ }
3310
+ this.streamableTransport = streamableTransport;
3311
+ this.connectionManager = {
3312
+ stop: /* @__PURE__ */ __name(async () => {
3313
+ if (this.streamableTransport) {
3314
+ try {
3315
+ await this.streamableTransport.terminateSession();
3316
+ await this.streamableTransport.close();
3317
+ } catch (e) {
3318
+ logger.warn(`Error closing Streamable HTTP transport: ${e}`);
3319
+ } finally {
3320
+ this.streamableTransport = null;
3321
+ }
3322
+ }
3323
+ }, "stop")
3324
+ };
3325
+ this.connected = true;
3326
+ this.transportType = "streamable-http";
3327
+ this.setupNotificationHandler();
3328
+ this.setupSamplingHandler();
3329
+ this.setupElicitationHandler();
3330
+ logger.debug(
3331
+ `Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
3332
+ );
3333
+ this.trackConnectorInit({
3334
+ serverUrl: this.baseUrl,
3335
+ publicIdentifier: `${this.baseUrl} (streamable-http)`
3336
+ });
3337
+ } catch (err) {
3338
+ await this.cleanupResources();
3339
+ throw err;
3340
+ }
3341
+ }
3342
+ async connectWithSse(baseUrl) {
3343
+ try {
3344
+ this.connectionManager = new SseConnectionManager(baseUrl, {
3345
+ authProvider: this.opts.authProvider,
3346
+ // ← Pass OAuth provider to SDK (same as streamable HTTP)
3347
+ requestInit: {
3348
+ headers: this.headers
3349
+ }
3350
+ });
3351
+ let transport = await this.connectionManager.start();
3352
+ if (this.opts.wrapTransport) {
3353
+ const serverId = this.baseUrl;
3354
+ transport = this.opts.wrapTransport(transport, serverId);
3355
+ }
3356
+ const clientOptions = {
3357
+ ...this.opts.clientOptions || {},
3358
+ capabilities: {
3359
+ ...this.opts.clientOptions?.capabilities || {},
3360
+ roots: { listChanged: true },
3361
+ // Always advertise roots capability
3362
+ // Add sampling capability if callback is provided
3363
+ ...this.opts.samplingCallback ? { sampling: {} } : {},
3364
+ // Add elicitation capability if callback is provided
3365
+ ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
3366
+ }
3367
+ };
3368
+ logger.debug(
3369
+ `Creating Client with capabilities (SSE):`,
3370
+ JSON.stringify(clientOptions.capabilities, null, 2)
3371
+ );
3372
+ this.client = new import_client.Client(this.clientInfo, clientOptions);
3373
+ this.setupRootsHandler();
3374
+ logger.debug("Roots handler registered before connect (SSE)");
3375
+ await this.client.connect(transport);
3376
+ this.connected = true;
3377
+ this.transportType = "sse";
3378
+ this.setupNotificationHandler();
3379
+ this.setupSamplingHandler();
3380
+ this.setupElicitationHandler();
3381
+ logger.debug(
3382
+ `Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
3383
+ );
3384
+ this.trackConnectorInit({
3385
+ serverUrl: this.baseUrl,
3386
+ publicIdentifier: `${this.baseUrl} (sse)`
3387
+ });
3388
+ } catch (err) {
3389
+ await this.cleanupResources();
3390
+ throw err;
3391
+ }
3392
+ }
3393
+ get publicIdentifier() {
3394
+ return {
3395
+ type: "http",
3396
+ url: this.baseUrl,
3397
+ transport: this.transportType || "unknown"
3398
+ };
3399
+ }
3400
+ /**
3401
+ * Get the transport type being used (streamable-http or sse)
3402
+ */
3403
+ getTransportType() {
3404
+ return this.transportType;
3405
+ }
3406
+ };
3407
+
3408
+ // src/connectors/stdio.ts
3409
+ var import_node_process = __toESM(require("process"), 1);
3410
+ var import_client2 = require("@mcp-use/modelcontextprotocol-sdk/client/index.js");
3411
+
3412
+ // src/task_managers/stdio.ts
3413
+ var import_stdio = require("@mcp-use/modelcontextprotocol-sdk/client/stdio.js");
3414
+ var StdioConnectionManager = class extends ConnectionManager {
3415
+ static {
3416
+ __name(this, "StdioConnectionManager");
3417
+ }
3418
+ serverParams;
3419
+ errlog;
3420
+ _transport = null;
3421
+ /**
3422
+ * Create a new stdio connection manager.
3423
+ *
3424
+ * @param serverParams Parameters for the stdio server process.
3425
+ * @param errlog Stream to which the server's stderr should be piped.
3426
+ * Defaults to `process.stderr`.
3427
+ */
3428
+ constructor(serverParams, errlog = process.stderr) {
3429
+ super();
3430
+ this.serverParams = serverParams;
3431
+ this.errlog = errlog;
3432
+ }
3433
+ /**
3434
+ * Establish the stdio connection by spawning the server process and starting
3435
+ * the SDK's transport. Returns the live `StdioClientTransport` instance.
3436
+ */
3437
+ async establishConnection() {
3438
+ this._transport = new import_stdio.StdioClientTransport(this.serverParams);
3439
+ if (this._transport.stderr && typeof this._transport.stderr.pipe === "function") {
3440
+ this._transport.stderr.pipe(
3441
+ this.errlog
3442
+ );
3443
+ }
3444
+ logger.debug(`${this.constructor.name} connected successfully`);
3445
+ return this._transport;
3446
+ }
3447
+ /**
3448
+ * Close the stdio connection, making sure the transport cleans up the child
3449
+ * process and associated resources.
3450
+ */
3451
+ async closeConnection(_connection) {
3452
+ if (this._transport) {
3453
+ try {
3454
+ await this._transport.close();
3455
+ } catch (e) {
3456
+ logger.warn(`Error closing stdio transport: ${e}`);
3457
+ } finally {
3458
+ this._transport = null;
3459
+ }
3460
+ }
3461
+ }
3462
+ };
3463
+
3464
+ // src/connectors/stdio.ts
3465
+ var StdioConnector = class extends BaseConnector {
3466
+ static {
3467
+ __name(this, "StdioConnector");
3468
+ }
3469
+ command;
3470
+ args;
3471
+ env;
3472
+ errlog;
3473
+ clientInfo;
3474
+ constructor({
3475
+ command = "npx",
3476
+ args = [],
3477
+ env,
3478
+ errlog = import_node_process.default.stderr,
3479
+ ...rest
3480
+ } = {}) {
3481
+ super(rest);
3482
+ this.command = command;
3483
+ this.args = args;
3484
+ this.env = env;
3485
+ this.errlog = errlog;
3486
+ this.clientInfo = rest.clientInfo ?? {
3487
+ name: "stdio-connector",
3488
+ version: "1.0.0"
3489
+ };
3490
+ }
3491
+ /** Establish connection to the MCP implementation. */
3492
+ async connect() {
3493
+ if (this.connected) {
3494
+ logger.debug("Already connected to MCP implementation");
3495
+ return;
3496
+ }
3497
+ logger.debug(`Connecting to MCP implementation via stdio: ${this.command}`);
3498
+ try {
3499
+ let mergedEnv;
3500
+ if (this.env) {
3501
+ mergedEnv = {};
3502
+ for (const [key, value] of Object.entries(import_node_process.default.env)) {
3503
+ if (value !== void 0) {
3504
+ mergedEnv[key] = value;
3505
+ }
3506
+ }
3507
+ Object.assign(mergedEnv, this.env);
3508
+ }
3509
+ const serverParams = {
3510
+ command: this.command,
3511
+ args: this.args,
3512
+ env: mergedEnv
3513
+ };
3514
+ this.connectionManager = new StdioConnectionManager(
3515
+ serverParams,
3516
+ this.errlog
3517
+ );
3518
+ const transport = await this.connectionManager.start();
3519
+ const clientOptions = {
3520
+ ...this.opts.clientOptions || {},
3521
+ capabilities: {
3522
+ ...this.opts.clientOptions?.capabilities || {},
3523
+ roots: { listChanged: true },
3524
+ // Always advertise roots capability
3525
+ // Add sampling capability if callback is provided
3526
+ ...this.opts.samplingCallback ? { sampling: {} } : {},
3527
+ // Add elicitation capability if callback is provided
3528
+ ...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
3529
+ }
3530
+ };
3531
+ this.client = new import_client2.Client(this.clientInfo, clientOptions);
3532
+ await this.client.connect(transport);
3533
+ this.connected = true;
3534
+ this.setupNotificationHandler();
3535
+ this.setupRootsHandler();
3536
+ this.setupSamplingHandler();
3537
+ this.setupElicitationHandler();
3538
+ logger.debug(
3539
+ `Successfully connected to MCP implementation: ${this.command}`
3540
+ );
3541
+ this.trackConnectorInit({
3542
+ serverCommand: this.command,
3543
+ serverArgs: this.args,
3544
+ publicIdentifier: `${this.command} ${this.args.join(" ")}`
3545
+ });
3546
+ } catch (err) {
3547
+ logger.error(`Failed to connect to MCP implementation: ${err}`);
3548
+ await this.cleanupResources();
3549
+ throw err;
3550
+ }
3551
+ }
3552
+ get publicIdentifier() {
3553
+ return {
3554
+ type: "stdio",
3555
+ "command&args": `${this.command} ${this.args.join(" ")}`
3556
+ };
3557
+ }
3558
+ };
3559
+
3560
+ // src/config.ts
3561
+ function loadConfigFile(filepath) {
3562
+ const raw = (0, import_node_fs.readFileSync)(filepath, "utf-8");
3563
+ return JSON.parse(raw);
3564
+ }
3565
+ __name(loadConfigFile, "loadConfigFile");
3566
+ function createConnectorFromConfig(serverConfig, connectorOptions) {
3567
+ if ("command" in serverConfig && "args" in serverConfig) {
3568
+ return new StdioConnector({
3569
+ command: serverConfig.command,
3570
+ args: serverConfig.args,
3571
+ env: serverConfig.env,
3572
+ ...connectorOptions
3573
+ });
3574
+ }
3575
+ if ("url" in serverConfig) {
3576
+ const transport = serverConfig.transport || "http";
3577
+ return new HttpConnector(serverConfig.url, {
3578
+ headers: serverConfig.headers,
3579
+ authToken: serverConfig.auth_token || serverConfig.authToken,
3580
+ // Only force SSE if explicitly requested
3581
+ preferSse: serverConfig.preferSse || transport === "sse",
3582
+ ...connectorOptions
3583
+ });
3584
+ }
3585
+ throw new Error("Cannot determine connector type from config");
3586
+ }
3587
+ __name(createConnectorFromConfig, "createConnectorFromConfig");
3588
+
3589
+ // src/client.ts
3590
+ var MCPClient = class _MCPClient extends BaseMCPClient {
3591
+ static {
3592
+ __name(this, "MCPClient");
3593
+ }
3594
+ /**
3595
+ * Get the mcp-use package version.
3596
+ * Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
3597
+ */
3598
+ static getPackageVersion() {
3599
+ return getPackageVersion();
3600
+ }
3601
+ codeMode = false;
3602
+ _codeExecutor = null;
3603
+ _customCodeExecutor = null;
3604
+ _codeExecutorConfig = "vm";
3605
+ _executorOptions;
3606
+ _samplingCallback;
3607
+ _elicitationCallback;
3608
+ constructor(config, options) {
3609
+ if (config) {
3610
+ if (typeof config === "string") {
3611
+ super(loadConfigFile(config));
3612
+ } else {
3613
+ super(config);
3614
+ }
3615
+ } else {
3616
+ super();
3617
+ }
3618
+ let codeModeEnabled = false;
3619
+ let executorConfig = "vm";
3620
+ let executorOptions;
3621
+ if (options?.codeMode) {
3622
+ if (typeof options.codeMode === "boolean") {
3623
+ codeModeEnabled = options.codeMode;
3624
+ } else {
3625
+ codeModeEnabled = options.codeMode.enabled;
3626
+ executorConfig = options.codeMode.executor ?? "vm";
3627
+ executorOptions = options.codeMode.executorOptions;
3628
+ }
3629
+ }
3630
+ this.codeMode = codeModeEnabled;
3631
+ this._codeExecutorConfig = executorConfig;
3632
+ this._executorOptions = executorOptions;
3633
+ this._samplingCallback = options?.samplingCallback;
3634
+ this._elicitationCallback = options?.elicitationCallback;
3635
+ if (this.codeMode) {
3636
+ this._setupCodeModeConnector();
3637
+ }
3638
+ this._trackClientInit();
3639
+ }
3640
+ _trackClientInit() {
3641
+ const servers = Object.keys(this.config.mcpServers ?? {});
3642
+ const hasSamplingCallback = !!this._samplingCallback;
3643
+ const hasElicitationCallback = !!this._elicitationCallback;
3644
+ Tel.getInstance().trackMCPClientInit({
3645
+ codeMode: this.codeMode,
3646
+ sandbox: false,
3647
+ // Sandbox not supported in TS yet
3648
+ allCallbacks: hasSamplingCallback && hasElicitationCallback,
3649
+ verify: false,
3650
+ // No verify option in TS client
3651
+ servers,
3652
+ numServers: servers.length,
3653
+ isBrowser: false
3654
+ // Node.js MCPClient
3655
+ }).catch((e) => logger.debug(`Failed to track MCPClient init: ${e}`));
3656
+ }
3657
+ static fromDict(cfg, options) {
3658
+ return new _MCPClient(cfg, options);
3659
+ }
3660
+ static fromConfigFile(path2, options) {
3661
+ return new _MCPClient(loadConfigFile(path2), options);
3662
+ }
3663
+ /**
3664
+ * Save configuration to a file (Node.js only)
3665
+ */
3666
+ saveConfig(filepath) {
3667
+ const dir = import_node_path.default.dirname(filepath);
3668
+ if (!import_node_fs2.default.existsSync(dir)) {
3669
+ import_node_fs2.default.mkdirSync(dir, { recursive: true });
3670
+ }
3671
+ import_node_fs2.default.writeFileSync(filepath, JSON.stringify(this.config, null, 2), "utf-8");
3672
+ }
3673
+ /**
3674
+ * Create a connector from server configuration (Node.js version)
3675
+ * Supports all connector types including StdioConnector
3676
+ */
3677
+ createConnectorFromConfig(serverConfig) {
3678
+ return createConnectorFromConfig(serverConfig, {
3679
+ samplingCallback: this._samplingCallback,
3680
+ elicitationCallback: this._elicitationCallback
3681
+ });
3682
+ }
3683
+ _setupCodeModeConnector() {
3684
+ logger.debug("Code mode connector initialized as internal meta server");
3685
+ const connector = new CodeModeConnector(this);
3686
+ const session = new MCPSession(connector);
3687
+ this.sessions["code_mode"] = session;
3688
+ this.activeSessions.push("code_mode");
3689
+ }
3690
+ _ensureCodeExecutor() {
3691
+ if (!this._codeExecutor) {
3692
+ const config = this._codeExecutorConfig;
3693
+ if (config instanceof BaseCodeExecutor) {
3694
+ this._codeExecutor = config;
3695
+ } else if (typeof config === "function") {
3696
+ this._customCodeExecutor = config;
3697
+ throw new Error(
3698
+ "Custom executor function should be handled in executeCode"
3699
+ );
3700
+ } else if (config === "e2b") {
3701
+ const opts = this._executorOptions;
3702
+ if (!opts?.apiKey) {
3703
+ logger.warn("E2B executor requires apiKey. Falling back to VM.");
3704
+ try {
3705
+ this._codeExecutor = new VMCodeExecutor(
3706
+ this,
3707
+ this._executorOptions
3708
+ );
3709
+ } catch (error) {
3710
+ throw new Error(
3711
+ "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."
3712
+ );
3713
+ }
3714
+ } else {
3715
+ this._codeExecutor = new E2BCodeExecutor(this, opts);
3716
+ }
3717
+ } else {
3718
+ try {
3719
+ this._codeExecutor = new VMCodeExecutor(
3720
+ this,
3721
+ this._executorOptions
3722
+ );
3723
+ } catch (error) {
3724
+ const e2bOpts = this._executorOptions;
3725
+ const e2bApiKey = e2bOpts?.apiKey || process.env.E2B_API_KEY;
3726
+ if (e2bApiKey) {
3727
+ logger.info(
3728
+ "VM executor not available in this environment. Falling back to E2B."
3729
+ );
3730
+ this._codeExecutor = new E2BCodeExecutor(this, {
3731
+ ...e2bOpts,
3732
+ apiKey: e2bApiKey
3733
+ });
3734
+ } else {
3735
+ throw new Error(
3736
+ "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."
3737
+ );
3738
+ }
3739
+ }
3740
+ }
3741
+ }
3742
+ return this._codeExecutor;
3743
+ }
3744
+ /**
3745
+ * Execute code in code mode
3746
+ */
3747
+ async executeCode(code, timeout) {
3748
+ if (!this.codeMode) {
3749
+ throw new Error("Code execution mode is not enabled");
3750
+ }
3751
+ if (this._customCodeExecutor) {
3752
+ return this._customCodeExecutor(code, timeout);
3753
+ }
3754
+ return this._ensureCodeExecutor().execute(code, timeout);
3755
+ }
3756
+ /**
3757
+ * Search available tools (used by code mode)
3758
+ */
3759
+ async searchTools(query = "", detailLevel = "full") {
3760
+ if (!this.codeMode) {
3761
+ throw new Error("Code execution mode is not enabled");
3762
+ }
3763
+ return this._ensureCodeExecutor().createSearchToolsFunction()(
3764
+ query,
3765
+ detailLevel
3766
+ );
3767
+ }
3768
+ /**
3769
+ * Override getServerNames to exclude internal code_mode server
3770
+ */
3771
+ getServerNames() {
3772
+ const isCodeModeEnabled = this.codeMode;
3773
+ return super.getServerNames().filter((name) => {
3774
+ return !isCodeModeEnabled || name !== "code_mode";
3775
+ });
3776
+ }
3777
+ /**
3778
+ * Close the client and clean up resources including code executors.
3779
+ * This ensures E2B sandboxes and other resources are properly released.
3780
+ */
3781
+ async close() {
3782
+ if (this._codeExecutor) {
3783
+ await this._codeExecutor.cleanup();
3784
+ this._codeExecutor = null;
3785
+ }
3786
+ await this.closeAllSessions();
3787
+ }
3788
+ };