mcp-use 0.1.20 → 0.3.0

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/dist/chunk-2HFIPY7C.js +429 -0
  2. package/dist/chunk-4DEFXVWT.js +680 -0
  3. package/dist/chunk-JXLQRAW2.js +532 -0
  4. package/dist/chunk-SHUYVCID.js +6 -0
  5. package/dist/chunk-YUSC6R6V.js +299 -0
  6. package/dist/index.cjs +5762 -0
  7. package/dist/index.d.ts +7 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3767 -22
  10. package/dist/langfuse-YA2S23SM.js +13 -0
  11. package/dist/src/agents/remote.d.ts.map +1 -1
  12. package/dist/src/agents/utils/ai_sdk.d.ts.map +1 -1
  13. package/dist/src/auth/browser-provider.d.ts +52 -0
  14. package/dist/src/auth/browser-provider.d.ts.map +1 -0
  15. package/dist/src/auth/callback.d.ts +6 -0
  16. package/dist/src/auth/callback.d.ts.map +1 -0
  17. package/dist/src/auth/index.d.ts +7 -0
  18. package/dist/src/auth/index.d.ts.map +1 -0
  19. package/dist/src/auth/types.d.ts +18 -0
  20. package/dist/src/auth/types.d.ts.map +1 -0
  21. package/dist/src/browser.cjs +323 -0
  22. package/dist/src/browser.d.ts +8 -0
  23. package/dist/src/browser.d.ts.map +1 -0
  24. package/dist/src/browser.js +9 -0
  25. package/dist/src/client/base.d.ts +32 -0
  26. package/dist/src/client/base.d.ts.map +1 -0
  27. package/dist/src/client.d.ts +19 -16
  28. package/dist/src/client.d.ts.map +1 -1
  29. package/dist/src/logging.d.ts +1 -1
  30. package/dist/src/logging.d.ts.map +1 -1
  31. package/dist/src/oauth-helper.d.ts +125 -0
  32. package/dist/src/oauth-helper.d.ts.map +1 -0
  33. package/dist/src/react/index.cjs +986 -0
  34. package/dist/src/react/index.d.ts +9 -0
  35. package/dist/src/react/index.d.ts.map +1 -0
  36. package/dist/src/react/index.js +11 -0
  37. package/dist/src/react/types.d.ts +139 -0
  38. package/dist/src/react/types.d.ts.map +1 -0
  39. package/dist/src/react/useMcp.d.ts +3 -0
  40. package/dist/src/react/useMcp.d.ts.map +1 -0
  41. package/dist/src/server/index.cjs +566 -0
  42. package/dist/src/server/index.d.ts +3 -0
  43. package/dist/src/server/index.d.ts.map +1 -0
  44. package/dist/src/server/index.js +9 -0
  45. package/dist/src/server/logging.d.ts +16 -0
  46. package/dist/src/server/logging.d.ts.map +1 -0
  47. package/dist/src/server/mcp-server.d.ts +282 -0
  48. package/dist/src/server/mcp-server.d.ts.map +1 -0
  49. package/dist/src/server/types.d.ts +47 -0
  50. package/dist/src/server/types.d.ts.map +1 -0
  51. package/dist/src/utils/assert.d.ts +8 -0
  52. package/dist/src/utils/assert.d.ts.map +1 -0
  53. package/dist/tsconfig.tsbuildinfo +1 -0
  54. package/package.json +72 -40
  55. package/dist/examples/add_server_tool.d.ts +0 -8
  56. package/dist/examples/add_server_tool.d.ts.map +0 -1
  57. package/dist/examples/add_server_tool.js +0 -79
  58. package/dist/examples/ai_sdk_example.d.ts +0 -23
  59. package/dist/examples/ai_sdk_example.d.ts.map +0 -1
  60. package/dist/examples/ai_sdk_example.js +0 -213
  61. package/dist/examples/airbnb_use.d.ts +0 -10
  62. package/dist/examples/airbnb_use.d.ts.map +0 -1
  63. package/dist/examples/airbnb_use.js +0 -43
  64. package/dist/examples/blender_use.d.ts +0 -15
  65. package/dist/examples/blender_use.d.ts.map +0 -1
  66. package/dist/examples/blender_use.js +0 -39
  67. package/dist/examples/browser_use.d.ts +0 -10
  68. package/dist/examples/browser_use.d.ts.map +0 -1
  69. package/dist/examples/browser_use.js +0 -46
  70. package/dist/examples/chat_example.d.ts +0 -10
  71. package/dist/examples/chat_example.d.ts.map +0 -1
  72. package/dist/examples/chat_example.js +0 -86
  73. package/dist/examples/filesystem_use.d.ts +0 -11
  74. package/dist/examples/filesystem_use.d.ts.map +0 -1
  75. package/dist/examples/filesystem_use.js +0 -43
  76. package/dist/examples/http_example.d.ts +0 -18
  77. package/dist/examples/http_example.d.ts.map +0 -1
  78. package/dist/examples/http_example.js +0 -37
  79. package/dist/examples/mcp_everything.d.ts +0 -6
  80. package/dist/examples/mcp_everything.d.ts.map +0 -1
  81. package/dist/examples/mcp_everything.js +0 -25
  82. package/dist/examples/multi_server_example.d.ts +0 -10
  83. package/dist/examples/multi_server_example.d.ts.map +0 -1
  84. package/dist/examples/multi_server_example.js +0 -51
  85. package/dist/examples/observability.d.ts +0 -6
  86. package/dist/examples/observability.d.ts.map +0 -1
  87. package/dist/examples/observability.js +0 -50
  88. package/dist/examples/stream_example.d.ts +0 -12
  89. package/dist/examples/stream_example.d.ts.map +0 -1
  90. package/dist/examples/stream_example.js +0 -198
  91. package/dist/examples/structured_output.d.ts +0 -9
  92. package/dist/examples/structured_output.d.ts.map +0 -1
  93. package/dist/examples/structured_output.js +0 -95
  94. package/dist/src/adapters/base.js +0 -124
  95. package/dist/src/adapters/index.js +0 -2
  96. package/dist/src/adapters/langchain_adapter.js +0 -49
  97. package/dist/src/agents/base.js +0 -9
  98. package/dist/src/agents/index.js +0 -3
  99. package/dist/src/agents/mcp_agent.js +0 -1002
  100. package/dist/src/agents/prompts/system_prompt_builder.js +0 -40
  101. package/dist/src/agents/prompts/templates.js +0 -39
  102. package/dist/src/agents/remote.js +0 -264
  103. package/dist/src/agents/utils/ai_sdk.js +0 -62
  104. package/dist/src/agents/utils/index.js +0 -1
  105. package/dist/src/client.js +0 -133
  106. package/dist/src/config.js +0 -34
  107. package/dist/src/connectors/base.js +0 -143
  108. package/dist/src/connectors/http.js +0 -150
  109. package/dist/src/connectors/index.js +0 -4
  110. package/dist/src/connectors/stdio.js +0 -68
  111. package/dist/src/connectors/websocket.js +0 -157
  112. package/dist/src/logging.js +0 -217
  113. package/dist/src/managers/index.js +0 -2
  114. package/dist/src/managers/server_manager.js +0 -106
  115. package/dist/src/managers/tools/acquire_active_mcp_server.js +0 -17
  116. package/dist/src/managers/tools/add_server_from_config.js +0 -40
  117. package/dist/src/managers/tools/base.js +0 -17
  118. package/dist/src/managers/tools/connect_mcp_server.js +0 -46
  119. package/dist/src/managers/tools/index.js +0 -5
  120. package/dist/src/managers/tools/list_mcp_servers.js +0 -33
  121. package/dist/src/managers/tools/release_mcp_server_connection.js +0 -19
  122. package/dist/src/observability/index.js +0 -12
  123. package/dist/src/observability/langfuse.js +0 -211
  124. package/dist/src/observability/manager.js +0 -199
  125. package/dist/src/observability/types.js +0 -4
  126. package/dist/src/session.js +0 -23
  127. package/dist/src/task_managers/base.js +0 -127
  128. package/dist/src/task_managers/index.js +0 -5
  129. package/dist/src/task_managers/sse.js +0 -43
  130. package/dist/src/task_managers/stdio.js +0 -51
  131. package/dist/src/task_managers/streamable_http.js +0 -50
  132. package/dist/src/task_managers/websocket.js +0 -67
  133. package/dist/src/telemetry/events.js +0 -44
  134. package/dist/src/telemetry/index.js +0 -8
  135. package/dist/src/telemetry/telemetry.js +0 -324
  136. package/dist/src/telemetry/utils.js +0 -39
  137. package/dist/tests/ai_sdk_compatibility.test.js +0 -214
  138. package/dist/tests/stream_events.test.js +0 -307
  139. package/dist/tests/stream_events_simple.test.js +0 -179
  140. package/dist/vitest.config.js +0 -21
package/dist/index.js CHANGED
@@ -1,22 +1,3767 @@
1
- import { MCPAgent } from './src/agents/mcp_agent.js';
2
- import { RemoteAgent } from './src/agents/remote.js';
3
- import { MCPClient } from './src/client.js';
4
- import { loadConfigFile } from './src/config.js';
5
- import { BaseConnector } from './src/connectors/base.js';
6
- import { HttpConnector } from './src/connectors/http.js';
7
- import { StdioConnector } from './src/connectors/stdio.js';
8
- import { WebSocketConnector } from './src/connectors/websocket.js';
9
- import { Logger, logger } from './src/logging.js';
10
- import { MCPSession } from './src/session.js';
11
- export { BaseAdapter, LangChainAdapter } from './src/adapters/index.js';
12
- // Export AI SDK utilities
13
- export * from './src/agents/utils/index.js';
14
- export { ServerManager } from './src/managers/server_manager.js';
15
- export * from './src/managers/tools/index.js';
16
- // Export observability utilities
17
- export { ObservabilityManager } from './src/observability/index.js';
18
- // Export telemetry utilities
19
- export { setTelemetrySource, Telemetry } from './src/telemetry/index.js';
20
- // Re-export message classes to ensure a single constructor instance is shared by consumers
21
- export { AIMessage, BaseMessage, HumanMessage, SystemMessage, ToolMessage } from '@langchain/core/messages';
22
- export { BaseConnector, HttpConnector, loadConfigFile, Logger, logger, MCPAgent, MCPClient, MCPSession, RemoteAgent, StdioConnector, WebSocketConnector };
1
+ import {
2
+ useMcp
3
+ } from "./chunk-4DEFXVWT.js";
4
+ import {
5
+ BrowserOAuthClientProvider,
6
+ onMcpAuthorization
7
+ } from "./chunk-YUSC6R6V.js";
8
+ import {
9
+ McpServer,
10
+ createMCPServer
11
+ } from "./chunk-JXLQRAW2.js";
12
+ import {
13
+ Logger,
14
+ logger
15
+ } from "./chunk-2HFIPY7C.js";
16
+ import {
17
+ __name
18
+ } from "./chunk-SHUYVCID.js";
19
+
20
+ // src/agents/mcp_agent.ts
21
+ import { CallbackManager } from "@langchain/core/callbacks/manager";
22
+ import {
23
+ AIMessage,
24
+ HumanMessage,
25
+ SystemMessage as SystemMessage2,
26
+ ToolMessage
27
+ } from "@langchain/core/messages";
28
+ import { OutputParserException } from "@langchain/core/output_parsers";
29
+ import {
30
+ ChatPromptTemplate,
31
+ MessagesPlaceholder
32
+ } from "@langchain/core/prompts";
33
+ import { AgentExecutor, createToolCallingAgent } from "langchain/agents";
34
+ import { zodToJsonSchema as zodToJsonSchema2 } from "zod-to-json-schema";
35
+
36
+ // src/adapters/langchain_adapter.ts
37
+ import { JSONSchemaToZod } from "@dmitryrechkin/json-schema-to-zod";
38
+ import { DynamicStructuredTool } from "@langchain/core/tools";
39
+ import { z } from "zod";
40
+
41
+ // src/adapters/base.ts
42
+ var BaseAdapter = class {
43
+ static {
44
+ __name(this, "BaseAdapter");
45
+ }
46
+ /**
47
+ * List of tool names that should not be available.
48
+ */
49
+ disallowedTools;
50
+ /**
51
+ * Internal cache that maps a connector instance to the list of tools
52
+ * generated for it.
53
+ */
54
+ connectorToolMap = /* @__PURE__ */ new Map();
55
+ constructor(disallowedTools) {
56
+ this.disallowedTools = disallowedTools ?? [];
57
+ }
58
+ /**
59
+ * Create tools from an MCPClient instance.
60
+ *
61
+ * This is the recommended way to create tools from an MCPClient, as it handles
62
+ * session creation and connector extraction automatically.
63
+ *
64
+ * @param client The MCPClient to extract tools from.
65
+ * @param disallowedTools Optional list of tool names to exclude.
66
+ * @returns A promise that resolves with a list of converted tools.
67
+ */
68
+ static async createTools(client, disallowedTools) {
69
+ const adapter = new this(disallowedTools);
70
+ if (!client.activeSessions || Object.keys(client.activeSessions).length === 0) {
71
+ logger.info("No active sessions found, creating new ones...");
72
+ await client.createAllSessions();
73
+ }
74
+ const sessions = client.getAllActiveSessions();
75
+ const connectors = Object.values(sessions).map(
76
+ (session) => session.connector
77
+ );
78
+ return adapter.createToolsFromConnectors(connectors);
79
+ }
80
+ /**
81
+ * Dynamically load tools for a specific connector.
82
+ *
83
+ * @param connector The connector to load tools for.
84
+ * @returns The list of tools that were loaded in the target framework's format.
85
+ */
86
+ async loadToolsForConnector(connector) {
87
+ if (this.connectorToolMap.has(connector)) {
88
+ const cached = this.connectorToolMap.get(connector);
89
+ logger.debug(`Returning ${cached.length} existing tools for connector`);
90
+ return cached;
91
+ }
92
+ const connectorTools = [];
93
+ const success = await this.ensureConnectorInitialized(connector);
94
+ if (!success) {
95
+ return [];
96
+ }
97
+ for (const tool of connector.tools) {
98
+ const converted = this.convertTool(tool, connector);
99
+ if (converted) {
100
+ connectorTools.push(converted);
101
+ }
102
+ }
103
+ this.connectorToolMap.set(connector, connectorTools);
104
+ logger.debug(
105
+ `Loaded ${connectorTools.length} new tools for connector: ${connectorTools.map((t) => t?.name ?? String(t)).join(", ")}`
106
+ );
107
+ return connectorTools;
108
+ }
109
+ /**
110
+ * Create tools from MCP tools in all provided connectors.
111
+ *
112
+ * @param connectors List of MCP connectors to create tools from.
113
+ * @returns A promise that resolves with all converted tools.
114
+ */
115
+ async createToolsFromConnectors(connectors) {
116
+ const tools = [];
117
+ for (const connector of connectors) {
118
+ const connectorTools = await this.loadToolsForConnector(connector);
119
+ tools.push(...connectorTools);
120
+ }
121
+ logger.debug(`Available tools: ${tools.length}`);
122
+ return tools;
123
+ }
124
+ /**
125
+ * Check if a connector is initialized and has tools.
126
+ *
127
+ * @param connector The connector to check.
128
+ * @returns True if the connector is initialized and has tools, false otherwise.
129
+ */
130
+ checkConnectorInitialized(connector) {
131
+ return Boolean(connector.tools && connector.tools.length);
132
+ }
133
+ /**
134
+ * Ensure a connector is initialized.
135
+ *
136
+ * @param connector The connector to initialize.
137
+ * @returns True if initialization succeeded, false otherwise.
138
+ */
139
+ async ensureConnectorInitialized(connector) {
140
+ if (!this.checkConnectorInitialized(connector)) {
141
+ logger.debug("Connector doesn't have tools, initializing it");
142
+ try {
143
+ await connector.initialize();
144
+ return true;
145
+ } catch (err) {
146
+ logger.error(`Error initializing connector: ${err}`);
147
+ return false;
148
+ }
149
+ }
150
+ return true;
151
+ }
152
+ };
153
+
154
+ // src/adapters/langchain_adapter.ts
155
+ function schemaToZod(schema) {
156
+ try {
157
+ return JSONSchemaToZod.convert(schema);
158
+ } catch (err) {
159
+ logger.warn(`Failed to convert JSON schema to Zod: ${err}`);
160
+ return z.any();
161
+ }
162
+ }
163
+ __name(schemaToZod, "schemaToZod");
164
+ var LangChainAdapter = class extends BaseAdapter {
165
+ static {
166
+ __name(this, "LangChainAdapter");
167
+ }
168
+ constructor(disallowedTools = []) {
169
+ super(disallowedTools);
170
+ }
171
+ /**
172
+ * Convert a single MCP tool specification into a LangChainJS structured tool.
173
+ */
174
+ convertTool(mcpTool, connector) {
175
+ if (this.disallowedTools.includes(mcpTool.name)) {
176
+ return null;
177
+ }
178
+ const argsSchema = mcpTool.inputSchema ? schemaToZod(mcpTool.inputSchema) : z.object({}).optional();
179
+ const tool = new DynamicStructuredTool({
180
+ name: mcpTool.name ?? "NO NAME",
181
+ description: mcpTool.description ?? "",
182
+ // Blank is acceptable but discouraged.
183
+ schema: argsSchema,
184
+ func: /* @__PURE__ */ __name(async (input) => {
185
+ logger.debug(`MCP tool "${mcpTool.name}" received input: ${JSON.stringify(input)}`);
186
+ try {
187
+ const result = await connector.callTool(mcpTool.name, input);
188
+ return JSON.stringify(result);
189
+ } catch (err) {
190
+ logger.error(`Error executing MCP tool: ${err.message}`);
191
+ return `Error executing MCP tool: ${String(err)}`;
192
+ }
193
+ }, "func")
194
+ });
195
+ return tool;
196
+ }
197
+ };
198
+
199
+ // src/managers/server_manager.ts
200
+ import { isEqual } from "lodash-es";
201
+
202
+ // src/managers/tools/acquire_active_mcp_server.ts
203
+ import { z as z2 } from "zod";
204
+
205
+ // src/managers/tools/base.ts
206
+ import { StructuredTool } from "@langchain/core/tools";
207
+ var MCPServerTool = class extends StructuredTool {
208
+ static {
209
+ __name(this, "MCPServerTool");
210
+ }
211
+ name = "mcp_server_tool";
212
+ description = "Base tool for MCP server operations.";
213
+ schema;
214
+ _manager;
215
+ constructor(manager) {
216
+ super();
217
+ this._manager = manager;
218
+ }
219
+ async _call(_arg, _runManager, _parentConfig) {
220
+ throw new Error("Method not implemented.");
221
+ }
222
+ get manager() {
223
+ return this._manager;
224
+ }
225
+ };
226
+
227
+ // src/managers/tools/acquire_active_mcp_server.ts
228
+ var PresentActiveServerSchema = z2.object({});
229
+ var AcquireActiveMCPServerTool = class extends MCPServerTool {
230
+ static {
231
+ __name(this, "AcquireActiveMCPServerTool");
232
+ }
233
+ name = "get_active_mcp_server";
234
+ description = "Get the currently active MCP (Model Context Protocol) server";
235
+ schema = PresentActiveServerSchema;
236
+ constructor(manager) {
237
+ super(manager);
238
+ }
239
+ async _call() {
240
+ if (!this.manager.activeServer) {
241
+ return `No MCP server is currently active. Use connect_to_mcp_server to connect to a server.`;
242
+ }
243
+ return `Currently active MCP server: ${this.manager.activeServer}`;
244
+ }
245
+ };
246
+
247
+ // src/managers/tools/add_server_from_config.ts
248
+ import { StructuredTool as StructuredTool2 } from "langchain/tools";
249
+ import { z as z3 } from "zod";
250
+ var AddMCPServerFromConfigTool = class extends StructuredTool2 {
251
+ static {
252
+ __name(this, "AddMCPServerFromConfigTool");
253
+ }
254
+ name = "add_mcp_server_from_config";
255
+ description = "Adds a new MCP server to the client from a configuration object and connects to it, making its tools available.";
256
+ schema = z3.object({
257
+ serverName: z3.string().describe("The name for the new MCP server."),
258
+ serverConfig: z3.any().describe(
259
+ 'The configuration object for the server. This should not include the top-level "mcpServers" key.'
260
+ )
261
+ });
262
+ manager;
263
+ constructor(manager) {
264
+ super();
265
+ this.manager = manager;
266
+ }
267
+ async _call({
268
+ serverName,
269
+ serverConfig
270
+ }) {
271
+ try {
272
+ this.manager.client.addServer(serverName, serverConfig);
273
+ let result = `Server '${serverName}' added to the client.`;
274
+ logger.debug(
275
+ `Connecting to new server '${serverName}' and discovering tools.`
276
+ );
277
+ const session = await this.manager.client.createSession(serverName);
278
+ const connector = session.connector;
279
+ const tools = await this.manager.adapter.createToolsFromConnectors([connector]);
280
+ this.manager.serverTools[serverName] = tools;
281
+ this.manager.initializedServers[serverName] = true;
282
+ this.manager.activeServer = serverName;
283
+ const numTools = tools.length;
284
+ result += ` Session created and connected. '${serverName}' is now the active server with ${numTools} tools available.`;
285
+ result += `
286
+
287
+ ${tools.map((t) => t.name).join("\n")}`;
288
+ logger.info(result);
289
+ return result;
290
+ } catch (e) {
291
+ logger.error(
292
+ `Failed to add or connect to server '${serverName}': ${e.message}`
293
+ );
294
+ return `Failed to add or connect to server '${serverName}': ${e.message}`;
295
+ }
296
+ }
297
+ };
298
+
299
+ // src/managers/tools/connect_mcp_server.ts
300
+ import { z as z4 } from "zod";
301
+ var ConnectMCPServerSchema = z4.object({
302
+ serverName: z4.string().describe("The name of the MCP server.")
303
+ });
304
+ var ConnectMCPServerTool = class extends MCPServerTool {
305
+ static {
306
+ __name(this, "ConnectMCPServerTool");
307
+ }
308
+ name = "connect_to_mcp_server";
309
+ description = "Connect to a specific MCP (Model Context Protocol) server to use its tools. Use this tool to connect to a specific server and use its tools.";
310
+ schema = ConnectMCPServerSchema;
311
+ constructor(manager) {
312
+ super(manager);
313
+ }
314
+ async _call({ serverName }) {
315
+ const serverNames = this.manager.client.getServerNames();
316
+ if (!serverNames.includes(serverName)) {
317
+ const available = serverNames.length > 0 ? serverNames.join(", ") : "none";
318
+ return `Server '${serverName}' not found. Available servers: ${available}`;
319
+ }
320
+ if (this.manager.activeServer === serverName) {
321
+ return `Already connected to MCP server '${serverName}'`;
322
+ }
323
+ try {
324
+ let session = this.manager.client.getSession(serverName);
325
+ logger.debug(`Using existing session for server '${serverName}'`);
326
+ if (!session) {
327
+ logger.debug(`Creating new session for server '${serverName}'`);
328
+ session = await this.manager.client.createSession(serverName);
329
+ }
330
+ this.manager.activeServer = serverName;
331
+ if (this.manager.serverTools[serverName]) {
332
+ const connector = session.connector;
333
+ const tools = await this.manager.adapter.createToolsFromConnectors([connector]);
334
+ this.manager.serverTools[serverName] = tools;
335
+ this.manager.initializedServers[serverName] = true;
336
+ }
337
+ const serverTools = this.manager.serverTools[serverName] || [];
338
+ const numTools = serverTools.length;
339
+ return `Connected to MCP server '${serverName}'. ${numTools} tools are now available.`;
340
+ } catch (error) {
341
+ logger.error(`Error connecting to server '${serverName}': ${String(error)}`);
342
+ return `Failed to connect to server '${serverName}': ${String(error)}`;
343
+ }
344
+ }
345
+ };
346
+
347
+ // src/managers/tools/list_mcp_servers.ts
348
+ import { z as z5 } from "zod";
349
+ var EnumerateServersSchema = z5.object({});
350
+ var ListMCPServersTool = class extends MCPServerTool {
351
+ static {
352
+ __name(this, "ListMCPServersTool");
353
+ }
354
+ name = "list_mcp_servers";
355
+ description = `Lists all available MCP (Model Context Protocol) servers that can be connected to, along with the tools available on each server. Use this tool to discover servers and see what functionalities they offer.`;
356
+ schema = EnumerateServersSchema;
357
+ constructor(manager) {
358
+ super(manager);
359
+ }
360
+ async _call() {
361
+ const serverNames = this.manager.client.getServerNames();
362
+ if (serverNames.length === 0) {
363
+ return `No MCP servers are currently defined.`;
364
+ }
365
+ const outputLines = ["Available MCP servers:"];
366
+ for (const serverName of serverNames) {
367
+ const isActiveServer = serverName === this.manager.activeServer;
368
+ const activeFlag = isActiveServer ? " (ACTIVE)" : "";
369
+ outputLines.push(`- ${serverName}${activeFlag}`);
370
+ try {
371
+ const serverTools = this.manager.serverTools?.[serverName] ?? [];
372
+ const numberOfTools = Array.isArray(serverTools) ? serverTools.length : 0;
373
+ outputLines.push(`${numberOfTools} tools available for this server
374
+ `);
375
+ } catch (error) {
376
+ logger.error(`Unexpected error listing tools for server '${serverName}': ${String(error)}`);
377
+ }
378
+ }
379
+ return outputLines.join("\n");
380
+ }
381
+ };
382
+
383
+ // src/managers/tools/release_mcp_server_connection.ts
384
+ import { z as z6 } from "zod";
385
+ var ReleaseConnectionSchema = z6.object({});
386
+ var ReleaseMCPServerConnectionTool = class extends MCPServerTool {
387
+ static {
388
+ __name(this, "ReleaseMCPServerConnectionTool");
389
+ }
390
+ name = "disconnect_from_mcp_server";
391
+ description = "Disconnect from the currently active MCP (Model Context Protocol) server";
392
+ schema = ReleaseConnectionSchema;
393
+ constructor(manager) {
394
+ super(manager);
395
+ }
396
+ async _call() {
397
+ if (!this.manager.activeServer) {
398
+ return `No MCP server is currently active, so there's nothing to disconnect from.`;
399
+ }
400
+ const serverName = this.manager.activeServer;
401
+ this.manager.activeServer = null;
402
+ return `Successfully disconnected from MCP server '${serverName}'.`;
403
+ }
404
+ };
405
+
406
+ // src/managers/server_manager.ts
407
+ var ServerManager = class {
408
+ static {
409
+ __name(this, "ServerManager");
410
+ }
411
+ initializedServers = {};
412
+ serverTools = {};
413
+ client;
414
+ adapter;
415
+ activeServer = null;
416
+ overrideManagementTools;
417
+ constructor(client, adapter, managementTools) {
418
+ this.client = client;
419
+ this.adapter = adapter;
420
+ this.overrideManagementTools = managementTools;
421
+ }
422
+ setManagementTools(tools) {
423
+ this.overrideManagementTools = tools;
424
+ logger.info(
425
+ `Overriding default management tools with a new set of ${tools.length} tools.`
426
+ );
427
+ }
428
+ logState(context) {
429
+ const allServerNames = this.client.getServerNames();
430
+ const activeSessionNames = Object.keys(this.client.getAllActiveSessions());
431
+ if (allServerNames.length === 0) {
432
+ logger.info("Server Manager State: No servers configured.");
433
+ return;
434
+ }
435
+ const tableData = allServerNames.map((name) => ({
436
+ "Server Name": name,
437
+ "Connected": activeSessionNames.includes(name) ? "\u2705" : "\u274C",
438
+ "Initialized": this.initializedServers[name] ? "\u2705" : "\u274C",
439
+ "Tool Count": this.serverTools[name]?.length ?? 0,
440
+ "Active": this.activeServer === name ? "\u2705" : "\u274C"
441
+ }));
442
+ logger.info(`Server Manager State: [${context}]`);
443
+ console.table(tableData);
444
+ }
445
+ initialize() {
446
+ const serverNames = this.client.getServerNames?.();
447
+ if (serverNames.length === 0) {
448
+ logger.warn("No MCP servers defined in client configuration");
449
+ }
450
+ }
451
+ async prefetchServerTools() {
452
+ const servers = this.client.getServerNames();
453
+ for (const serverName of servers) {
454
+ try {
455
+ let session = null;
456
+ session = this.client.getSession(serverName);
457
+ logger.debug(`Using existing session for server '${serverName}' to prefetch tools.`);
458
+ if (!session) {
459
+ session = await this.client.createSession(serverName).catch((createSessionError) => {
460
+ logger.warn(`Could not create session for '${serverName}' during prefetch: ${createSessionError}`);
461
+ return null;
462
+ });
463
+ logger.debug(`Temporarily created session for '${serverName}' to prefetch tools.`);
464
+ }
465
+ if (session) {
466
+ const connector = session.connector;
467
+ let tools = [];
468
+ try {
469
+ tools = await this.adapter.createToolsFromConnectors([connector]);
470
+ } catch (toolFetchError) {
471
+ logger.error(`Failed to create tools from connector for server '${serverName}': ${toolFetchError}`);
472
+ continue;
473
+ }
474
+ const cachedTools = this.serverTools[serverName];
475
+ const toolsChanged = !cachedTools || !isEqual(cachedTools, tools);
476
+ if (toolsChanged) {
477
+ this.serverTools[serverName] = tools;
478
+ this.initializedServers[serverName] = true;
479
+ logger.debug(`Prefetched ${tools.length} tools for server '${serverName}'.`);
480
+ } else {
481
+ logger.debug(
482
+ `Tools for server '${serverName}' unchanged, using cached version.`
483
+ );
484
+ }
485
+ }
486
+ } catch (outerError) {
487
+ logger.error(`Error prefetching tools for server '${serverName}': ${outerError}`);
488
+ }
489
+ }
490
+ }
491
+ get tools() {
492
+ if (logger.level === "debug") {
493
+ this.logState("Providing tools to agent");
494
+ }
495
+ const managementTools = this.overrideManagementTools ?? [
496
+ new AddMCPServerFromConfigTool(this),
497
+ new ListMCPServersTool(this),
498
+ new ConnectMCPServerTool(this),
499
+ new AcquireActiveMCPServerTool(this),
500
+ new ReleaseMCPServerConnectionTool(this)
501
+ ];
502
+ if (this.activeServer && this.serverTools[this.activeServer]) {
503
+ const activeTools = this.serverTools[this.activeServer];
504
+ logger.debug(
505
+ `Adding ${activeTools.length} tools from active server '${this.activeServer}'`
506
+ );
507
+ return [...managementTools, ...activeTools];
508
+ }
509
+ return managementTools;
510
+ }
511
+ };
512
+
513
+ // src/observability/manager.ts
514
+ var ObservabilityManager = class {
515
+ static {
516
+ __name(this, "ObservabilityManager");
517
+ }
518
+ customCallbacks;
519
+ availableHandlers = [];
520
+ handlerNames = [];
521
+ initialized = false;
522
+ verbose;
523
+ observe;
524
+ agentId;
525
+ metadata;
526
+ metadataProvider;
527
+ tagsProvider;
528
+ constructor(config = {}) {
529
+ this.customCallbacks = config.customCallbacks;
530
+ this.verbose = config.verbose ?? false;
531
+ this.observe = config.observe ?? true;
532
+ this.agentId = config.agentId;
533
+ this.metadata = config.metadata;
534
+ this.metadataProvider = config.metadataProvider;
535
+ this.tagsProvider = config.tagsProvider;
536
+ }
537
+ /**
538
+ * Collect all available observability handlers from configured platforms.
539
+ */
540
+ async collectAvailableHandlers() {
541
+ if (this.initialized) {
542
+ return;
543
+ }
544
+ try {
545
+ const { langfuseHandler: langfuseHandler2, langfuseInitPromise: langfuseInitPromise2 } = await import("./langfuse-YA2S23SM.js");
546
+ if (this.agentId || this.metadata || this.metadataProvider || this.tagsProvider) {
547
+ const { initializeLangfuse } = await import("./langfuse-YA2S23SM.js");
548
+ await initializeLangfuse(this.agentId, this.metadata, this.metadataProvider, this.tagsProvider);
549
+ logger.debug(`ObservabilityManager: Reinitialized Langfuse with agent ID: ${this.agentId}, metadata: ${JSON.stringify(this.metadata)}`);
550
+ } else {
551
+ const initPromise = langfuseInitPromise2();
552
+ if (initPromise) {
553
+ await initPromise;
554
+ }
555
+ }
556
+ const handler = langfuseHandler2();
557
+ if (handler) {
558
+ this.availableHandlers.push(handler);
559
+ this.handlerNames.push("Langfuse");
560
+ logger.debug("ObservabilityManager: Langfuse handler available");
561
+ }
562
+ } catch {
563
+ logger.debug("ObservabilityManager: Langfuse module not available");
564
+ }
565
+ this.initialized = true;
566
+ }
567
+ /**
568
+ * Get the list of callbacks to use.
569
+ * @returns List of callbacks - either custom callbacks if provided, or all available observability handlers.
570
+ */
571
+ async getCallbacks() {
572
+ if (!this.observe) {
573
+ logger.debug("ObservabilityManager: Observability disabled via observe=false");
574
+ return [];
575
+ }
576
+ if (this.customCallbacks) {
577
+ logger.debug(`ObservabilityManager: Using ${this.customCallbacks.length} custom callbacks`);
578
+ return this.customCallbacks;
579
+ }
580
+ await this.collectAvailableHandlers();
581
+ if (this.availableHandlers.length > 0) {
582
+ logger.debug(`ObservabilityManager: Using ${this.availableHandlers.length} handlers`);
583
+ } else {
584
+ logger.debug("ObservabilityManager: No callbacks configured");
585
+ }
586
+ return this.availableHandlers;
587
+ }
588
+ /**
589
+ * Get the names of available handlers.
590
+ * @returns List of handler names (e.g., ["Langfuse", "Laminar"])
591
+ */
592
+ async getHandlerNames() {
593
+ if (!this.observe) {
594
+ return [];
595
+ }
596
+ if (this.customCallbacks) {
597
+ return this.customCallbacks.map((cb) => cb.constructor.name);
598
+ }
599
+ await this.collectAvailableHandlers();
600
+ return this.handlerNames;
601
+ }
602
+ /**
603
+ * Check if any callbacks are available.
604
+ * @returns True if callbacks are available, False otherwise.
605
+ */
606
+ async hasCallbacks() {
607
+ if (!this.observe) {
608
+ return false;
609
+ }
610
+ const callbacks = await this.getCallbacks();
611
+ return callbacks.length > 0;
612
+ }
613
+ /**
614
+ * Add a callback to the custom callbacks list.
615
+ * @param callback The callback to add.
616
+ */
617
+ addCallback(callback) {
618
+ if (!this.customCallbacks) {
619
+ this.customCallbacks = [];
620
+ }
621
+ this.customCallbacks.push(callback);
622
+ logger.debug(`ObservabilityManager: Added custom callback: ${callback.constructor.name}`);
623
+ }
624
+ /**
625
+ * Clear all custom callbacks.
626
+ */
627
+ clearCallbacks() {
628
+ this.customCallbacks = [];
629
+ logger.debug("ObservabilityManager: Cleared all custom callbacks");
630
+ }
631
+ /**
632
+ * Flush all pending traces to observability platforms.
633
+ * Important for serverless environments and short-lived processes.
634
+ */
635
+ async flush() {
636
+ const callbacks = await this.getCallbacks();
637
+ for (const callback of callbacks) {
638
+ if ("flushAsync" in callback && typeof callback.flushAsync === "function") {
639
+ await callback.flushAsync();
640
+ }
641
+ }
642
+ logger.debug("ObservabilityManager: All traces flushed");
643
+ }
644
+ /**
645
+ * Shutdown all handlers gracefully (for serverless environments).
646
+ */
647
+ async shutdown() {
648
+ await this.flush();
649
+ const callbacks = await this.getCallbacks();
650
+ for (const callback of callbacks) {
651
+ if ("shutdownAsync" in callback && typeof callback.shutdownAsync === "function") {
652
+ await callback.shutdownAsync();
653
+ } else if ("shutdown" in callback && typeof callback.shutdown === "function") {
654
+ await callback.shutdown();
655
+ }
656
+ }
657
+ logger.debug("ObservabilityManager: All handlers shutdown");
658
+ }
659
+ /**
660
+ * String representation of the ObservabilityManager.
661
+ */
662
+ toString() {
663
+ const names = this.handlerNames;
664
+ if (names.length > 0) {
665
+ return `ObservabilityManager(handlers=${names.join(", ")})`;
666
+ }
667
+ return "ObservabilityManager(no handlers)";
668
+ }
669
+ };
670
+
671
+ // src/telemetry/telemetry.ts
672
+ import * as fs2 from "fs";
673
+ import * as os from "os";
674
+ import * as path2 from "path";
675
+ import { PostHog } from "posthog-node";
676
+ import { v4 as uuidv4 } from "uuid";
677
+
678
+ // src/telemetry/events.ts
679
+ var BaseTelemetryEvent = class {
680
+ static {
681
+ __name(this, "BaseTelemetryEvent");
682
+ }
683
+ };
684
+ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
685
+ constructor(data) {
686
+ super();
687
+ this.data = data;
688
+ }
689
+ static {
690
+ __name(this, "MCPAgentExecutionEvent");
691
+ }
692
+ get name() {
693
+ return "mcp_agent_execution";
694
+ }
695
+ get properties() {
696
+ return {
697
+ // Core execution info
698
+ execution_method: this.data.executionMethod,
699
+ query: this.data.query,
700
+ query_length: this.data.query.length,
701
+ success: this.data.success,
702
+ // Agent configuration
703
+ model_provider: this.data.modelProvider,
704
+ model_name: this.data.modelName,
705
+ server_count: this.data.serverCount,
706
+ server_identifiers: this.data.serverIdentifiers,
707
+ total_tools_available: this.data.totalToolsAvailable,
708
+ tools_available_names: this.data.toolsAvailableNames,
709
+ max_steps_configured: this.data.maxStepsConfigured,
710
+ memory_enabled: this.data.memoryEnabled,
711
+ use_server_manager: this.data.useServerManager,
712
+ // Execution parameters (always include, even if null)
713
+ max_steps_used: this.data.maxStepsUsed,
714
+ manage_connector: this.data.manageConnector,
715
+ external_history_used: this.data.externalHistoryUsed,
716
+ // Execution results (always include, even if null)
717
+ steps_taken: this.data.stepsTaken ?? null,
718
+ tools_used_count: this.data.toolsUsedCount ?? null,
719
+ tools_used_names: this.data.toolsUsedNames ?? null,
720
+ response: this.data.response ?? null,
721
+ response_length: this.data.response ? this.data.response.length : null,
722
+ execution_time_ms: this.data.executionTimeMs ?? null,
723
+ error_type: this.data.errorType ?? null,
724
+ conversation_history_length: this.data.conversationHistoryLength ?? null
725
+ };
726
+ }
727
+ };
728
+
729
+ // src/telemetry/utils.ts
730
+ import * as fs from "fs";
731
+ import * as path from "path";
732
+ function getPackageVersion() {
733
+ try {
734
+ if (typeof __dirname === "undefined" || typeof fs === "undefined") {
735
+ return "unknown";
736
+ }
737
+ const packagePath = path.join(__dirname, "../../package.json");
738
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
739
+ return packageJson.version || "unknown";
740
+ } catch {
741
+ return "unknown";
742
+ }
743
+ }
744
+ __name(getPackageVersion, "getPackageVersion");
745
+ function getModelProvider(llm) {
746
+ return llm._llm_type || llm.constructor.name.toLowerCase();
747
+ }
748
+ __name(getModelProvider, "getModelProvider");
749
+ function getModelName(llm) {
750
+ if ("_identifyingParams" in llm) {
751
+ const identifyingParams = llm._identifyingParams;
752
+ if (typeof identifyingParams === "object" && identifyingParams !== null) {
753
+ for (const key of ["model", "modelName", "model_name", "modelId", "model_id", "deploymentName", "deployment_name"]) {
754
+ if (key in identifyingParams) {
755
+ return String(identifyingParams[key]);
756
+ }
757
+ }
758
+ }
759
+ }
760
+ return llm.model || llm.modelName || llm.constructor.name;
761
+ }
762
+ __name(getModelName, "getModelName");
763
+ function extractModelInfo(llm) {
764
+ return [getModelProvider(llm), getModelName(llm)];
765
+ }
766
+ __name(extractModelInfo, "extractModelInfo");
767
+
768
+ // src/telemetry/telemetry.ts
769
+ function isNodeJSEnvironment() {
770
+ try {
771
+ if (typeof navigator !== "undefined" && navigator.userAgent?.includes("Cloudflare-Workers")) {
772
+ return false;
773
+ }
774
+ if (typeof globalThis.EdgeRuntime !== "undefined" || typeof globalThis.Deno !== "undefined") {
775
+ return false;
776
+ }
777
+ const hasNodeGlobals = typeof process !== "undefined" && typeof process.platform !== "undefined" && typeof __dirname !== "undefined";
778
+ const hasNodeModules = typeof fs2 !== "undefined" && typeof os !== "undefined" && typeof fs2.existsSync === "function";
779
+ return hasNodeGlobals && hasNodeModules;
780
+ } catch {
781
+ return false;
782
+ }
783
+ }
784
+ __name(isNodeJSEnvironment, "isNodeJSEnvironment");
785
+ var ScarfEventLogger = class {
786
+ static {
787
+ __name(this, "ScarfEventLogger");
788
+ }
789
+ endpoint;
790
+ timeout;
791
+ constructor(endpoint, timeout = 3e3) {
792
+ this.endpoint = endpoint;
793
+ this.timeout = timeout;
794
+ }
795
+ async logEvent(properties) {
796
+ try {
797
+ const controller = new AbortController();
798
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
799
+ const response = await fetch(this.endpoint, {
800
+ method: "POST",
801
+ headers: {
802
+ "Content-Type": "application/json"
803
+ },
804
+ body: JSON.stringify(properties),
805
+ signal: controller.signal
806
+ });
807
+ clearTimeout(timeoutId);
808
+ if (!response.ok) {
809
+ throw new Error(`HTTP error! status: ${response.status}`);
810
+ }
811
+ } catch (error) {
812
+ logger.debug(`Failed to send Scarf event: ${error}`);
813
+ }
814
+ }
815
+ };
816
+ function getCacheHome() {
817
+ if (!isNodeJSEnvironment()) {
818
+ return "/tmp/mcp_use_cache";
819
+ }
820
+ const envVar = process.env.XDG_CACHE_HOME;
821
+ if (envVar && path2.isAbsolute(envVar)) {
822
+ return envVar;
823
+ }
824
+ const platform = process.platform;
825
+ const homeDir = os.homedir();
826
+ if (platform === "win32") {
827
+ const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
828
+ if (appdata) {
829
+ return appdata;
830
+ }
831
+ return path2.join(homeDir, "AppData", "Local");
832
+ } else if (platform === "darwin") {
833
+ return path2.join(homeDir, "Library", "Caches");
834
+ } else {
835
+ return path2.join(homeDir, ".cache");
836
+ }
837
+ }
838
+ __name(getCacheHome, "getCacheHome");
839
+ var Telemetry = class _Telemetry {
840
+ static {
841
+ __name(this, "Telemetry");
842
+ }
843
+ static instance = null;
844
+ USER_ID_PATH = path2.join(getCacheHome(), "mcp_use_3", "telemetry_user_id");
845
+ VERSION_DOWNLOAD_PATH = path2.join(getCacheHome(), "mcp_use", "download_version");
846
+ PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
847
+ HOST = "https://eu.i.posthog.com";
848
+ SCARF_GATEWAY_URL = "https://mcpuse.gateway.scarf.sh/events-ts";
849
+ UNKNOWN_USER_ID = "UNKNOWN_USER_ID";
850
+ _currUserId = null;
851
+ _posthogClient = null;
852
+ _scarfClient = null;
853
+ _source = "typescript";
854
+ constructor() {
855
+ const isNodeJS = isNodeJSEnvironment();
856
+ const telemetryDisabled = typeof process !== "undefined" && process.env?.MCP_USE_ANONYMIZED_TELEMETRY?.toLowerCase() === "false" || false;
857
+ this._source = typeof process !== "undefined" && process.env?.MCP_USE_TELEMETRY_SOURCE || "typescript";
858
+ if (telemetryDisabled) {
859
+ this._posthogClient = null;
860
+ this._scarfClient = null;
861
+ logger.debug("Telemetry disabled via environment variable");
862
+ } else if (!isNodeJS) {
863
+ this._posthogClient = null;
864
+ this._scarfClient = null;
865
+ logger.debug("Telemetry disabled - non-Node.js environment detected (e.g., Cloudflare Workers)");
866
+ } else {
867
+ logger.info("Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable.");
868
+ try {
869
+ this._posthogClient = new PostHog(
870
+ this.PROJECT_API_KEY,
871
+ {
872
+ host: this.HOST,
873
+ disableGeoip: false
874
+ }
875
+ );
876
+ } catch (e) {
877
+ logger.warn(`Failed to initialize PostHog telemetry: ${e}`);
878
+ this._posthogClient = null;
879
+ }
880
+ try {
881
+ this._scarfClient = new ScarfEventLogger(this.SCARF_GATEWAY_URL, 3e3);
882
+ } catch (e) {
883
+ logger.warn(`Failed to initialize Scarf telemetry: ${e}`);
884
+ this._scarfClient = null;
885
+ }
886
+ }
887
+ }
888
+ static getInstance() {
889
+ if (!_Telemetry.instance) {
890
+ _Telemetry.instance = new _Telemetry();
891
+ }
892
+ return _Telemetry.instance;
893
+ }
894
+ /**
895
+ * Set the source identifier for telemetry events.
896
+ * This allows tracking usage from different applications.
897
+ * @param source - The source identifier (e.g., "my-app", "cli", "vs-code-extension")
898
+ */
899
+ setSource(source) {
900
+ this._source = source;
901
+ logger.debug(`Telemetry source set to: ${source}`);
902
+ }
903
+ /**
904
+ * Get the current source identifier.
905
+ */
906
+ getSource() {
907
+ return this._source;
908
+ }
909
+ get userId() {
910
+ if (this._currUserId) {
911
+ return this._currUserId;
912
+ }
913
+ if (!isNodeJSEnvironment()) {
914
+ this._currUserId = this.UNKNOWN_USER_ID;
915
+ return this._currUserId;
916
+ }
917
+ try {
918
+ const isFirstTime = !fs2.existsSync(this.USER_ID_PATH);
919
+ if (isFirstTime) {
920
+ logger.debug(`Creating user ID path: ${this.USER_ID_PATH}`);
921
+ fs2.mkdirSync(path2.dirname(this.USER_ID_PATH), { recursive: true });
922
+ const newUserId = uuidv4();
923
+ fs2.writeFileSync(this.USER_ID_PATH, newUserId);
924
+ this._currUserId = newUserId;
925
+ logger.debug(`User ID path created: ${this.USER_ID_PATH}`);
926
+ } else {
927
+ this._currUserId = fs2.readFileSync(this.USER_ID_PATH, "utf-8").trim();
928
+ }
929
+ this.trackPackageDownload({
930
+ triggered_by: "user_id_property"
931
+ }).catch((e) => logger.debug(`Failed to track package download: ${e}`));
932
+ } catch (e) {
933
+ logger.debug(`Failed to get/create user ID: ${e}`);
934
+ this._currUserId = this.UNKNOWN_USER_ID;
935
+ }
936
+ return this._currUserId;
937
+ }
938
+ async capture(event) {
939
+ if (!this._posthogClient && !this._scarfClient) {
940
+ return;
941
+ }
942
+ if (this._posthogClient) {
943
+ try {
944
+ const properties = { ...event.properties };
945
+ properties.mcp_use_version = getPackageVersion();
946
+ properties.language = "typescript";
947
+ properties.source = this._source;
948
+ this._posthogClient.capture({
949
+ distinctId: this.userId,
950
+ event: event.name,
951
+ properties
952
+ });
953
+ } catch (e) {
954
+ logger.debug(`Failed to track PostHog event ${event.name}: ${e}`);
955
+ }
956
+ }
957
+ if (this._scarfClient) {
958
+ try {
959
+ const properties = {};
960
+ properties.mcp_use_version = getPackageVersion();
961
+ properties.user_id = this.userId;
962
+ properties.event = event.name;
963
+ properties.language = "typescript";
964
+ properties.source = this._source;
965
+ await this._scarfClient.logEvent(properties);
966
+ } catch (e) {
967
+ logger.debug(`Failed to track Scarf event ${event.name}: ${e}`);
968
+ }
969
+ }
970
+ }
971
+ async trackPackageDownload(properties) {
972
+ if (!this._scarfClient) {
973
+ return;
974
+ }
975
+ if (!isNodeJSEnvironment()) {
976
+ return;
977
+ }
978
+ try {
979
+ const currentVersion = getPackageVersion();
980
+ let shouldTrack = false;
981
+ let firstDownload = false;
982
+ if (!fs2.existsSync(this.VERSION_DOWNLOAD_PATH)) {
983
+ shouldTrack = true;
984
+ firstDownload = true;
985
+ fs2.mkdirSync(path2.dirname(this.VERSION_DOWNLOAD_PATH), { recursive: true });
986
+ fs2.writeFileSync(this.VERSION_DOWNLOAD_PATH, currentVersion);
987
+ } else {
988
+ const savedVersion = fs2.readFileSync(this.VERSION_DOWNLOAD_PATH, "utf-8").trim();
989
+ if (currentVersion > savedVersion) {
990
+ shouldTrack = true;
991
+ firstDownload = false;
992
+ fs2.writeFileSync(this.VERSION_DOWNLOAD_PATH, currentVersion);
993
+ }
994
+ }
995
+ if (shouldTrack) {
996
+ logger.debug(`Tracking package download event with properties: ${JSON.stringify(properties)}`);
997
+ const eventProperties = { ...properties || {} };
998
+ eventProperties.mcp_use_version = currentVersion;
999
+ eventProperties.user_id = this.userId;
1000
+ eventProperties.event = "package_download";
1001
+ eventProperties.first_download = firstDownload;
1002
+ eventProperties.language = "typescript";
1003
+ eventProperties.source = this._source;
1004
+ await this._scarfClient.logEvent(eventProperties);
1005
+ }
1006
+ } catch (e) {
1007
+ logger.debug(`Failed to track Scarf package_download event: ${e}`);
1008
+ }
1009
+ }
1010
+ async trackAgentExecution(data) {
1011
+ const event = new MCPAgentExecutionEvent(data);
1012
+ await this.capture(event);
1013
+ }
1014
+ flush() {
1015
+ if (this._posthogClient) {
1016
+ try {
1017
+ this._posthogClient.flush();
1018
+ logger.debug("PostHog client telemetry queue flushed");
1019
+ } catch (e) {
1020
+ logger.debug(`Failed to flush PostHog client: ${e}`);
1021
+ }
1022
+ }
1023
+ if (this._scarfClient) {
1024
+ logger.debug("Scarf telemetry events sent immediately (no flush needed)");
1025
+ }
1026
+ }
1027
+ shutdown() {
1028
+ if (this._posthogClient) {
1029
+ try {
1030
+ this._posthogClient.shutdown();
1031
+ logger.debug("PostHog client shutdown successfully");
1032
+ } catch (e) {
1033
+ logger.debug(`Error shutting down PostHog client: ${e}`);
1034
+ }
1035
+ }
1036
+ if (this._scarfClient) {
1037
+ logger.debug("Scarf telemetry client shutdown (no action needed)");
1038
+ }
1039
+ }
1040
+ };
1041
+
1042
+ // src/telemetry/index.ts
1043
+ function setTelemetrySource(source) {
1044
+ Telemetry.getInstance().setSource(source);
1045
+ }
1046
+ __name(setTelemetrySource, "setTelemetrySource");
1047
+
1048
+ // src/agents/prompts/system_prompt_builder.ts
1049
+ import { SystemMessage } from "@langchain/core/messages";
1050
+ function generateToolDescriptions(tools, disallowedTools) {
1051
+ const disallowedSet = new Set(disallowedTools ?? []);
1052
+ const descriptions = [];
1053
+ for (const tool of tools) {
1054
+ if (disallowedSet.has(tool.name))
1055
+ continue;
1056
+ const escaped = tool.description.replace(/\{/g, "{{").replace(/\}/g, "}}");
1057
+ descriptions.push(`- ${tool.name}: ${escaped}`);
1058
+ }
1059
+ return descriptions;
1060
+ }
1061
+ __name(generateToolDescriptions, "generateToolDescriptions");
1062
+ function buildSystemPromptContent(template, toolDescriptionLines, additionalInstructions) {
1063
+ const block = toolDescriptionLines.join("\n");
1064
+ let content;
1065
+ if (template.includes("{tool_descriptions}")) {
1066
+ content = template.replace("{tool_descriptions}", block);
1067
+ } else {
1068
+ console.warn("`{tool_descriptions}` placeholder not found; appending at end.");
1069
+ content = `${template}
1070
+
1071
+ Available tools:
1072
+ ${block}`;
1073
+ }
1074
+ if (additionalInstructions) {
1075
+ content += `
1076
+
1077
+ ${additionalInstructions}`;
1078
+ }
1079
+ return content;
1080
+ }
1081
+ __name(buildSystemPromptContent, "buildSystemPromptContent");
1082
+ function createSystemMessage(tools, systemPromptTemplate, serverManagerTemplate, useServerManager, disallowedTools, userProvidedPrompt, additionalInstructions) {
1083
+ if (userProvidedPrompt) {
1084
+ return new SystemMessage({ content: userProvidedPrompt });
1085
+ }
1086
+ const template = useServerManager ? serverManagerTemplate : systemPromptTemplate;
1087
+ const toolLines = generateToolDescriptions(tools, disallowedTools);
1088
+ const finalContent = buildSystemPromptContent(
1089
+ template,
1090
+ toolLines,
1091
+ additionalInstructions
1092
+ );
1093
+ return new SystemMessage({ content: finalContent });
1094
+ }
1095
+ __name(createSystemMessage, "createSystemMessage");
1096
+
1097
+ // src/agents/prompts/templates.ts
1098
+ var DEFAULT_SYSTEM_PROMPT_TEMPLATE = `You are a helpful AI assistant.
1099
+ You have access to the following tools:
1100
+
1101
+ {tool_descriptions}
1102
+
1103
+ Use the following format:
1104
+
1105
+ Question: the input question you must answer
1106
+ Thought: you should always think about what to do
1107
+ Action: the action to take, should be one of the available tools
1108
+ Action Input: the input to the action
1109
+ Observation: the result of the action
1110
+ ... (this Thought/Action/Action Input/Observation can repeat N times)
1111
+ Thought: I now know the final answer
1112
+ Final Answer: the final answer to the original input question`;
1113
+ var SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE = `You are a helpful assistant designed to interact with MCP
1114
+ (Model Context Protocol) servers. You can manage connections to different servers and use the tools
1115
+ provided by the currently active server.
1116
+
1117
+ Important: The available tools change depending on which server is active.
1118
+ If a request requires tools not listed below (e.g., file operations, web browsing,
1119
+ image manipulation), you MUST first connect to the appropriate server using
1120
+ 'connect_to_mcp_server'.
1121
+ Use 'list_mcp_servers' to find the relevant server if you are unsure.
1122
+ Only after successfully connecting and seeing the new tools listed in
1123
+ the response should you attempt to use those server-specific tools.
1124
+ Before attempting a task that requires specific tools, you should
1125
+ ensure you are connected to the correct server and aware of its
1126
+ available tools. If unsure, use 'list_mcp_servers' to see options
1127
+ or 'get_active_mcp_server' to check the current connection.
1128
+
1129
+ When you connect to a server using 'connect_to_mcp_server',
1130
+ you will be informed about the new tools that become available.
1131
+ You can then use these server-specific tools in subsequent steps.
1132
+
1133
+ Here are the tools *currently* available to you (this list includes server management tools and will
1134
+ change when you connect to a server):
1135
+ {tool_descriptions}
1136
+ `;
1137
+
1138
+ // src/agents/remote.ts
1139
+ import { zodToJsonSchema } from "zod-to-json-schema";
1140
+ var API_CHATS_ENDPOINT = "/api/v1/chats";
1141
+ var API_CHAT_EXECUTE_ENDPOINT = "/api/v1/chats/{chat_id}/execute";
1142
+ var RemoteAgent = class {
1143
+ static {
1144
+ __name(this, "RemoteAgent");
1145
+ }
1146
+ agentId;
1147
+ apiKey;
1148
+ baseUrl;
1149
+ chatId = null;
1150
+ constructor(options) {
1151
+ this.agentId = options.agentId;
1152
+ this.baseUrl = options.baseUrl ?? "https://cloud.mcp-use.com";
1153
+ const apiKey = options.apiKey ?? process.env.MCP_USE_API_KEY;
1154
+ if (!apiKey) {
1155
+ throw new Error(
1156
+ "API key is required for remote execution. Please provide it as a parameter or set the MCP_USE_API_KEY environment variable. You can get an API key from https://cloud.mcp-use.com"
1157
+ );
1158
+ }
1159
+ this.apiKey = apiKey;
1160
+ }
1161
+ pydanticToJsonSchema(schema) {
1162
+ return zodToJsonSchema(schema);
1163
+ }
1164
+ parseStructuredResponse(responseData, outputSchema) {
1165
+ let resultData;
1166
+ if (typeof responseData === "object" && responseData !== null) {
1167
+ if ("result" in responseData) {
1168
+ const outerResult = responseData.result;
1169
+ if (typeof outerResult === "object" && outerResult !== null && "result" in outerResult) {
1170
+ resultData = outerResult.result;
1171
+ } else {
1172
+ resultData = outerResult;
1173
+ }
1174
+ } else {
1175
+ resultData = responseData;
1176
+ }
1177
+ } else if (typeof responseData === "string") {
1178
+ try {
1179
+ resultData = JSON.parse(responseData);
1180
+ } catch {
1181
+ resultData = { content: responseData };
1182
+ }
1183
+ } else {
1184
+ resultData = responseData;
1185
+ }
1186
+ try {
1187
+ return outputSchema.parse(resultData);
1188
+ } catch (e) {
1189
+ logger.warn(`Failed to parse structured output: ${e}`);
1190
+ const schemaShape = outputSchema._def?.shape();
1191
+ if (schemaShape && "content" in schemaShape) {
1192
+ return outputSchema.parse({ content: String(resultData) });
1193
+ }
1194
+ throw e;
1195
+ }
1196
+ }
1197
+ async createChatSession() {
1198
+ const chatPayload = {
1199
+ title: `Remote Agent Session - ${this.agentId}`,
1200
+ agent_id: this.agentId,
1201
+ type: "agent_execution"
1202
+ };
1203
+ const headers = {
1204
+ "Content-Type": "application/json",
1205
+ "x-api-key": this.apiKey
1206
+ };
1207
+ const chatUrl = `${this.baseUrl}${API_CHATS_ENDPOINT}`;
1208
+ logger.info(`\u{1F4DD} Creating chat session for agent ${this.agentId}`);
1209
+ try {
1210
+ const response = await fetch(chatUrl, {
1211
+ method: "POST",
1212
+ headers,
1213
+ body: JSON.stringify(chatPayload)
1214
+ });
1215
+ if (!response.ok) {
1216
+ const responseText = await response.text();
1217
+ const statusCode = response.status;
1218
+ if (statusCode === 404) {
1219
+ throw new Error(
1220
+ `Agent not found: Agent '${this.agentId}' does not exist or you don't have access to it. Please verify the agent ID and ensure it exists in your account.`
1221
+ );
1222
+ }
1223
+ throw new Error(`Failed to create chat session: ${statusCode} - ${responseText}`);
1224
+ }
1225
+ const chatData = await response.json();
1226
+ const chatId = chatData.id;
1227
+ logger.info(`\u2705 Chat session created: ${chatId}`);
1228
+ return chatId;
1229
+ } catch (e) {
1230
+ if (e instanceof Error) {
1231
+ throw new TypeError(`Failed to create chat session: ${e.message}`);
1232
+ }
1233
+ throw new Error(`Failed to create chat session: ${String(e)}`);
1234
+ }
1235
+ }
1236
+ async run(query, maxSteps, manageConnector, externalHistory, outputSchema) {
1237
+ if (externalHistory !== void 0) {
1238
+ logger.warn("External history is not yet supported for remote execution");
1239
+ }
1240
+ try {
1241
+ logger.info(`\u{1F310} Executing query on remote agent ${this.agentId}`);
1242
+ if (this.chatId === null) {
1243
+ this.chatId = await this.createChatSession();
1244
+ }
1245
+ const chatId = this.chatId;
1246
+ const executionPayload = {
1247
+ query,
1248
+ max_steps: maxSteps ?? 10
1249
+ };
1250
+ if (outputSchema) {
1251
+ executionPayload.output_schema = this.pydanticToJsonSchema(outputSchema);
1252
+ logger.info(`\u{1F527} Using structured output with schema`);
1253
+ }
1254
+ const headers = {
1255
+ "Content-Type": "application/json",
1256
+ "x-api-key": this.apiKey
1257
+ };
1258
+ const executionUrl = `${this.baseUrl}${API_CHAT_EXECUTE_ENDPOINT.replace("{chat_id}", chatId)}`;
1259
+ logger.info(`\u{1F680} Executing agent in chat ${chatId}`);
1260
+ const response = await fetch(executionUrl, {
1261
+ method: "POST",
1262
+ headers,
1263
+ body: JSON.stringify(executionPayload),
1264
+ signal: AbortSignal.timeout(3e5)
1265
+ // 5 minute timeout
1266
+ });
1267
+ if (!response.ok) {
1268
+ const responseText = await response.text();
1269
+ const statusCode = response.status;
1270
+ if (statusCode === 401) {
1271
+ logger.error(`\u274C Authentication failed: ${responseText}`);
1272
+ throw new Error(
1273
+ "Authentication failed: Invalid or missing API key. Please check your API key and ensure the MCP_USE_API_KEY environment variable is set correctly."
1274
+ );
1275
+ } else if (statusCode === 403) {
1276
+ logger.error(`\u274C Access forbidden: ${responseText}`);
1277
+ throw new Error(
1278
+ `Access denied: You don't have permission to execute agent '${this.agentId}'. Check if the agent exists and you have the necessary permissions.`
1279
+ );
1280
+ } else if (statusCode === 404) {
1281
+ logger.error(`\u274C Agent not found: ${responseText}`);
1282
+ throw new Error(
1283
+ `Agent not found: Agent '${this.agentId}' does not exist or you don't have access to it. Please verify the agent ID and ensure it exists in your account.`
1284
+ );
1285
+ } else if (statusCode === 422) {
1286
+ logger.error(`\u274C Validation error: ${responseText}`);
1287
+ throw new Error(
1288
+ `Request validation failed: ${responseText}. Please check your query parameters and output schema format.`
1289
+ );
1290
+ } else if (statusCode === 500) {
1291
+ logger.error(`\u274C Server error: ${responseText}`);
1292
+ throw new Error(
1293
+ "Internal server error occurred during agent execution. Please try again later or contact support if the issue persists."
1294
+ );
1295
+ } else {
1296
+ logger.error(`\u274C Remote execution failed with status ${statusCode}: ${responseText}`);
1297
+ throw new Error(`Remote agent execution failed: ${statusCode} - ${responseText}`);
1298
+ }
1299
+ }
1300
+ const result = await response.json();
1301
+ logger.info(`\u{1F527} Response: ${JSON.stringify(result)}`);
1302
+ logger.info("\u2705 Remote execution completed successfully");
1303
+ if (typeof result === "object" && result !== null) {
1304
+ if (result.status === "error" || result.error !== null) {
1305
+ const errorMsg = result.error ?? String(result);
1306
+ logger.error(`\u274C Remote agent execution failed: ${errorMsg}`);
1307
+ throw new Error(`Remote agent execution failed: ${errorMsg}`);
1308
+ }
1309
+ if (String(result).includes("failed to initialize")) {
1310
+ logger.error(`\u274C Agent initialization failed: ${result}`);
1311
+ throw new Error(
1312
+ `Agent initialization failed on remote server. This usually indicates:
1313
+ \u2022 Invalid agent configuration (LLM model, system prompt)
1314
+ \u2022 Missing or invalid MCP server configurations
1315
+ \u2022 Network connectivity issues with MCP servers
1316
+ \u2022 Missing environment variables or credentials
1317
+ Raw error: ${result}`
1318
+ );
1319
+ }
1320
+ }
1321
+ if (outputSchema) {
1322
+ return this.parseStructuredResponse(result, outputSchema);
1323
+ }
1324
+ if (typeof result === "object" && result !== null && "result" in result) {
1325
+ return result.result;
1326
+ } else if (typeof result === "string") {
1327
+ return result;
1328
+ } else {
1329
+ return String(result);
1330
+ }
1331
+ } catch (e) {
1332
+ if (e instanceof Error) {
1333
+ if (e.name === "AbortError") {
1334
+ logger.error(`\u274C Remote execution timed out: ${e}`);
1335
+ throw new Error(
1336
+ "Remote agent execution timed out. The server may be overloaded or the query is taking too long to process. Try again or use a simpler query."
1337
+ );
1338
+ }
1339
+ logger.error(`\u274C Remote execution error: ${e}`);
1340
+ throw new Error(`Remote agent execution failed: ${e.message}`);
1341
+ }
1342
+ logger.error(`\u274C Remote execution error: ${e}`);
1343
+ throw new Error(`Remote agent execution failed: ${String(e)}`);
1344
+ }
1345
+ }
1346
+ // eslint-disable-next-line require-yield
1347
+ async *stream(query, maxSteps, manageConnector, externalHistory, outputSchema) {
1348
+ const result = await this.run(query, maxSteps, manageConnector, externalHistory, outputSchema);
1349
+ return result;
1350
+ }
1351
+ async close() {
1352
+ logger.info("\u{1F50C} Remote agent client closed");
1353
+ }
1354
+ };
1355
+
1356
+ // src/agents/mcp_agent.ts
1357
+ var MCPAgent = class {
1358
+ static {
1359
+ __name(this, "MCPAgent");
1360
+ }
1361
+ llm;
1362
+ client;
1363
+ connectors;
1364
+ maxSteps;
1365
+ autoInitialize;
1366
+ memoryEnabled;
1367
+ disallowedTools;
1368
+ additionalTools;
1369
+ useServerManager;
1370
+ verbose;
1371
+ observe;
1372
+ systemPrompt;
1373
+ systemPromptTemplateOverride;
1374
+ additionalInstructions;
1375
+ _initialized = false;
1376
+ conversationHistory = [];
1377
+ _agentExecutor = null;
1378
+ sessions = {};
1379
+ systemMessage = null;
1380
+ _tools = [];
1381
+ adapter;
1382
+ serverManager = null;
1383
+ telemetry;
1384
+ modelProvider;
1385
+ modelName;
1386
+ // Observability support
1387
+ observabilityManager;
1388
+ callbacks = [];
1389
+ metadata = {};
1390
+ tags = [];
1391
+ // Remote agent support
1392
+ isRemote = false;
1393
+ remoteAgent = null;
1394
+ constructor(options) {
1395
+ if (options.agentId) {
1396
+ this.isRemote = true;
1397
+ this.remoteAgent = new RemoteAgent({
1398
+ agentId: options.agentId,
1399
+ apiKey: options.apiKey,
1400
+ baseUrl: options.baseUrl
1401
+ });
1402
+ this.maxSteps = options.maxSteps ?? 5;
1403
+ this.memoryEnabled = options.memoryEnabled ?? true;
1404
+ this.autoInitialize = options.autoInitialize ?? false;
1405
+ this.verbose = options.verbose ?? false;
1406
+ this.observe = options.observe ?? true;
1407
+ this.connectors = [];
1408
+ this.disallowedTools = [];
1409
+ this.additionalTools = [];
1410
+ this.useServerManager = false;
1411
+ this.adapter = new LangChainAdapter();
1412
+ this.telemetry = Telemetry.getInstance();
1413
+ this.modelProvider = "remote";
1414
+ this.modelName = "remote-agent";
1415
+ this.observabilityManager = new ObservabilityManager({
1416
+ customCallbacks: options.callbacks,
1417
+ agentId: options.agentId
1418
+ });
1419
+ this.callbacks = [];
1420
+ return;
1421
+ }
1422
+ if (!options.llm) {
1423
+ throw new Error("llm is required for local execution. For remote execution, provide agentId instead.");
1424
+ }
1425
+ this.llm = options.llm;
1426
+ this.client = options.client;
1427
+ this.connectors = options.connectors ?? [];
1428
+ this.maxSteps = options.maxSteps ?? 5;
1429
+ this.autoInitialize = options.autoInitialize ?? false;
1430
+ this.memoryEnabled = options.memoryEnabled ?? true;
1431
+ this.systemPrompt = options.systemPrompt ?? null;
1432
+ this.systemPromptTemplateOverride = options.systemPromptTemplate ?? null;
1433
+ this.additionalInstructions = options.additionalInstructions ?? null;
1434
+ this.disallowedTools = options.disallowedTools ?? [];
1435
+ this.additionalTools = options.additionalTools ?? [];
1436
+ this.useServerManager = options.useServerManager ?? false;
1437
+ this.verbose = options.verbose ?? false;
1438
+ this.observe = options.observe ?? true;
1439
+ if (!this.client && this.connectors.length === 0) {
1440
+ throw new Error("Either 'client' or at least one 'connector' must be provided.");
1441
+ }
1442
+ if (this.useServerManager) {
1443
+ if (!this.client) {
1444
+ throw new Error("'client' must be provided when 'useServerManager' is true.");
1445
+ }
1446
+ this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
1447
+ this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
1448
+ } else {
1449
+ this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
1450
+ }
1451
+ this.telemetry = Telemetry.getInstance();
1452
+ if (this.llm) {
1453
+ const [provider, name] = extractModelInfo(this.llm);
1454
+ this.modelProvider = provider;
1455
+ this.modelName = name;
1456
+ } else {
1457
+ this.modelProvider = "unknown";
1458
+ this.modelName = "unknown";
1459
+ }
1460
+ this.observabilityManager = new ObservabilityManager({
1461
+ customCallbacks: options.callbacks,
1462
+ verbose: this.verbose,
1463
+ observe: this.observe,
1464
+ agentId: options.agentId,
1465
+ metadataProvider: /* @__PURE__ */ __name(() => this.getMetadata(), "metadataProvider"),
1466
+ tagsProvider: /* @__PURE__ */ __name(() => this.getTags(), "tagsProvider")
1467
+ });
1468
+ Object.defineProperty(this, "agentExecutor", {
1469
+ get: /* @__PURE__ */ __name(() => this._agentExecutor, "get"),
1470
+ configurable: true
1471
+ });
1472
+ Object.defineProperty(this, "tools", {
1473
+ get: /* @__PURE__ */ __name(() => this._tools, "get"),
1474
+ configurable: true
1475
+ });
1476
+ Object.defineProperty(this, "initialized", {
1477
+ get: /* @__PURE__ */ __name(() => this._initialized, "get"),
1478
+ configurable: true
1479
+ });
1480
+ }
1481
+ async initialize() {
1482
+ if (this.isRemote) {
1483
+ this._initialized = true;
1484
+ return;
1485
+ }
1486
+ logger.info("\u{1F680} Initializing MCP agent and connecting to services...");
1487
+ this.callbacks = await this.observabilityManager.getCallbacks();
1488
+ const handlerNames = await this.observabilityManager.getHandlerNames();
1489
+ if (handlerNames.length > 0) {
1490
+ logger.info(`\u{1F4CA} Observability enabled with: ${handlerNames.join(", ")}`);
1491
+ }
1492
+ if (this.useServerManager && this.serverManager) {
1493
+ await this.serverManager.initialize();
1494
+ const managementTools = this.serverManager.tools;
1495
+ this._tools = managementTools;
1496
+ this._tools.push(...this.additionalTools);
1497
+ logger.info(
1498
+ `\u{1F527} Server manager mode active with ${managementTools.length} management tools`
1499
+ );
1500
+ await this.createSystemMessageFromTools(this._tools);
1501
+ } else {
1502
+ if (this.client) {
1503
+ this.sessions = this.client.getAllActiveSessions();
1504
+ logger.info(`\u{1F50C} Found ${Object.keys(this.sessions).length} existing sessions`);
1505
+ if (Object.keys(this.sessions).length === 0) {
1506
+ logger.info("\u{1F504} No active sessions found, creating new ones...");
1507
+ this.sessions = await this.client.createAllSessions();
1508
+ logger.info(`\u2705 Created ${Object.keys(this.sessions).length} new sessions`);
1509
+ }
1510
+ this._tools = await LangChainAdapter.createTools(this.client);
1511
+ this._tools.push(...this.additionalTools);
1512
+ logger.info(`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain tools from client`);
1513
+ } else {
1514
+ logger.info(`\u{1F517} Connecting to ${this.connectors.length} direct connectors...`);
1515
+ for (const connector of this.connectors) {
1516
+ if (!connector.isClientConnected) {
1517
+ await connector.connect();
1518
+ }
1519
+ }
1520
+ this._tools = await this.adapter.createToolsFromConnectors(this.connectors);
1521
+ this._tools.push(...this.additionalTools);
1522
+ logger.info(`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain tools from connectors`);
1523
+ }
1524
+ logger.info(`\u{1F9F0} Found ${this._tools.length} tools across all connectors`);
1525
+ await this.createSystemMessageFromTools(this._tools);
1526
+ }
1527
+ this._agentExecutor = this.createAgent();
1528
+ this._initialized = true;
1529
+ const mcpServerInfo = this.getMCPServerInfo();
1530
+ if (Object.keys(mcpServerInfo).length > 0) {
1531
+ this.setMetadata(mcpServerInfo);
1532
+ logger.debug(`MCP server info added to metadata: ${JSON.stringify(mcpServerInfo)}`);
1533
+ }
1534
+ logger.info("\u2728 Agent initialization complete");
1535
+ }
1536
+ async createSystemMessageFromTools(tools) {
1537
+ const systemPromptTemplate = this.systemPromptTemplateOverride ?? DEFAULT_SYSTEM_PROMPT_TEMPLATE;
1538
+ this.systemMessage = createSystemMessage(
1539
+ tools,
1540
+ systemPromptTemplate,
1541
+ SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE,
1542
+ this.useServerManager,
1543
+ this.disallowedTools,
1544
+ this.systemPrompt ?? void 0,
1545
+ this.additionalInstructions ?? void 0
1546
+ );
1547
+ if (this.memoryEnabled) {
1548
+ this.conversationHistory = [
1549
+ this.systemMessage,
1550
+ ...this.conversationHistory.filter((m) => !(m instanceof SystemMessage2))
1551
+ ];
1552
+ }
1553
+ }
1554
+ createAgent() {
1555
+ if (!this.llm) {
1556
+ throw new Error("LLM is required to create agent");
1557
+ }
1558
+ const systemContent = this.systemMessage?.content ?? "You are a helpful assistant.";
1559
+ const prompt = ChatPromptTemplate.fromMessages([
1560
+ ["system", systemContent],
1561
+ new MessagesPlaceholder("chat_history"),
1562
+ ["human", "{input}"],
1563
+ new MessagesPlaceholder("agent_scratchpad")
1564
+ ]);
1565
+ const agent = createToolCallingAgent({
1566
+ llm: this.llm,
1567
+ tools: this._tools,
1568
+ prompt
1569
+ });
1570
+ return new AgentExecutor({
1571
+ agent,
1572
+ tools: this._tools,
1573
+ maxIterations: this.maxSteps,
1574
+ verbose: this.verbose,
1575
+ returnIntermediateSteps: true,
1576
+ callbacks: this.callbacks
1577
+ });
1578
+ }
1579
+ getConversationHistory() {
1580
+ return [...this.conversationHistory];
1581
+ }
1582
+ clearConversationHistory() {
1583
+ this.conversationHistory = this.memoryEnabled && this.systemMessage ? [this.systemMessage] : [];
1584
+ }
1585
+ addToHistory(message) {
1586
+ if (this.memoryEnabled)
1587
+ this.conversationHistory.push(message);
1588
+ }
1589
+ getSystemMessage() {
1590
+ return this.systemMessage;
1591
+ }
1592
+ setSystemMessage(message) {
1593
+ this.systemMessage = new SystemMessage2(message);
1594
+ if (this.memoryEnabled) {
1595
+ this.conversationHistory = this.conversationHistory.filter((m) => !(m instanceof SystemMessage2));
1596
+ this.conversationHistory.unshift(this.systemMessage);
1597
+ }
1598
+ if (this._initialized && this._tools.length) {
1599
+ this._agentExecutor = this.createAgent();
1600
+ logger.debug("Agent recreated with new system message");
1601
+ }
1602
+ }
1603
+ setDisallowedTools(disallowedTools) {
1604
+ this.disallowedTools = disallowedTools;
1605
+ this.adapter = new LangChainAdapter(this.disallowedTools);
1606
+ if (this._initialized) {
1607
+ logger.debug("Agent already initialized. Changes will take effect on next initialization.");
1608
+ }
1609
+ }
1610
+ getDisallowedTools() {
1611
+ return this.disallowedTools;
1612
+ }
1613
+ /**
1614
+ * Set metadata for observability traces
1615
+ * @param newMetadata - Key-value pairs to add to metadata. Keys should be strings, values should be serializable.
1616
+ */
1617
+ setMetadata(newMetadata) {
1618
+ const sanitizedMetadata = this.sanitizeMetadata(newMetadata);
1619
+ this.metadata = { ...this.metadata, ...sanitizedMetadata };
1620
+ logger.debug(`Metadata set: ${JSON.stringify(this.metadata)}`);
1621
+ }
1622
+ /**
1623
+ * Get current metadata
1624
+ * @returns A copy of the current metadata object
1625
+ */
1626
+ getMetadata() {
1627
+ return { ...this.metadata };
1628
+ }
1629
+ /**
1630
+ * Set tags for observability traces
1631
+ * @param newTags - Array of tag strings to add. Duplicates will be automatically removed.
1632
+ */
1633
+ setTags(newTags) {
1634
+ const sanitizedTags = this.sanitizeTags(newTags);
1635
+ this.tags = [.../* @__PURE__ */ new Set([...this.tags, ...sanitizedTags])];
1636
+ logger.debug(`Tags set: ${JSON.stringify(this.tags)}`);
1637
+ }
1638
+ /**
1639
+ * Get current tags
1640
+ * @returns A copy of the current tags array
1641
+ */
1642
+ getTags() {
1643
+ return [...this.tags];
1644
+ }
1645
+ /**
1646
+ * Sanitize metadata to ensure compatibility with observability platforms
1647
+ * @param metadata - Raw metadata object
1648
+ * @returns Sanitized metadata object
1649
+ */
1650
+ sanitizeMetadata(metadata) {
1651
+ const sanitized = {};
1652
+ for (const [key, value] of Object.entries(metadata)) {
1653
+ if (typeof key !== "string" || key.length === 0) {
1654
+ logger.warn(`Invalid metadata key: ${key}. Skipping.`);
1655
+ continue;
1656
+ }
1657
+ const sanitizedKey = key.replace(/[^\w-]/g, "_");
1658
+ if (value === null || value === void 0) {
1659
+ sanitized[sanitizedKey] = value;
1660
+ } else if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1661
+ sanitized[sanitizedKey] = value;
1662
+ } else if (Array.isArray(value)) {
1663
+ const sanitizedArray = value.filter(
1664
+ (item) => typeof item === "string" || typeof item === "number" || typeof item === "boolean"
1665
+ );
1666
+ if (sanitizedArray.length > 0) {
1667
+ sanitized[sanitizedKey] = sanitizedArray;
1668
+ }
1669
+ } else if (typeof value === "object") {
1670
+ try {
1671
+ const serialized = JSON.stringify(value);
1672
+ if (serialized.length > 1e3) {
1673
+ logger.warn(`Metadata value for key '${sanitizedKey}' is too large. Truncating.`);
1674
+ sanitized[sanitizedKey] = `${serialized.substring(0, 1e3)}...`;
1675
+ } else {
1676
+ sanitized[sanitizedKey] = value;
1677
+ }
1678
+ } catch (error) {
1679
+ logger.warn(`Failed to serialize metadata value for key '${sanitizedKey}': ${error}. Skipping.`);
1680
+ }
1681
+ } else {
1682
+ logger.warn(`Unsupported metadata value type for key '${sanitizedKey}': ${typeof value}. Skipping.`);
1683
+ }
1684
+ }
1685
+ return sanitized;
1686
+ }
1687
+ /**
1688
+ * Sanitize tags to ensure compatibility with observability platforms
1689
+ * @param tags - Array of tag strings
1690
+ * @returns Array of sanitized tag strings
1691
+ */
1692
+ sanitizeTags(tags) {
1693
+ return tags.filter((tag) => typeof tag === "string" && tag.length > 0).map((tag) => tag.replace(/[^\w:-]/g, "_")).filter((tag) => tag.length <= 50);
1694
+ }
1695
+ /**
1696
+ * Get MCP server information for observability metadata
1697
+ */
1698
+ getMCPServerInfo() {
1699
+ const serverInfo = {};
1700
+ try {
1701
+ if (this.client) {
1702
+ const serverNames = this.client.getServerNames();
1703
+ serverInfo.mcp_servers_count = serverNames.length;
1704
+ serverInfo.mcp_server_names = serverNames;
1705
+ const serverConfigs = {};
1706
+ for (const serverName of serverNames) {
1707
+ try {
1708
+ const config = this.client.getServerConfig(serverName);
1709
+ if (config) {
1710
+ let serverType = "unknown";
1711
+ if (config.command) {
1712
+ serverType = "command";
1713
+ } else if (config.url) {
1714
+ serverType = "http";
1715
+ } else if (config.ws_url) {
1716
+ serverType = "websocket";
1717
+ }
1718
+ serverConfigs[serverName] = {
1719
+ type: serverType,
1720
+ // Include safe configuration details (avoid sensitive data)
1721
+ has_args: !!config.args,
1722
+ has_env: !!config.env,
1723
+ has_headers: !!config.headers,
1724
+ url: config.url || null,
1725
+ command: config.command || null
1726
+ };
1727
+ }
1728
+ } catch (error) {
1729
+ logger.warn(`Failed to get config for server '${serverName}': ${error}`);
1730
+ serverConfigs[serverName] = { type: "error", error: "config_unavailable" };
1731
+ }
1732
+ }
1733
+ serverInfo.mcp_server_configs = serverConfigs;
1734
+ } else if (this.connectors && this.connectors.length > 0) {
1735
+ serverInfo.mcp_servers_count = this.connectors.length;
1736
+ serverInfo.mcp_server_names = this.connectors.map((c) => c.publicIdentifier);
1737
+ serverInfo.mcp_server_types = this.connectors.map((c) => c.constructor.name);
1738
+ }
1739
+ } catch (error) {
1740
+ logger.warn(`Failed to collect MCP server info: ${error}`);
1741
+ serverInfo.error = "collection_failed";
1742
+ }
1743
+ return serverInfo;
1744
+ }
1745
+ async _consumeAndReturn(generator) {
1746
+ while (true) {
1747
+ const { done, value } = await generator.next();
1748
+ if (done) {
1749
+ return value;
1750
+ }
1751
+ }
1752
+ }
1753
+ async run(query, maxSteps, manageConnector, externalHistory, outputSchema) {
1754
+ if (this.isRemote && this.remoteAgent) {
1755
+ return this.remoteAgent.run(query, maxSteps, manageConnector, externalHistory, outputSchema);
1756
+ }
1757
+ const generator = this.stream(
1758
+ query,
1759
+ maxSteps,
1760
+ manageConnector,
1761
+ externalHistory,
1762
+ outputSchema
1763
+ );
1764
+ return this._consumeAndReturn(generator);
1765
+ }
1766
+ /**
1767
+ * Runs the agent and yields intermediate steps as an async generator.
1768
+ * If outputSchema is provided, returns structured output of type T.
1769
+ */
1770
+ async *stream(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
1771
+ if (this.isRemote && this.remoteAgent) {
1772
+ const result2 = await this.remoteAgent.run(query, maxSteps, manageConnector, externalHistory, outputSchema);
1773
+ return result2;
1774
+ }
1775
+ let result = "";
1776
+ let initializedHere = false;
1777
+ const startTime = Date.now();
1778
+ const toolsUsedNames = [];
1779
+ let stepsTaken = 0;
1780
+ let success = false;
1781
+ let structuredLlm = null;
1782
+ let schemaDescription = "";
1783
+ if (outputSchema) {
1784
+ query = this._enhanceQueryWithSchema(query, outputSchema);
1785
+ logger.debug(`\u{1F504} Structured output requested, schema: ${JSON.stringify(zodToJsonSchema2(outputSchema), null, 2)}`);
1786
+ if (this.llm && "withStructuredOutput" in this.llm && typeof this.llm.withStructuredOutput === "function") {
1787
+ structuredLlm = this.llm.withStructuredOutput(outputSchema);
1788
+ } else if (this.llm) {
1789
+ structuredLlm = this.llm;
1790
+ } else {
1791
+ throw new Error("LLM is required for structured output");
1792
+ }
1793
+ schemaDescription = JSON.stringify(zodToJsonSchema2(outputSchema), null, 2);
1794
+ }
1795
+ try {
1796
+ if (manageConnector && !this._initialized) {
1797
+ await this.initialize();
1798
+ initializedHere = true;
1799
+ } else if (!this._initialized && this.autoInitialize) {
1800
+ await this.initialize();
1801
+ initializedHere = true;
1802
+ }
1803
+ if (!this._agentExecutor) {
1804
+ throw new Error("MCP agent failed to initialize");
1805
+ }
1806
+ const steps = maxSteps ?? this.maxSteps;
1807
+ this._agentExecutor.maxIterations = steps;
1808
+ const display_query = query.length > 50 ? `${query.slice(0, 50).replace(/\n/g, " ")}...` : query.replace(/\n/g, " ");
1809
+ logger.info(`\u{1F4AC} Received query: '${display_query}'`);
1810
+ if (this.memoryEnabled) {
1811
+ this.addToHistory(new HumanMessage(query));
1812
+ }
1813
+ const historyToUse = externalHistory ?? this.conversationHistory;
1814
+ const langchainHistory = [];
1815
+ for (const msg of historyToUse) {
1816
+ if (msg instanceof HumanMessage || msg instanceof AIMessage) {
1817
+ langchainHistory.push(msg);
1818
+ }
1819
+ }
1820
+ const intermediateSteps = [];
1821
+ const inputs = { input: query, chat_history: langchainHistory };
1822
+ let nameToToolMap = Object.fromEntries(this._tools.map((t) => [t.name, t]));
1823
+ logger.info(`\u{1F3C1} Starting agent execution with max_steps=${steps}`);
1824
+ let runManager;
1825
+ if (this.callbacks?.length > 0) {
1826
+ const callbackManager = new CallbackManager(void 0, {
1827
+ handlers: this.callbacks,
1828
+ inheritableHandlers: this.callbacks
1829
+ });
1830
+ runManager = await callbackManager.handleChainStart({
1831
+ name: "MCPAgent (mcp-use)",
1832
+ id: ["MCPAgent (mcp-use)"],
1833
+ lc: 1,
1834
+ type: "not_implemented"
1835
+ }, inputs);
1836
+ }
1837
+ for (let stepNum = 0; stepNum < steps; stepNum++) {
1838
+ stepsTaken = stepNum + 1;
1839
+ if (this.useServerManager && this.serverManager) {
1840
+ const currentTools = this.serverManager.tools;
1841
+ const currentToolNames = new Set(currentTools.map((t) => t.name));
1842
+ const existingToolNames = new Set(this._tools.map((t) => t.name));
1843
+ const changed = currentTools.length !== this._tools.length || [...currentToolNames].some((n) => !existingToolNames.has(n));
1844
+ if (changed) {
1845
+ logger.info(
1846
+ `\u{1F504} Tools changed before step ${stepNum + 1}, updating agent. New tools: ${[...currentToolNames].join(", ")}`
1847
+ );
1848
+ this._tools = currentTools;
1849
+ this._tools.push(...this.additionalTools);
1850
+ await this.createSystemMessageFromTools(this._tools);
1851
+ this._agentExecutor = this.createAgent();
1852
+ this._agentExecutor.maxIterations = steps;
1853
+ nameToToolMap = Object.fromEntries(this._tools.map((t) => [t.name, t]));
1854
+ }
1855
+ }
1856
+ logger.info(`\u{1F463} Step ${stepNum + 1}/${steps}`);
1857
+ try {
1858
+ logger.debug("Starting agent step execution");
1859
+ const nextStepOutput = await this._agentExecutor._takeNextStep(
1860
+ nameToToolMap,
1861
+ inputs,
1862
+ intermediateSteps,
1863
+ runManager
1864
+ );
1865
+ if ("returnValues" in nextStepOutput) {
1866
+ logger.info(`\u2705 Agent finished at step ${stepNum + 1}`);
1867
+ result = nextStepOutput.returnValues?.output ?? "No output generated";
1868
+ runManager?.handleChainEnd({ output: result });
1869
+ if (outputSchema && structuredLlm) {
1870
+ try {
1871
+ logger.info("\u{1F527} Attempting structured output...");
1872
+ const structuredResult = await this._attemptStructuredOutput(
1873
+ result,
1874
+ structuredLlm,
1875
+ outputSchema,
1876
+ schemaDescription
1877
+ );
1878
+ logger.debug(`\u{1F504} Structured result: ${JSON.stringify(structuredResult)}`);
1879
+ if (this.memoryEnabled) {
1880
+ this.addToHistory(new AIMessage(`Structured result: ${JSON.stringify(structuredResult)}`));
1881
+ }
1882
+ logger.info("\u2705 Structured output successful");
1883
+ success = true;
1884
+ return structuredResult;
1885
+ } catch (e) {
1886
+ logger.warn(`\u26A0\uFE0F Structured output failed: ${e}`);
1887
+ const failedStructuredOutputPrompt = `
1888
+ The current result cannot be formatted into the required structure.
1889
+ Error: ${String(e)}
1890
+
1891
+ Current information: ${result}
1892
+
1893
+ If information is missing, please continue working to gather the missing information needed for:
1894
+ ${schemaDescription}
1895
+
1896
+ If the information is complete, please return the result in the required structure.
1897
+ `;
1898
+ inputs.input = failedStructuredOutputPrompt;
1899
+ if (this.memoryEnabled) {
1900
+ this.addToHistory(new HumanMessage(failedStructuredOutputPrompt));
1901
+ }
1902
+ logger.info("\u{1F504} Continuing execution to gather missing information...");
1903
+ continue;
1904
+ }
1905
+ } else {
1906
+ break;
1907
+ }
1908
+ }
1909
+ const stepArray = nextStepOutput;
1910
+ intermediateSteps.push(...stepArray);
1911
+ for (const step of stepArray) {
1912
+ yield step;
1913
+ const { action, observation } = step;
1914
+ const toolName = action.tool;
1915
+ toolsUsedNames.push(toolName);
1916
+ let toolInputStr = typeof action.toolInput === "string" ? action.toolInput : JSON.stringify(action.toolInput, null, 2);
1917
+ if (toolInputStr.length > 100)
1918
+ toolInputStr = `${toolInputStr.slice(0, 97)}...`;
1919
+ logger.info(`\u{1F527} Tool call: ${toolName} with input: ${toolInputStr}`);
1920
+ let outputStr = String(observation);
1921
+ if (outputStr.length > 100)
1922
+ outputStr = `${outputStr.slice(0, 97)}...`;
1923
+ outputStr = outputStr.replace(/\n/g, " ");
1924
+ logger.info(`\u{1F4C4} Tool result: ${outputStr}`);
1925
+ }
1926
+ if (stepArray.length) {
1927
+ const lastStep = stepArray[stepArray.length - 1];
1928
+ const toolReturn = await this._agentExecutor._getToolReturn(lastStep);
1929
+ if (toolReturn) {
1930
+ logger.info(`\u{1F3C6} Tool returned directly at step ${stepNum + 1}`);
1931
+ result = toolReturn.returnValues?.output ?? "No output generated";
1932
+ break;
1933
+ }
1934
+ }
1935
+ } catch (e) {
1936
+ if (e instanceof OutputParserException) {
1937
+ logger.error(`\u274C Output parsing error during step ${stepNum + 1}: ${e}`);
1938
+ result = `Agent stopped due to a parsing error: ${e}`;
1939
+ runManager?.handleChainError(result);
1940
+ break;
1941
+ }
1942
+ logger.error(`\u274C Error during agent execution step ${stepNum + 1}: ${e}`);
1943
+ console.error(e);
1944
+ result = `Agent stopped due to an error: ${e}`;
1945
+ runManager?.handleChainError(result);
1946
+ break;
1947
+ }
1948
+ }
1949
+ if (!result) {
1950
+ logger.warn(`\u26A0\uFE0F Agent stopped after reaching max iterations (${steps})`);
1951
+ result = `Agent stopped after reaching the maximum number of steps (${steps}).`;
1952
+ runManager?.handleChainEnd({ output: result });
1953
+ }
1954
+ logger.info("\u{1F389} Agent execution complete");
1955
+ success = true;
1956
+ return result;
1957
+ } catch (e) {
1958
+ logger.error(`\u274C Error running query: ${e}`);
1959
+ if (initializedHere && manageConnector) {
1960
+ logger.info("\u{1F9F9} Cleaning up resources after initialization error in run");
1961
+ await this.close();
1962
+ }
1963
+ throw e;
1964
+ } finally {
1965
+ const executionTimeMs = Date.now() - startTime;
1966
+ let serverCount = 0;
1967
+ if (this.client) {
1968
+ serverCount = Object.keys(this.client.getAllActiveSessions()).length;
1969
+ } else if (this.connectors) {
1970
+ serverCount = this.connectors.length;
1971
+ }
1972
+ const conversationHistoryLength = this.memoryEnabled ? this.conversationHistory.length : 0;
1973
+ await this.telemetry.trackAgentExecution({
1974
+ executionMethod: "stream",
1975
+ query,
1976
+ success,
1977
+ modelProvider: this.modelProvider,
1978
+ modelName: this.modelName,
1979
+ serverCount,
1980
+ serverIdentifiers: this.connectors.map((connector) => connector.publicIdentifier),
1981
+ totalToolsAvailable: this._tools.length,
1982
+ toolsAvailableNames: this._tools.map((t) => t.name),
1983
+ maxStepsConfigured: this.maxSteps,
1984
+ memoryEnabled: this.memoryEnabled,
1985
+ useServerManager: this.useServerManager,
1986
+ maxStepsUsed: maxSteps ?? null,
1987
+ manageConnector,
1988
+ externalHistoryUsed: externalHistory !== void 0,
1989
+ stepsTaken,
1990
+ toolsUsedCount: toolsUsedNames.length,
1991
+ toolsUsedNames,
1992
+ response: result,
1993
+ executionTimeMs,
1994
+ errorType: success ? null : "execution_error",
1995
+ conversationHistoryLength
1996
+ });
1997
+ if (manageConnector && !this.client && initializedHere) {
1998
+ logger.info("\u{1F9F9} Closing agent after query completion");
1999
+ await this.close();
2000
+ }
2001
+ }
2002
+ }
2003
+ async close() {
2004
+ if (this.isRemote && this.remoteAgent) {
2005
+ await this.remoteAgent.close();
2006
+ return;
2007
+ }
2008
+ logger.info("\u{1F50C} Closing MCPAgent resources\u2026");
2009
+ await this.observabilityManager.shutdown();
2010
+ try {
2011
+ this._agentExecutor = null;
2012
+ this._tools = [];
2013
+ if (this.client) {
2014
+ logger.info("\u{1F504} Closing sessions through client");
2015
+ await this.client.closeAllSessions();
2016
+ this.sessions = {};
2017
+ } else {
2018
+ for (const connector of this.connectors) {
2019
+ logger.info("\u{1F504} Disconnecting connector");
2020
+ await connector.disconnect();
2021
+ }
2022
+ }
2023
+ if ("connectorToolMap" in this.adapter) {
2024
+ this.adapter = new LangChainAdapter();
2025
+ }
2026
+ } finally {
2027
+ this._initialized = false;
2028
+ logger.info("\u{1F44B} Agent closed successfully");
2029
+ }
2030
+ }
2031
+ /**
2032
+ * Yields LangChain StreamEvent objects from the underlying streamEvents() method.
2033
+ * This provides token-level streaming and fine-grained event updates.
2034
+ */
2035
+ async *streamEvents(query, maxSteps, manageConnector = true, externalHistory) {
2036
+ let initializedHere = false;
2037
+ const startTime = Date.now();
2038
+ let success = false;
2039
+ let eventCount = 0;
2040
+ let totalResponseLength = 0;
2041
+ let finalResponse = "";
2042
+ try {
2043
+ if (manageConnector && !this._initialized) {
2044
+ await this.initialize();
2045
+ initializedHere = true;
2046
+ } else if (!this._initialized && this.autoInitialize) {
2047
+ await this.initialize();
2048
+ initializedHere = true;
2049
+ }
2050
+ const agentExecutor = this.agentExecutor;
2051
+ if (!agentExecutor) {
2052
+ throw new Error("MCP agent failed to initialize");
2053
+ }
2054
+ const steps = maxSteps ?? this.maxSteps;
2055
+ agentExecutor.maxIterations = steps;
2056
+ const display_query = query.length > 50 ? `${query.slice(0, 50).replace(/\n/g, " ")}...` : query.replace(/\n/g, " ");
2057
+ logger.info(`\u{1F4AC} Received query for streamEvents: '${display_query}'`);
2058
+ if (this.memoryEnabled) {
2059
+ logger.info(`\u{1F504} Adding user message to history: ${query}`);
2060
+ this.addToHistory(new HumanMessage(query));
2061
+ }
2062
+ const historyToUse = externalHistory ?? this.conversationHistory;
2063
+ const langchainHistory = [];
2064
+ for (const msg of historyToUse) {
2065
+ if (msg instanceof HumanMessage || msg instanceof AIMessage || msg instanceof ToolMessage) {
2066
+ langchainHistory.push(msg);
2067
+ } else {
2068
+ logger.info(`\u26A0\uFE0F Skipped message of type: ${msg.constructor.name}`);
2069
+ }
2070
+ }
2071
+ const inputs = { input: query, chat_history: langchainHistory };
2072
+ logger.info("callbacks", this.callbacks);
2073
+ const eventStream = agentExecutor.streamEvents(
2074
+ inputs,
2075
+ {
2076
+ version: "v2",
2077
+ callbacks: this.callbacks.length > 0 ? this.callbacks : void 0
2078
+ }
2079
+ );
2080
+ for await (const event of eventStream) {
2081
+ eventCount++;
2082
+ if (!event || typeof event !== "object") {
2083
+ continue;
2084
+ }
2085
+ if (event.event === "on_chat_model_stream" && event.data?.chunk?.content) {
2086
+ totalResponseLength += event.data.chunk.content.length;
2087
+ }
2088
+ yield event;
2089
+ if (event.event === "on_chain_end" && event.data?.output) {
2090
+ const output = event.data.output;
2091
+ if (Array.isArray(output) && output.length > 0 && output[0]?.text) {
2092
+ finalResponse = output[0].text;
2093
+ }
2094
+ }
2095
+ }
2096
+ if (this.memoryEnabled && finalResponse) {
2097
+ this.addToHistory(new AIMessage(finalResponse));
2098
+ }
2099
+ logger.info(`\u{1F389} StreamEvents complete - ${eventCount} events emitted`);
2100
+ success = true;
2101
+ } catch (e) {
2102
+ logger.error(`\u274C Error during streamEvents: ${e}`);
2103
+ if (initializedHere && manageConnector) {
2104
+ logger.info("\u{1F9F9} Cleaning up resources after initialization error in streamEvents");
2105
+ await this.close();
2106
+ }
2107
+ throw e;
2108
+ } finally {
2109
+ const executionTimeMs = Date.now() - startTime;
2110
+ let serverCount = 0;
2111
+ if (this.client) {
2112
+ serverCount = Object.keys(this.client.getAllActiveSessions()).length;
2113
+ } else if (this.connectors) {
2114
+ serverCount = this.connectors.length;
2115
+ }
2116
+ const conversationHistoryLength = this.memoryEnabled ? this.conversationHistory.length : 0;
2117
+ await this.telemetry.trackAgentExecution({
2118
+ executionMethod: "streamEvents",
2119
+ query,
2120
+ success,
2121
+ modelProvider: this.modelProvider,
2122
+ modelName: this.modelName,
2123
+ serverCount,
2124
+ serverIdentifiers: this.connectors.map((connector) => connector.publicIdentifier),
2125
+ totalToolsAvailable: this._tools.length,
2126
+ toolsAvailableNames: this._tools.map((t) => t.name),
2127
+ maxStepsConfigured: this.maxSteps,
2128
+ memoryEnabled: this.memoryEnabled,
2129
+ useServerManager: this.useServerManager,
2130
+ maxStepsUsed: maxSteps ?? null,
2131
+ manageConnector,
2132
+ externalHistoryUsed: externalHistory !== void 0,
2133
+ response: `[STREAMED RESPONSE - ${totalResponseLength} chars]`,
2134
+ executionTimeMs,
2135
+ errorType: success ? null : "streaming_error",
2136
+ conversationHistoryLength
2137
+ });
2138
+ if (manageConnector && !this.client && initializedHere) {
2139
+ logger.info("\u{1F9F9} Closing agent after streamEvents completion");
2140
+ await this.close();
2141
+ }
2142
+ }
2143
+ }
2144
+ /**
2145
+ * Attempt to create structured output from raw result with validation and retry logic.
2146
+ */
2147
+ async _attemptStructuredOutput(rawResult, structuredLlm, outputSchema, schemaDescription) {
2148
+ logger.info(`\u{1F504} Attempting structured output with schema: ${outputSchema}`);
2149
+ logger.info(`\u{1F504} Schema description: ${schemaDescription}`);
2150
+ logger.info(`\u{1F504} Raw result: ${JSON.stringify(rawResult, null, 2)}`);
2151
+ let textContent = "";
2152
+ if (typeof rawResult === "string") {
2153
+ textContent = rawResult;
2154
+ } else if (rawResult && typeof rawResult === "object") {
2155
+ textContent = JSON.stringify(rawResult);
2156
+ }
2157
+ if (!textContent) {
2158
+ textContent = JSON.stringify(rawResult);
2159
+ }
2160
+ const maxRetries = 3;
2161
+ let lastError = "";
2162
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
2163
+ logger.info(`\u{1F504} Structured output attempt ${attempt}/${maxRetries}`);
2164
+ let formatPrompt = `
2165
+ Please format the following information according to the EXACT schema specified below.
2166
+ You must use the exact field names and types as shown in the schema.
2167
+
2168
+ Required schema format:
2169
+ ${schemaDescription}
2170
+
2171
+ Content to extract from:
2172
+ ${textContent}
2173
+
2174
+ IMPORTANT:
2175
+ - Use ONLY the field names specified in the schema
2176
+ - Match the data types exactly (string, number, boolean, array, etc.)
2177
+ - Include ALL required fields
2178
+ - Return valid JSON that matches the schema structure exactly
2179
+ `;
2180
+ if (attempt > 1) {
2181
+ formatPrompt += `
2182
+
2183
+ PREVIOUS ATTEMPT FAILED with error: ${lastError}
2184
+ Please fix the issues mentioned above and ensure the output matches the schema exactly.
2185
+ `;
2186
+ }
2187
+ try {
2188
+ const structuredResult = await structuredLlm.invoke(formatPrompt);
2189
+ logger.info(`\u{1F504} Structured result attempt ${attempt}: ${JSON.stringify(structuredResult, null, 2)}`);
2190
+ const validatedResult = this._validateStructuredResult(structuredResult, outputSchema);
2191
+ logger.info(`\u2705 Structured output successful on attempt ${attempt}`);
2192
+ return validatedResult;
2193
+ } catch (e) {
2194
+ lastError = e instanceof Error ? e.message : String(e);
2195
+ logger.warn(`\u26A0\uFE0F Structured output attempt ${attempt} failed: ${lastError}`);
2196
+ if (attempt === maxRetries) {
2197
+ logger.error(`\u274C All ${maxRetries} structured output attempts failed`);
2198
+ throw new Error(`Failed to generate valid structured output after ${maxRetries} attempts. Last error: ${lastError}`);
2199
+ }
2200
+ continue;
2201
+ }
2202
+ }
2203
+ throw new Error("Unexpected error in structured output generation");
2204
+ }
2205
+ /**
2206
+ * Validate the structured result against the schema with detailed error reporting
2207
+ */
2208
+ _validateStructuredResult(structuredResult, outputSchema) {
2209
+ try {
2210
+ const validatedResult = outputSchema.parse(structuredResult);
2211
+ const schemaType = outputSchema;
2212
+ if (schemaType._def && schemaType._def.shape) {
2213
+ for (const [fieldName, fieldSchema] of Object.entries(schemaType._def.shape)) {
2214
+ const field = fieldSchema;
2215
+ const isOptional = field.isOptional?.() ?? field._def?.typeName === "ZodOptional";
2216
+ const isNullable = field.isNullable?.() ?? field._def?.typeName === "ZodNullable";
2217
+ if (!isOptional && !isNullable) {
2218
+ const value = validatedResult[fieldName];
2219
+ if (value === null || value === void 0 || typeof value === "string" && !value.trim() || Array.isArray(value) && value.length === 0) {
2220
+ throw new Error(`Required field '${fieldName}' is missing or empty`);
2221
+ }
2222
+ }
2223
+ }
2224
+ }
2225
+ return validatedResult;
2226
+ } catch (e) {
2227
+ logger.debug(`Validation details: ${e}`);
2228
+ throw e;
2229
+ }
2230
+ }
2231
+ /**
2232
+ * Enhance the query with schema information to make the agent aware of required fields.
2233
+ */
2234
+ _enhanceQueryWithSchema(query, outputSchema) {
2235
+ try {
2236
+ const schemaDescription = JSON.stringify(zodToJsonSchema2(outputSchema), null, 2);
2237
+ const enhancedQuery = `
2238
+ ${query}
2239
+
2240
+ IMPORTANT: Your response must include sufficient information to populate the following structured output:
2241
+
2242
+ ${schemaDescription}
2243
+
2244
+ Make sure you gather ALL the required information during your task execution.
2245
+ If any required information is missing, continue working to find it.
2246
+ `;
2247
+ return enhancedQuery;
2248
+ } catch (e) {
2249
+ logger.warn(`Could not extract schema details: ${e}`);
2250
+ return query;
2251
+ }
2252
+ }
2253
+ };
2254
+
2255
+ // src/client.ts
2256
+ import fs3 from "fs";
2257
+ import path3 from "path";
2258
+
2259
+ // src/session.ts
2260
+ var MCPSession = class {
2261
+ static {
2262
+ __name(this, "MCPSession");
2263
+ }
2264
+ connector;
2265
+ autoConnect;
2266
+ constructor(connector, autoConnect = true) {
2267
+ this.connector = connector;
2268
+ this.autoConnect = autoConnect;
2269
+ }
2270
+ async connect() {
2271
+ await this.connector.connect();
2272
+ }
2273
+ async disconnect() {
2274
+ await this.connector.disconnect();
2275
+ }
2276
+ async initialize() {
2277
+ if (!this.isConnected && this.autoConnect) {
2278
+ await this.connect();
2279
+ }
2280
+ await this.connector.initialize();
2281
+ }
2282
+ get isConnected() {
2283
+ return this.connector && this.connector.isClientConnected;
2284
+ }
2285
+ };
2286
+
2287
+ // src/client/base.ts
2288
+ var BaseMCPClient = class {
2289
+ static {
2290
+ __name(this, "BaseMCPClient");
2291
+ }
2292
+ config = {};
2293
+ sessions = {};
2294
+ activeSessions = [];
2295
+ constructor(config) {
2296
+ if (config) {
2297
+ this.config = config;
2298
+ }
2299
+ }
2300
+ static fromDict(_cfg) {
2301
+ throw new Error("fromDict must be implemented by concrete class");
2302
+ }
2303
+ addServer(name, serverConfig) {
2304
+ this.config.mcpServers = this.config.mcpServers || {};
2305
+ this.config.mcpServers[name] = serverConfig;
2306
+ }
2307
+ removeServer(name) {
2308
+ if (this.config.mcpServers?.[name]) {
2309
+ delete this.config.mcpServers[name];
2310
+ this.activeSessions = this.activeSessions.filter((n) => n !== name);
2311
+ }
2312
+ }
2313
+ getServerNames() {
2314
+ return Object.keys(this.config.mcpServers ?? {});
2315
+ }
2316
+ getServerConfig(name) {
2317
+ return this.config.mcpServers?.[name];
2318
+ }
2319
+ getConfig() {
2320
+ return this.config ?? {};
2321
+ }
2322
+ async createSession(serverName, autoInitialize = true) {
2323
+ const servers = this.config.mcpServers ?? {};
2324
+ if (Object.keys(servers).length === 0) {
2325
+ logger.warn("No MCP servers defined in config");
2326
+ }
2327
+ if (!servers[serverName]) {
2328
+ throw new Error(`Server '${serverName}' not found in config`);
2329
+ }
2330
+ const connector = this.createConnectorFromConfig(servers[serverName]);
2331
+ const session = new MCPSession(connector);
2332
+ if (autoInitialize) {
2333
+ await session.initialize();
2334
+ }
2335
+ this.sessions[serverName] = session;
2336
+ if (!this.activeSessions.includes(serverName)) {
2337
+ this.activeSessions.push(serverName);
2338
+ }
2339
+ return session;
2340
+ }
2341
+ async createAllSessions(autoInitialize = true) {
2342
+ const servers = this.config.mcpServers ?? {};
2343
+ if (Object.keys(servers).length === 0) {
2344
+ logger.warn("No MCP servers defined in config");
2345
+ }
2346
+ for (const name of Object.keys(servers)) {
2347
+ await this.createSession(name, autoInitialize);
2348
+ }
2349
+ return this.sessions;
2350
+ }
2351
+ getSession(serverName) {
2352
+ const session = this.sessions[serverName];
2353
+ if (!session) {
2354
+ return null;
2355
+ }
2356
+ return session;
2357
+ }
2358
+ getAllActiveSessions() {
2359
+ return Object.fromEntries(
2360
+ this.activeSessions.map((n) => [n, this.sessions[n]])
2361
+ );
2362
+ }
2363
+ async closeSession(serverName) {
2364
+ const session = this.sessions[serverName];
2365
+ if (!session) {
2366
+ logger.warn(`No session exists for server ${serverName}, nothing to close`);
2367
+ return;
2368
+ }
2369
+ try {
2370
+ logger.debug(`Closing session for server ${serverName}`);
2371
+ await session.disconnect();
2372
+ } catch (e) {
2373
+ logger.error(`Error closing session for server '${serverName}': ${e}`);
2374
+ } finally {
2375
+ delete this.sessions[serverName];
2376
+ this.activeSessions = this.activeSessions.filter((n) => n !== serverName);
2377
+ }
2378
+ }
2379
+ async closeAllSessions() {
2380
+ const serverNames = Object.keys(this.sessions);
2381
+ const errors = [];
2382
+ for (const serverName of serverNames) {
2383
+ try {
2384
+ logger.debug(`Closing session for server ${serverName}`);
2385
+ await this.closeSession(serverName);
2386
+ } catch (e) {
2387
+ const errorMsg = `Failed to close session for server '${serverName}': ${e}`;
2388
+ logger.error(errorMsg);
2389
+ errors.push(errorMsg);
2390
+ }
2391
+ }
2392
+ if (errors.length) {
2393
+ logger.error(`Encountered ${errors.length} errors while closing sessions`);
2394
+ } else {
2395
+ logger.debug("All sessions closed successfully");
2396
+ }
2397
+ }
2398
+ };
2399
+
2400
+ // src/config.ts
2401
+ import { readFileSync as readFileSync3 } from "fs";
2402
+
2403
+ // src/connectors/http.ts
2404
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2405
+ import { StreamableHTTPError } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2406
+
2407
+ // src/task_managers/sse.ts
2408
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
2409
+
2410
+ // src/task_managers/base.ts
2411
+ var ConnectionManager = class {
2412
+ static {
2413
+ __name(this, "ConnectionManager");
2414
+ }
2415
+ _readyPromise;
2416
+ _readyResolver;
2417
+ _donePromise;
2418
+ _doneResolver;
2419
+ _exception = null;
2420
+ _connection = null;
2421
+ _task = null;
2422
+ _abortController = null;
2423
+ constructor() {
2424
+ this.reset();
2425
+ }
2426
+ /**
2427
+ * Start the connection manager and establish a connection.
2428
+ *
2429
+ * @returns The established connection.
2430
+ * @throws If the connection cannot be established.
2431
+ */
2432
+ async start() {
2433
+ this.reset();
2434
+ logger.debug(`Starting ${this.constructor.name}`);
2435
+ this._task = this.connectionTask();
2436
+ await this._readyPromise;
2437
+ if (this._exception) {
2438
+ throw this._exception;
2439
+ }
2440
+ if (this._connection === null) {
2441
+ throw new Error("Connection was not established");
2442
+ }
2443
+ return this._connection;
2444
+ }
2445
+ /**
2446
+ * Stop the connection manager and close the connection.
2447
+ */
2448
+ async stop() {
2449
+ if (this._task && this._abortController) {
2450
+ logger.debug(`Cancelling ${this.constructor.name} task`);
2451
+ this._abortController.abort();
2452
+ try {
2453
+ await this._task;
2454
+ } catch (e) {
2455
+ if (e instanceof Error && e.name === "AbortError") {
2456
+ logger.debug(`${this.constructor.name} task aborted successfully`);
2457
+ } else {
2458
+ logger.warn(`Error stopping ${this.constructor.name} task: ${e}`);
2459
+ }
2460
+ }
2461
+ }
2462
+ await this._donePromise;
2463
+ logger.debug(`${this.constructor.name} task completed`);
2464
+ }
2465
+ /**
2466
+ * Reset all internal state.
2467
+ */
2468
+ reset() {
2469
+ this._readyPromise = new Promise((res) => this._readyResolver = res);
2470
+ this._donePromise = new Promise((res) => this._doneResolver = res);
2471
+ this._exception = null;
2472
+ this._connection = null;
2473
+ this._task = null;
2474
+ this._abortController = new AbortController();
2475
+ }
2476
+ /**
2477
+ * The background task responsible for establishing and maintaining the
2478
+ * connection until it is cancelled.
2479
+ */
2480
+ async connectionTask() {
2481
+ logger.debug(`Running ${this.constructor.name} task`);
2482
+ try {
2483
+ this._connection = await this.establishConnection();
2484
+ logger.debug(`${this.constructor.name} connected successfully`);
2485
+ this._readyResolver();
2486
+ await this.waitForAbort();
2487
+ } catch (err) {
2488
+ this._exception = err;
2489
+ logger.error(`Error in ${this.constructor.name} task: ${err}`);
2490
+ this._readyResolver();
2491
+ } finally {
2492
+ if (this._connection !== null) {
2493
+ try {
2494
+ await this.closeConnection(this._connection);
2495
+ } catch (closeErr) {
2496
+ logger.warn(`Error closing connection in ${this.constructor.name}: ${closeErr}`);
2497
+ }
2498
+ this._connection = null;
2499
+ }
2500
+ this._doneResolver();
2501
+ }
2502
+ }
2503
+ /**
2504
+ * Helper that returns a promise which resolves when the abort signal fires.
2505
+ */
2506
+ async waitForAbort() {
2507
+ return new Promise((_resolve, _reject) => {
2508
+ if (!this._abortController) {
2509
+ return;
2510
+ }
2511
+ const signal = this._abortController.signal;
2512
+ if (signal.aborted) {
2513
+ _resolve();
2514
+ return;
2515
+ }
2516
+ const onAbort = /* @__PURE__ */ __name(() => {
2517
+ signal.removeEventListener("abort", onAbort);
2518
+ _resolve();
2519
+ }, "onAbort");
2520
+ signal.addEventListener("abort", onAbort);
2521
+ });
2522
+ }
2523
+ };
2524
+
2525
+ // src/task_managers/sse.ts
2526
+ var SseConnectionManager = class extends ConnectionManager {
2527
+ static {
2528
+ __name(this, "SseConnectionManager");
2529
+ }
2530
+ url;
2531
+ opts;
2532
+ _transport = null;
2533
+ /**
2534
+ * Create an SSE connection manager.
2535
+ *
2536
+ * @param url The SSE endpoint URL.
2537
+ * @param opts Optional transport options (auth, headers, etc.).
2538
+ */
2539
+ constructor(url, opts) {
2540
+ super();
2541
+ this.url = typeof url === "string" ? new URL(url) : url;
2542
+ this.opts = opts;
2543
+ }
2544
+ /**
2545
+ * Spawn a new `SSEClientTransport` and start the connection.
2546
+ */
2547
+ async establishConnection() {
2548
+ this._transport = new SSEClientTransport(this.url, this.opts);
2549
+ logger.debug(`${this.constructor.name} connected successfully`);
2550
+ return this._transport;
2551
+ }
2552
+ /**
2553
+ * Close the underlying transport and clean up resources.
2554
+ */
2555
+ async closeConnection(_connection) {
2556
+ if (this._transport) {
2557
+ try {
2558
+ await this._transport.close();
2559
+ } catch (e) {
2560
+ logger.warn(`Error closing SSE transport: ${e}`);
2561
+ } finally {
2562
+ this._transport = null;
2563
+ }
2564
+ }
2565
+ }
2566
+ };
2567
+
2568
+ // src/task_managers/streamable_http.ts
2569
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2570
+ var StreamableHttpConnectionManager = class extends ConnectionManager {
2571
+ static {
2572
+ __name(this, "StreamableHttpConnectionManager");
2573
+ }
2574
+ url;
2575
+ opts;
2576
+ _transport = null;
2577
+ /**
2578
+ * Create a Streamable HTTP connection manager.
2579
+ *
2580
+ * @param url The HTTP endpoint URL.
2581
+ * @param opts Optional transport options (auth, headers, etc.).
2582
+ */
2583
+ constructor(url, opts) {
2584
+ super();
2585
+ this.url = typeof url === "string" ? new URL(url) : url;
2586
+ this.opts = opts;
2587
+ }
2588
+ /**
2589
+ * Spawn a new `StreamableHTTPClientTransport` and return it.
2590
+ * The Client.connect() method will handle starting the transport.
2591
+ */
2592
+ async establishConnection() {
2593
+ this._transport = new StreamableHTTPClientTransport(this.url, this.opts);
2594
+ logger.debug(`${this.constructor.name} created successfully`);
2595
+ return this._transport;
2596
+ }
2597
+ /**
2598
+ * Close the underlying transport and clean up resources.
2599
+ */
2600
+ async closeConnection(_connection) {
2601
+ if (this._transport) {
2602
+ try {
2603
+ await this._transport.close();
2604
+ } catch (e) {
2605
+ logger.warn(`Error closing Streamable HTTP transport: ${e}`);
2606
+ } finally {
2607
+ this._transport = null;
2608
+ }
2609
+ }
2610
+ }
2611
+ /**
2612
+ * Get the session ID from the transport if available.
2613
+ */
2614
+ get sessionId() {
2615
+ return this._transport?.sessionId;
2616
+ }
2617
+ };
2618
+
2619
+ // src/connectors/base.ts
2620
+ var BaseConnector = class {
2621
+ static {
2622
+ __name(this, "BaseConnector");
2623
+ }
2624
+ client = null;
2625
+ connectionManager = null;
2626
+ toolsCache = null;
2627
+ connected = false;
2628
+ opts;
2629
+ constructor(opts = {}) {
2630
+ this.opts = opts;
2631
+ }
2632
+ /** Disconnect and release resources. */
2633
+ async disconnect() {
2634
+ if (!this.connected) {
2635
+ logger.debug("Not connected to MCP implementation");
2636
+ return;
2637
+ }
2638
+ logger.debug("Disconnecting from MCP implementation");
2639
+ await this.cleanupResources();
2640
+ this.connected = false;
2641
+ logger.debug("Disconnected from MCP implementation");
2642
+ }
2643
+ /** Check if the client is connected */
2644
+ get isClientConnected() {
2645
+ return this.client != null;
2646
+ }
2647
+ /**
2648
+ * Initialise the MCP session **after** `connect()` has succeeded.
2649
+ *
2650
+ * In the SDK, `Client.connect(transport)` automatically performs the
2651
+ * protocol‑level `initialize` handshake, so we only need to cache the list of
2652
+ * tools and expose some server info.
2653
+ */
2654
+ async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
2655
+ if (!this.client) {
2656
+ throw new Error("MCP client is not connected");
2657
+ }
2658
+ logger.debug("Caching server capabilities & tools");
2659
+ const capabilities = this.client.getServerCapabilities();
2660
+ const listToolsRes = await this.client.listTools(void 0, defaultRequestOptions);
2661
+ this.toolsCache = listToolsRes.tools ?? [];
2662
+ logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
2663
+ return capabilities;
2664
+ }
2665
+ /** Lazily expose the cached tools list. */
2666
+ get tools() {
2667
+ if (!this.toolsCache) {
2668
+ throw new Error("MCP client is not initialized; call initialize() first");
2669
+ }
2670
+ return this.toolsCache;
2671
+ }
2672
+ /** Call a tool on the server. */
2673
+ async callTool(name, args, options) {
2674
+ if (!this.client) {
2675
+ throw new Error("MCP client is not connected");
2676
+ }
2677
+ logger.debug(`Calling tool '${name}' with args`, args);
2678
+ const res = await this.client.callTool({ name, arguments: args }, void 0, options);
2679
+ logger.debug(`Tool '${name}' returned`, res);
2680
+ return res;
2681
+ }
2682
+ /** List resources from the server. */
2683
+ async listResources(options) {
2684
+ if (!this.client) {
2685
+ throw new Error("MCP client is not connected");
2686
+ }
2687
+ logger.debug("Listing resources");
2688
+ return await this.client.listResources(void 0, options);
2689
+ }
2690
+ /** Read a resource by URI. */
2691
+ async readResource(uri, options) {
2692
+ if (!this.client) {
2693
+ throw new Error("MCP client is not connected");
2694
+ }
2695
+ logger.debug(`Reading resource ${uri}`);
2696
+ const res = await this.client.readResource({ uri }, options);
2697
+ return { content: res.content, mimeType: res.mimeType };
2698
+ }
2699
+ async listPrompts() {
2700
+ if (!this.client) {
2701
+ throw new Error("MCP client is not connected");
2702
+ }
2703
+ logger.debug("Listing prompt");
2704
+ return await this.client.listPrompts();
2705
+ }
2706
+ async getPrompt(name, args) {
2707
+ if (!this.client) {
2708
+ throw new Error("MCP client is not connected");
2709
+ }
2710
+ logger.debug(`Getting prompt ${name}`);
2711
+ return await this.client.getPrompt({ name, arguments: args });
2712
+ }
2713
+ /** Send a raw request through the client. */
2714
+ async request(method, params = null, options) {
2715
+ if (!this.client) {
2716
+ throw new Error("MCP client is not connected");
2717
+ }
2718
+ logger.debug(`Sending raw request '${method}' with params`, params);
2719
+ return await this.client.request({ method, params: params ?? {} }, void 0, options);
2720
+ }
2721
+ /**
2722
+ * Helper to tear down the client & connection manager safely.
2723
+ */
2724
+ async cleanupResources() {
2725
+ const issues = [];
2726
+ if (this.client) {
2727
+ try {
2728
+ if (typeof this.client.close === "function") {
2729
+ await this.client.close();
2730
+ }
2731
+ } catch (e) {
2732
+ const msg = `Error closing client: ${e}`;
2733
+ logger.warn(msg);
2734
+ issues.push(msg);
2735
+ } finally {
2736
+ this.client = null;
2737
+ }
2738
+ }
2739
+ if (this.connectionManager) {
2740
+ try {
2741
+ await this.connectionManager.stop();
2742
+ } catch (e) {
2743
+ const msg = `Error stopping connection manager: ${e}`;
2744
+ logger.warn(msg);
2745
+ issues.push(msg);
2746
+ } finally {
2747
+ this.connectionManager = null;
2748
+ }
2749
+ }
2750
+ this.toolsCache = null;
2751
+ if (issues.length) {
2752
+ logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
2753
+ }
2754
+ }
2755
+ };
2756
+
2757
+ // src/connectors/http.ts
2758
+ var HttpConnector = class extends BaseConnector {
2759
+ static {
2760
+ __name(this, "HttpConnector");
2761
+ }
2762
+ baseUrl;
2763
+ headers;
2764
+ timeout;
2765
+ sseReadTimeout;
2766
+ clientInfo;
2767
+ preferSse;
2768
+ transportType = null;
2769
+ constructor(baseUrl, opts = {}) {
2770
+ super(opts);
2771
+ this.baseUrl = baseUrl.replace(/\/$/, "");
2772
+ this.headers = { ...opts.headers ?? {} };
2773
+ if (opts.authToken) {
2774
+ this.headers.Authorization = `Bearer ${opts.authToken}`;
2775
+ }
2776
+ this.timeout = opts.timeout ?? 5;
2777
+ this.sseReadTimeout = opts.sseReadTimeout ?? 60 * 5;
2778
+ this.clientInfo = opts.clientInfo ?? { name: "http-connector", version: "1.0.0" };
2779
+ this.preferSse = opts.preferSse ?? false;
2780
+ }
2781
+ /** Establish connection to the MCP implementation via HTTP (streamable or SSE). */
2782
+ async connect() {
2783
+ if (this.connected) {
2784
+ logger.debug("Already connected to MCP implementation");
2785
+ return;
2786
+ }
2787
+ const baseUrl = this.baseUrl;
2788
+ if (this.preferSse) {
2789
+ logger.debug(`Connecting to MCP implementation via HTTP/SSE: ${baseUrl}`);
2790
+ await this.connectWithSse(baseUrl);
2791
+ return;
2792
+ }
2793
+ logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
2794
+ try {
2795
+ logger.debug("Attempting streamable HTTP transport...");
2796
+ await this.connectWithStreamableHttp(baseUrl);
2797
+ } catch (err) {
2798
+ let fallbackReason = "Unknown error";
2799
+ if (err instanceof StreamableHTTPError) {
2800
+ if (err.code === 404 || err.code === 405) {
2801
+ fallbackReason = `Server returned ${err.code} - server likely doesn't support streamable HTTP`;
2802
+ logger.debug(fallbackReason);
2803
+ } else {
2804
+ fallbackReason = `Server returned ${err.code}: ${err.message}`;
2805
+ logger.debug(fallbackReason);
2806
+ }
2807
+ } else if (err instanceof Error) {
2808
+ const errorStr = err.toString();
2809
+ if (errorStr.includes("405 Method Not Allowed") || errorStr.includes("404 Not Found")) {
2810
+ fallbackReason = "Server doesn't support streamable HTTP (405/404)";
2811
+ logger.debug(fallbackReason);
2812
+ } else {
2813
+ fallbackReason = `Streamable HTTP failed: ${err.message}`;
2814
+ logger.debug(fallbackReason);
2815
+ }
2816
+ }
2817
+ logger.debug("Falling back to SSE transport...");
2818
+ try {
2819
+ await this.connectWithSse(baseUrl);
2820
+ } catch (sseErr) {
2821
+ logger.error(`Failed to connect with both transports:`);
2822
+ logger.error(` Streamable HTTP: ${fallbackReason}`);
2823
+ logger.error(` SSE: ${sseErr}`);
2824
+ await this.cleanupResources();
2825
+ throw new Error("Could not connect to server with any available transport");
2826
+ }
2827
+ }
2828
+ }
2829
+ async connectWithStreamableHttp(baseUrl) {
2830
+ try {
2831
+ this.connectionManager = new StreamableHttpConnectionManager(
2832
+ baseUrl,
2833
+ {
2834
+ requestInit: {
2835
+ headers: this.headers
2836
+ },
2837
+ // Pass through timeout and other options
2838
+ reconnectionOptions: {
2839
+ maxReconnectionDelay: 3e4,
2840
+ initialReconnectionDelay: 1e3,
2841
+ reconnectionDelayGrowFactor: 1.5,
2842
+ maxRetries: 2
2843
+ }
2844
+ }
2845
+ );
2846
+ const transport = await this.connectionManager.start();
2847
+ this.client = new Client(this.clientInfo, this.opts.clientOptions);
2848
+ await this.client.connect(transport);
2849
+ this.connected = true;
2850
+ this.transportType = "streamable-http";
2851
+ logger.debug(`Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`);
2852
+ } catch (err) {
2853
+ await this.cleanupResources();
2854
+ throw err;
2855
+ }
2856
+ }
2857
+ async connectWithSse(baseUrl) {
2858
+ try {
2859
+ this.connectionManager = new SseConnectionManager(
2860
+ baseUrl,
2861
+ {
2862
+ requestInit: {
2863
+ headers: this.headers
2864
+ }
2865
+ }
2866
+ );
2867
+ const transport = await this.connectionManager.start();
2868
+ this.client = new Client(this.clientInfo, this.opts.clientOptions);
2869
+ await this.client.connect(transport);
2870
+ this.connected = true;
2871
+ this.transportType = "sse";
2872
+ logger.debug(`Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`);
2873
+ } catch (err) {
2874
+ await this.cleanupResources();
2875
+ throw err;
2876
+ }
2877
+ }
2878
+ get publicIdentifier() {
2879
+ return {
2880
+ type: "http",
2881
+ url: this.baseUrl,
2882
+ transport: this.transportType || "unknown"
2883
+ };
2884
+ }
2885
+ /**
2886
+ * Get the transport type being used (streamable-http or sse)
2887
+ */
2888
+ getTransportType() {
2889
+ return this.transportType;
2890
+ }
2891
+ };
2892
+
2893
+ // src/connectors/stdio.ts
2894
+ import process2 from "process";
2895
+ import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
2896
+
2897
+ // src/task_managers/stdio.ts
2898
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
2899
+ var StdioConnectionManager = class extends ConnectionManager {
2900
+ static {
2901
+ __name(this, "StdioConnectionManager");
2902
+ }
2903
+ serverParams;
2904
+ errlog;
2905
+ _transport = null;
2906
+ /**
2907
+ * Create a new stdio connection manager.
2908
+ *
2909
+ * @param serverParams Parameters for the stdio server process.
2910
+ * @param errlog Stream to which the server's stderr should be piped.
2911
+ * Defaults to `process.stderr`.
2912
+ */
2913
+ constructor(serverParams, errlog = process.stderr) {
2914
+ super();
2915
+ this.serverParams = serverParams;
2916
+ this.errlog = errlog;
2917
+ }
2918
+ /**
2919
+ * Establish the stdio connection by spawning the server process and starting
2920
+ * the SDK's transport. Returns the live `StdioClientTransport` instance.
2921
+ */
2922
+ async establishConnection() {
2923
+ this._transport = new StdioClientTransport(this.serverParams);
2924
+ if (this._transport.stderr && typeof this._transport.stderr.pipe === "function") {
2925
+ this._transport.stderr.pipe(this.errlog);
2926
+ }
2927
+ logger.debug(`${this.constructor.name} connected successfully`);
2928
+ return this._transport;
2929
+ }
2930
+ /**
2931
+ * Close the stdio connection, making sure the transport cleans up the child
2932
+ * process and associated resources.
2933
+ */
2934
+ async closeConnection(_connection) {
2935
+ if (this._transport) {
2936
+ try {
2937
+ await this._transport.close();
2938
+ } catch (e) {
2939
+ logger.warn(`Error closing stdio transport: ${e}`);
2940
+ } finally {
2941
+ this._transport = null;
2942
+ }
2943
+ }
2944
+ }
2945
+ };
2946
+
2947
+ // src/connectors/stdio.ts
2948
+ var StdioConnector = class extends BaseConnector {
2949
+ static {
2950
+ __name(this, "StdioConnector");
2951
+ }
2952
+ command;
2953
+ args;
2954
+ env;
2955
+ errlog;
2956
+ clientInfo;
2957
+ constructor({
2958
+ command = "npx",
2959
+ args = [],
2960
+ env,
2961
+ errlog = process2.stderr,
2962
+ ...rest
2963
+ } = {}) {
2964
+ super(rest);
2965
+ this.command = command;
2966
+ this.args = args;
2967
+ this.env = env;
2968
+ this.errlog = errlog;
2969
+ this.clientInfo = rest.clientInfo ?? { name: "stdio-connector", version: "1.0.0" };
2970
+ }
2971
+ /** Establish connection to the MCP implementation. */
2972
+ async connect() {
2973
+ if (this.connected) {
2974
+ logger.debug("Already connected to MCP implementation");
2975
+ return;
2976
+ }
2977
+ logger.debug(`Connecting to MCP implementation via stdio: ${this.command}`);
2978
+ try {
2979
+ let mergedEnv;
2980
+ if (this.env) {
2981
+ mergedEnv = {};
2982
+ for (const [key, value] of Object.entries(process2.env)) {
2983
+ if (value !== void 0) {
2984
+ mergedEnv[key] = value;
2985
+ }
2986
+ }
2987
+ Object.assign(mergedEnv, this.env);
2988
+ }
2989
+ const serverParams = {
2990
+ command: this.command,
2991
+ args: this.args,
2992
+ env: mergedEnv
2993
+ };
2994
+ this.connectionManager = new StdioConnectionManager(serverParams, this.errlog);
2995
+ const transport = await this.connectionManager.start();
2996
+ this.client = new Client2(this.clientInfo, this.opts.clientOptions);
2997
+ await this.client.connect(transport);
2998
+ this.connected = true;
2999
+ logger.debug(`Successfully connected to MCP implementation: ${this.command}`);
3000
+ } catch (err) {
3001
+ logger.error(`Failed to connect to MCP implementation: ${err}`);
3002
+ await this.cleanupResources();
3003
+ throw err;
3004
+ }
3005
+ }
3006
+ get publicIdentifier() {
3007
+ return {
3008
+ "type": "stdio",
3009
+ "command&args": `${this.command} ${this.args.join(" ")}`
3010
+ };
3011
+ }
3012
+ };
3013
+
3014
+ // src/connectors/websocket.ts
3015
+ import { v4 as uuidv42 } from "uuid";
3016
+
3017
+ // src/task_managers/websocket.ts
3018
+ import WS from "ws";
3019
+ var WebSocketConnectionManager = class extends ConnectionManager {
3020
+ static {
3021
+ __name(this, "WebSocketConnectionManager");
3022
+ }
3023
+ url;
3024
+ headers;
3025
+ _ws = null;
3026
+ /**
3027
+ * @param url The WebSocket URL to connect to.
3028
+ * @param headers Optional headers to include in the connection handshake.
3029
+ */
3030
+ constructor(url, headers = {}) {
3031
+ super();
3032
+ this.url = url;
3033
+ this.headers = headers;
3034
+ }
3035
+ /** Establish a WebSocket connection and wait until it is open. */
3036
+ async establishConnection() {
3037
+ logger.debug(`Connecting to WebSocket: ${this.url}`);
3038
+ return new Promise((resolve, reject) => {
3039
+ const ws = new WS(this.url, { headers: this.headers });
3040
+ this._ws = ws;
3041
+ const onOpen = /* @__PURE__ */ __name(() => {
3042
+ cleanup();
3043
+ logger.debug("WebSocket connected successfully");
3044
+ resolve(ws);
3045
+ }, "onOpen");
3046
+ const onError = /* @__PURE__ */ __name((err) => {
3047
+ cleanup();
3048
+ logger.error(`Failed to connect to WebSocket: ${err}`);
3049
+ reject(err);
3050
+ }, "onError");
3051
+ const cleanup = /* @__PURE__ */ __name(() => {
3052
+ ws.off("open", onOpen);
3053
+ ws.off("error", onError);
3054
+ }, "cleanup");
3055
+ ws.on("open", onOpen);
3056
+ ws.on("error", onError);
3057
+ });
3058
+ }
3059
+ /** Cleanly close the WebSocket connection. */
3060
+ async closeConnection(connection) {
3061
+ logger.debug("Closing WebSocket connection");
3062
+ return new Promise((resolve) => {
3063
+ const onClose = /* @__PURE__ */ __name(() => {
3064
+ connection.off("close", onClose);
3065
+ this._ws = null;
3066
+ resolve();
3067
+ }, "onClose");
3068
+ if (connection.readyState === WS.CLOSED) {
3069
+ onClose();
3070
+ return;
3071
+ }
3072
+ connection.on("close", onClose);
3073
+ try {
3074
+ connection.close();
3075
+ } catch (e) {
3076
+ logger.warn(`Error closing WebSocket connection: ${e}`);
3077
+ onClose();
3078
+ }
3079
+ });
3080
+ }
3081
+ };
3082
+
3083
+ // src/connectors/websocket.ts
3084
+ var WebSocketConnector = class extends BaseConnector {
3085
+ static {
3086
+ __name(this, "WebSocketConnector");
3087
+ }
3088
+ url;
3089
+ headers;
3090
+ connectionManager = null;
3091
+ ws = null;
3092
+ receiverTask = null;
3093
+ pending = /* @__PURE__ */ new Map();
3094
+ toolsCache = null;
3095
+ constructor(url, opts = {}) {
3096
+ super();
3097
+ this.url = url;
3098
+ this.headers = { ...opts.headers ?? {} };
3099
+ if (opts.authToken)
3100
+ this.headers.Authorization = `Bearer ${opts.authToken}`;
3101
+ }
3102
+ async connect() {
3103
+ if (this.connected) {
3104
+ logger.debug("Already connected to MCP implementation");
3105
+ return;
3106
+ }
3107
+ logger.debug(`Connecting via WebSocket: ${this.url}`);
3108
+ try {
3109
+ this.connectionManager = new WebSocketConnectionManager(this.url, this.headers);
3110
+ this.ws = await this.connectionManager.start();
3111
+ this.receiverTask = this.receiveLoop();
3112
+ this.connected = true;
3113
+ logger.debug("WebSocket connected successfully");
3114
+ } catch (e) {
3115
+ logger.error(`Failed to connect: ${e}`);
3116
+ await this.cleanupResources();
3117
+ throw e;
3118
+ }
3119
+ }
3120
+ async disconnect() {
3121
+ if (!this.connected) {
3122
+ logger.debug("Not connected to MCP implementation");
3123
+ return;
3124
+ }
3125
+ logger.debug("Disconnecting \u2026");
3126
+ await this.cleanupResources();
3127
+ this.connected = false;
3128
+ }
3129
+ sendRequest(method, params = null) {
3130
+ if (!this.ws)
3131
+ throw new Error("WebSocket is not connected");
3132
+ const id = uuidv42();
3133
+ const payload = JSON.stringify({ id, method, params: params ?? {} });
3134
+ return new Promise((resolve, reject) => {
3135
+ this.pending.set(id, { resolve, reject });
3136
+ this.ws.send(payload, (err) => {
3137
+ if (err) {
3138
+ this.pending.delete(id);
3139
+ reject(err);
3140
+ }
3141
+ });
3142
+ });
3143
+ }
3144
+ async receiveLoop() {
3145
+ if (!this.ws)
3146
+ return;
3147
+ const socket = this.ws;
3148
+ const onMessage = /* @__PURE__ */ __name((msg) => {
3149
+ let data;
3150
+ try {
3151
+ data = JSON.parse(msg.data ?? msg);
3152
+ } catch (e) {
3153
+ logger.warn("Received non\u2011JSON frame", e);
3154
+ return;
3155
+ }
3156
+ const id = data.id;
3157
+ if (id && this.pending.has(id)) {
3158
+ const { resolve, reject } = this.pending.get(id);
3159
+ this.pending.delete(id);
3160
+ if ("result" in data)
3161
+ resolve(data.result);
3162
+ else if ("error" in data)
3163
+ reject(data.error);
3164
+ } else {
3165
+ logger.debug("Received unsolicited message", data);
3166
+ }
3167
+ }, "onMessage");
3168
+ socket.addEventListener ? socket.addEventListener("message", onMessage) : socket.on("message", onMessage);
3169
+ return new Promise((resolve) => {
3170
+ const onClose = /* @__PURE__ */ __name(() => {
3171
+ socket.removeEventListener ? socket.removeEventListener("message", onMessage) : socket.off("message", onMessage);
3172
+ this.rejectAll(new Error("WebSocket closed"));
3173
+ resolve();
3174
+ }, "onClose");
3175
+ socket.addEventListener ? socket.addEventListener("close", onClose) : socket.on("close", onClose);
3176
+ });
3177
+ }
3178
+ rejectAll(err) {
3179
+ for (const { reject } of this.pending.values()) reject(err);
3180
+ this.pending.clear();
3181
+ }
3182
+ async initialize() {
3183
+ logger.debug("Initializing MCP session over WebSocket");
3184
+ const result = await this.sendRequest("initialize");
3185
+ const toolsList = await this.listTools();
3186
+ this.toolsCache = toolsList.map((t) => t);
3187
+ logger.debug(`Initialized with ${this.toolsCache.length} tools`);
3188
+ return result;
3189
+ }
3190
+ async listTools() {
3191
+ const res = await this.sendRequest("tools/list");
3192
+ return res.tools ?? [];
3193
+ }
3194
+ async callTool(name, args) {
3195
+ return await this.sendRequest("tools/call", { name, arguments: args });
3196
+ }
3197
+ async listResources() {
3198
+ const resources = await this.sendRequest("resources/list");
3199
+ return { resources: Array.isArray(resources) ? resources : [] };
3200
+ }
3201
+ async readResource(uri) {
3202
+ const res = await this.sendRequest("resources/read", { uri });
3203
+ return { content: res.content, mimeType: res.mimeType };
3204
+ }
3205
+ async request(method, params = null) {
3206
+ return await this.sendRequest(method, params);
3207
+ }
3208
+ get tools() {
3209
+ if (!this.toolsCache)
3210
+ throw new Error("MCP client is not initialized");
3211
+ return this.toolsCache;
3212
+ }
3213
+ async cleanupResources() {
3214
+ if (this.receiverTask)
3215
+ await this.receiverTask.catch(() => {
3216
+ });
3217
+ this.receiverTask = null;
3218
+ this.rejectAll(new Error("WebSocket disconnected"));
3219
+ if (this.connectionManager) {
3220
+ await this.connectionManager.stop();
3221
+ this.connectionManager = null;
3222
+ this.ws = null;
3223
+ }
3224
+ this.toolsCache = null;
3225
+ }
3226
+ get publicIdentifier() {
3227
+ return {
3228
+ type: "websocket",
3229
+ url: this.url
3230
+ };
3231
+ }
3232
+ };
3233
+
3234
+ // src/config.ts
3235
+ function loadConfigFile(filepath) {
3236
+ const raw = readFileSync3(filepath, "utf-8");
3237
+ return JSON.parse(raw);
3238
+ }
3239
+ __name(loadConfigFile, "loadConfigFile");
3240
+ function createConnectorFromConfig(serverConfig) {
3241
+ if ("command" in serverConfig && "args" in serverConfig) {
3242
+ return new StdioConnector({
3243
+ command: serverConfig.command,
3244
+ args: serverConfig.args,
3245
+ env: serverConfig.env
3246
+ });
3247
+ }
3248
+ if ("url" in serverConfig) {
3249
+ const transport = serverConfig.transport || "http";
3250
+ return new HttpConnector(serverConfig.url, {
3251
+ headers: serverConfig.headers,
3252
+ authToken: serverConfig.auth_token || serverConfig.authToken,
3253
+ // Only force SSE if explicitly requested
3254
+ preferSse: serverConfig.preferSse || transport === "sse"
3255
+ });
3256
+ }
3257
+ if ("ws_url" in serverConfig) {
3258
+ return new WebSocketConnector(serverConfig.ws_url, {
3259
+ headers: serverConfig.headers,
3260
+ authToken: serverConfig.auth_token
3261
+ });
3262
+ }
3263
+ throw new Error("Cannot determine connector type from config");
3264
+ }
3265
+ __name(createConnectorFromConfig, "createConnectorFromConfig");
3266
+
3267
+ // src/client.ts
3268
+ var MCPClient = class _MCPClient extends BaseMCPClient {
3269
+ static {
3270
+ __name(this, "MCPClient");
3271
+ }
3272
+ constructor(config) {
3273
+ if (config) {
3274
+ if (typeof config === "string") {
3275
+ super(loadConfigFile(config));
3276
+ } else {
3277
+ super(config);
3278
+ }
3279
+ } else {
3280
+ super();
3281
+ }
3282
+ }
3283
+ static fromDict(cfg) {
3284
+ return new _MCPClient(cfg);
3285
+ }
3286
+ static fromConfigFile(path4) {
3287
+ return new _MCPClient(loadConfigFile(path4));
3288
+ }
3289
+ /**
3290
+ * Save configuration to a file (Node.js only)
3291
+ */
3292
+ saveConfig(filepath) {
3293
+ const dir = path3.dirname(filepath);
3294
+ if (!fs3.existsSync(dir)) {
3295
+ fs3.mkdirSync(dir, { recursive: true });
3296
+ }
3297
+ fs3.writeFileSync(filepath, JSON.stringify(this.config, null, 2), "utf-8");
3298
+ }
3299
+ /**
3300
+ * Create a connector from server configuration (Node.js version)
3301
+ * Supports all connector types including StdioConnector
3302
+ */
3303
+ createConnectorFromConfig(serverConfig) {
3304
+ return createConnectorFromConfig(serverConfig);
3305
+ }
3306
+ };
3307
+
3308
+ // src/agents/utils/ai_sdk.ts
3309
+ async function* streamEventsToAISDK(streamEvents) {
3310
+ for await (const event of streamEvents) {
3311
+ if (event.event === "on_chat_model_stream" && event.data?.chunk?.text) {
3312
+ const textContent = event.data.chunk.text;
3313
+ if (typeof textContent === "string" && textContent.length > 0) {
3314
+ yield textContent;
3315
+ }
3316
+ }
3317
+ }
3318
+ }
3319
+ __name(streamEventsToAISDK, "streamEventsToAISDK");
3320
+ function createReadableStreamFromGenerator(generator) {
3321
+ return new ReadableStream({
3322
+ async start(controller) {
3323
+ try {
3324
+ for await (const chunk of generator) {
3325
+ controller.enqueue(chunk);
3326
+ }
3327
+ controller.close();
3328
+ } catch (error) {
3329
+ controller.error(error);
3330
+ }
3331
+ }
3332
+ });
3333
+ }
3334
+ __name(createReadableStreamFromGenerator, "createReadableStreamFromGenerator");
3335
+ async function* streamEventsToAISDKWithTools(streamEvents) {
3336
+ for await (const event of streamEvents) {
3337
+ switch (event.event) {
3338
+ case "on_chat_model_stream":
3339
+ if (event.data?.chunk?.text) {
3340
+ const textContent = event.data.chunk.text;
3341
+ if (typeof textContent === "string" && textContent.length > 0) {
3342
+ yield textContent;
3343
+ }
3344
+ }
3345
+ break;
3346
+ case "on_tool_start":
3347
+ yield `
3348
+ \u{1F527} Using tool: ${event.name}
3349
+ `;
3350
+ break;
3351
+ case "on_tool_end":
3352
+ yield `
3353
+ \u2705 Tool completed: ${event.name}
3354
+ `;
3355
+ break;
3356
+ default:
3357
+ break;
3358
+ }
3359
+ }
3360
+ }
3361
+ __name(streamEventsToAISDKWithTools, "streamEventsToAISDKWithTools");
3362
+
3363
+ // src/oauth-helper.ts
3364
+ var OAuthHelper = class {
3365
+ static {
3366
+ __name(this, "OAuthHelper");
3367
+ }
3368
+ config;
3369
+ discovery;
3370
+ state;
3371
+ clientRegistration;
3372
+ constructor(config) {
3373
+ this.config = config;
3374
+ this.state = {
3375
+ isRequired: false,
3376
+ isAuthenticated: false,
3377
+ isAuthenticating: false,
3378
+ isCompletingOAuth: false,
3379
+ authError: null,
3380
+ oauthTokens: null
3381
+ };
3382
+ }
3383
+ /**
3384
+ * Get current OAuth state
3385
+ */
3386
+ getState() {
3387
+ return { ...this.state };
3388
+ }
3389
+ /**
3390
+ * Check if a server requires authentication by pinging the URL
3391
+ */
3392
+ async checkAuthRequired(serverUrl) {
3393
+ console.log("\u{1F50D} [OAuthHelper] Checking auth requirement for:", serverUrl);
3394
+ try {
3395
+ const response = await fetch(serverUrl, {
3396
+ method: "GET",
3397
+ headers: {
3398
+ "Accept": "text/event-stream",
3399
+ "Cache-Control": "no-cache"
3400
+ },
3401
+ redirect: "manual",
3402
+ signal: AbortSignal.timeout(1e4)
3403
+ // 10 second timeout
3404
+ });
3405
+ console.log("\u{1F50D} [OAuthHelper] Auth check response:", {
3406
+ status: response.status,
3407
+ statusText: response.statusText,
3408
+ url: serverUrl
3409
+ });
3410
+ if (response.status === 401 || response.status === 403 || response.status === 400) {
3411
+ console.log("\u{1F510} [OAuthHelper] Authentication required for:", serverUrl);
3412
+ return true;
3413
+ }
3414
+ console.log("\u2705 [OAuthHelper] No authentication required for:", serverUrl);
3415
+ return false;
3416
+ } catch (error) {
3417
+ console.warn("\u26A0\uFE0F [OAuthHelper] Could not check auth requirement for:", serverUrl, error);
3418
+ if (error.name === "TypeError" && (error.message?.includes("CORS") || error.message?.includes("Failed to fetch"))) {
3419
+ console.log("\u{1F50D} [OAuthHelper] CORS blocked direct check, using heuristics for:", serverUrl);
3420
+ return this.checkAuthByHeuristics(serverUrl);
3421
+ }
3422
+ if (error.name === "AbortError") {
3423
+ console.log("\u23F0 [OAuthHelper] Request timeout, assuming no auth required for:", serverUrl);
3424
+ return false;
3425
+ }
3426
+ return this.checkAuthByHeuristics(serverUrl);
3427
+ }
3428
+ }
3429
+ /**
3430
+ * Fallback heuristics for determining auth requirements when direct checking fails
3431
+ */
3432
+ checkAuthByHeuristics(serverUrl) {
3433
+ console.log("\u{1F50D} [OAuthHelper] Using heuristics to determine auth for:", serverUrl);
3434
+ const authRequiredPatterns = [
3435
+ /api\.githubcopilot\.com/i,
3436
+ // GitHub Copilot
3437
+ /api\.github\.com/i,
3438
+ // GitHub API
3439
+ /.*\.googleapis\.com/i,
3440
+ // Google APIs
3441
+ /api\.openai\.com/i,
3442
+ // OpenAI
3443
+ /api\.anthropic\.com/i,
3444
+ // Anthropic
3445
+ /.*\.atlassian\.net/i,
3446
+ // Atlassian (Jira, Confluence)
3447
+ /.*\.slack\.com/i,
3448
+ // Slack
3449
+ /api\.notion\.com/i,
3450
+ // Notion
3451
+ /api\.linear\.app/i
3452
+ // Linear
3453
+ ];
3454
+ const noAuthPatterns = [
3455
+ /localhost/i,
3456
+ // Local development
3457
+ /127\.0\.0\.1/,
3458
+ // Local development
3459
+ /\.local/i,
3460
+ // Local development
3461
+ /mcp\..*\.com/i
3462
+ // Generic MCP server pattern (often public)
3463
+ ];
3464
+ for (const pattern of noAuthPatterns) {
3465
+ if (pattern.test(serverUrl)) {
3466
+ console.log("\u2705 [OAuthHelper] Heuristic: No auth required (matches no-auth pattern):", serverUrl);
3467
+ return false;
3468
+ }
3469
+ }
3470
+ for (const pattern of authRequiredPatterns) {
3471
+ if (pattern.test(serverUrl)) {
3472
+ console.log("\u{1F510} [OAuthHelper] Heuristic: Auth required (matches auth pattern):", serverUrl);
3473
+ return true;
3474
+ }
3475
+ }
3476
+ console.log("\u2753 [OAuthHelper] Heuristic: Unknown pattern, assuming no auth required:", serverUrl);
3477
+ return false;
3478
+ }
3479
+ /**
3480
+ * Discover OAuth configuration from a server
3481
+ */
3482
+ async discoverOAuthConfig(serverUrl) {
3483
+ try {
3484
+ const discoveryUrl = `${serverUrl}/.well-known/oauth-authorization-server`;
3485
+ console.log("\u{1F50D} [OAuthHelper] Attempting OAuth discovery at:", discoveryUrl);
3486
+ const response = await fetch(discoveryUrl);
3487
+ if (!response.ok) {
3488
+ console.error("\u274C [OAuthHelper] OAuth discovery failed:", {
3489
+ status: response.status,
3490
+ statusText: response.statusText,
3491
+ url: discoveryUrl
3492
+ });
3493
+ throw new Error(`OAuth discovery failed: ${response.status} ${response.statusText}`);
3494
+ }
3495
+ this.discovery = await response.json();
3496
+ console.log("\u2705 [OAuthHelper] OAuth discovery successful:", {
3497
+ authorization_endpoint: this.discovery?.authorization_endpoint,
3498
+ token_endpoint: this.discovery?.token_endpoint,
3499
+ registration_endpoint: this.discovery?.registration_endpoint
3500
+ });
3501
+ return this.discovery;
3502
+ } catch (error) {
3503
+ console.error("\u274C [OAuthHelper] OAuth discovery error:", error);
3504
+ throw new Error(`Failed to discover OAuth configuration: ${error}`);
3505
+ }
3506
+ }
3507
+ /**
3508
+ * Register a new OAuth client dynamically
3509
+ */
3510
+ async registerClient(_serverUrl) {
3511
+ if (!this.discovery) {
3512
+ throw new Error("OAuth discovery not performed. Call discoverOAuthConfig first.");
3513
+ }
3514
+ if (!this.discovery.registration_endpoint) {
3515
+ throw new Error("Server does not support dynamic client registration");
3516
+ }
3517
+ try {
3518
+ const registrationData = {
3519
+ client_name: this.config.clientName || "MCP Use Example",
3520
+ redirect_uris: [this.config.redirectUri],
3521
+ grant_types: ["authorization_code"],
3522
+ response_types: ["code"],
3523
+ token_endpoint_auth_method: "none",
3524
+ // Use public client (no secret)
3525
+ scope: this.config.scope || "read write"
3526
+ };
3527
+ console.log("\u{1F510} [OAuthHelper] Registering OAuth client dynamically:", {
3528
+ registration_endpoint: this.discovery.registration_endpoint,
3529
+ client_name: registrationData.client_name,
3530
+ redirect_uri: this.config.redirectUri
3531
+ });
3532
+ const response = await fetch(this.discovery.registration_endpoint, {
3533
+ method: "POST",
3534
+ headers: {
3535
+ "Content-Type": "application/json"
3536
+ },
3537
+ body: JSON.stringify(registrationData)
3538
+ });
3539
+ if (!response.ok) {
3540
+ const errorText = await response.text();
3541
+ throw new Error(`Client registration failed: ${response.status} ${response.statusText} - ${errorText}`);
3542
+ }
3543
+ this.clientRegistration = await response.json();
3544
+ console.log("\u2705 [OAuthHelper] Client registered successfully:", {
3545
+ client_id: this.clientRegistration?.client_id,
3546
+ client_secret: this.clientRegistration?.client_secret ? "***" : "none"
3547
+ });
3548
+ return this.clientRegistration;
3549
+ } catch (error) {
3550
+ console.error("\u274C [OAuthHelper] Client registration failed:", error);
3551
+ throw new Error(`Failed to register OAuth client: ${error}`);
3552
+ }
3553
+ }
3554
+ /**
3555
+ * Generate authorization URL for OAuth flow
3556
+ */
3557
+ generateAuthUrl(serverUrl, additionalParams) {
3558
+ if (!this.discovery) {
3559
+ throw new Error("OAuth discovery not performed. Call discoverOAuthConfig first.");
3560
+ }
3561
+ if (!this.clientRegistration) {
3562
+ throw new Error("Client not registered. Call registerClient first.");
3563
+ }
3564
+ const params = new URLSearchParams({
3565
+ client_id: this.clientRegistration.client_id,
3566
+ redirect_uri: this.config.redirectUri,
3567
+ response_type: "code",
3568
+ scope: this.config.scope || "read",
3569
+ state: this.config.state || this.generateState(),
3570
+ ...additionalParams
3571
+ });
3572
+ return `${this.discovery.authorization_endpoint}?${params.toString()}`;
3573
+ }
3574
+ /**
3575
+ * Exchange authorization code for access token
3576
+ */
3577
+ async exchangeCodeForToken(serverUrl, code, codeVerifier) {
3578
+ if (!this.discovery) {
3579
+ throw new Error("OAuth discovery not performed. Call discoverOAuthConfig first.");
3580
+ }
3581
+ if (!this.clientRegistration) {
3582
+ throw new Error("Client not registered. Call registerClient first.");
3583
+ }
3584
+ const body = new URLSearchParams({
3585
+ grant_type: "authorization_code",
3586
+ client_id: this.clientRegistration.client_id,
3587
+ code,
3588
+ redirect_uri: this.config.redirectUri
3589
+ });
3590
+ if (codeVerifier) {
3591
+ body.append("code_verifier", codeVerifier);
3592
+ }
3593
+ const response = await fetch(this.discovery.token_endpoint, {
3594
+ method: "POST",
3595
+ headers: {
3596
+ "Content-Type": "application/x-www-form-urlencoded"
3597
+ },
3598
+ body: body.toString()
3599
+ });
3600
+ if (!response.ok) {
3601
+ const error = await response.text();
3602
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${error}`);
3603
+ }
3604
+ return await response.json();
3605
+ }
3606
+ /**
3607
+ * Handle OAuth callback and extract authorization code
3608
+ */
3609
+ handleCallback() {
3610
+ const urlParams = new URLSearchParams(window.location.search);
3611
+ const code = urlParams.get("code");
3612
+ const state = urlParams.get("state");
3613
+ if (!code || !state) {
3614
+ return null;
3615
+ }
3616
+ const url = new URL(window.location.href);
3617
+ url.searchParams.delete("code");
3618
+ url.searchParams.delete("state");
3619
+ window.history.replaceState({}, "", url.toString());
3620
+ return { code, state };
3621
+ }
3622
+ /**
3623
+ * Start OAuth flow by opening popup window (similar to your implementation)
3624
+ */
3625
+ async startOAuthFlow(serverUrl) {
3626
+ this.setState({
3627
+ isAuthenticating: true,
3628
+ authError: null
3629
+ });
3630
+ try {
3631
+ await this.discoverOAuthConfig(serverUrl);
3632
+ await this.registerClient(serverUrl);
3633
+ const authUrl = this.generateAuthUrl(serverUrl);
3634
+ const authWindow = window.open(
3635
+ authUrl,
3636
+ "mcp-oauth",
3637
+ "width=500,height=600,scrollbars=yes,resizable=yes,status=yes,location=yes"
3638
+ );
3639
+ if (!authWindow) {
3640
+ throw new Error("Failed to open authentication window. Please allow popups for this site and try again.");
3641
+ }
3642
+ console.log("\u2705 [OAuthHelper] OAuth popup opened successfully");
3643
+ } catch (error) {
3644
+ console.error("\u274C [OAuthHelper] Failed to start OAuth flow:", error);
3645
+ this.setState({
3646
+ isAuthenticating: false,
3647
+ authError: error instanceof Error ? error.message : "Failed to start authentication"
3648
+ });
3649
+ throw error;
3650
+ }
3651
+ }
3652
+ /**
3653
+ * Complete OAuth flow by exchanging code for token
3654
+ */
3655
+ async completeOAuthFlow(serverUrl, code) {
3656
+ this.setState({
3657
+ isCompletingOAuth: true,
3658
+ authError: null
3659
+ });
3660
+ try {
3661
+ const tokenResponse = await this.exchangeCodeForToken(serverUrl, code);
3662
+ this.setState({
3663
+ isAuthenticating: false,
3664
+ isAuthenticated: true,
3665
+ isCompletingOAuth: false,
3666
+ authError: null,
3667
+ oauthTokens: tokenResponse
3668
+ });
3669
+ console.log("\u2705 [OAuthHelper] OAuth flow completed successfully");
3670
+ return tokenResponse;
3671
+ } catch (error) {
3672
+ console.error("\u274C [OAuthHelper] Failed to complete OAuth flow:", error);
3673
+ this.setState({
3674
+ isAuthenticating: false,
3675
+ isCompletingOAuth: false,
3676
+ authError: error instanceof Error ? error.message : "Failed to complete authentication"
3677
+ });
3678
+ throw error;
3679
+ }
3680
+ }
3681
+ /**
3682
+ * Reset authentication state
3683
+ */
3684
+ resetAuth() {
3685
+ this.setState({
3686
+ isRequired: false,
3687
+ isAuthenticated: false,
3688
+ isAuthenticating: false,
3689
+ isCompletingOAuth: false,
3690
+ authError: null,
3691
+ oauthTokens: null
3692
+ });
3693
+ }
3694
+ /**
3695
+ * Set OAuth state (internal method)
3696
+ */
3697
+ setState(newState) {
3698
+ this.state = { ...this.state, ...newState };
3699
+ }
3700
+ /**
3701
+ * Generate a random state parameter for CSRF protection
3702
+ */
3703
+ generateState() {
3704
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
3705
+ }
3706
+ };
3707
+ var LINEAR_OAUTH_CONFIG = {
3708
+ // No clientId needed - will use dynamic client registration
3709
+ redirectUri: typeof window !== "undefined" ? window.location.origin + window.location.pathname : "http://localhost:5173",
3710
+ scope: "read write",
3711
+ clientName: "MCP Use Example"
3712
+ };
3713
+ function createOAuthMCPConfig(serverUrl, accessToken) {
3714
+ return {
3715
+ mcpServers: {
3716
+ linear: {
3717
+ url: serverUrl,
3718
+ authToken: accessToken,
3719
+ transport: "sse"
3720
+ }
3721
+ }
3722
+ };
3723
+ }
3724
+ __name(createOAuthMCPConfig, "createOAuthMCPConfig");
3725
+
3726
+ // index.ts
3727
+ import { AIMessage as AIMessage2, BaseMessage, HumanMessage as HumanMessage2, SystemMessage as SystemMessage3, ToolMessage as ToolMessage2 } from "@langchain/core/messages";
3728
+ export {
3729
+ AIMessage2 as AIMessage,
3730
+ AcquireActiveMCPServerTool,
3731
+ AddMCPServerFromConfigTool,
3732
+ BaseAdapter,
3733
+ BaseConnector,
3734
+ BaseMessage,
3735
+ BrowserOAuthClientProvider,
3736
+ ConnectMCPServerTool,
3737
+ HttpConnector,
3738
+ HumanMessage2 as HumanMessage,
3739
+ LINEAR_OAUTH_CONFIG,
3740
+ LangChainAdapter,
3741
+ ListMCPServersTool,
3742
+ Logger,
3743
+ MCPAgent,
3744
+ MCPClient,
3745
+ MCPSession,
3746
+ McpServer,
3747
+ OAuthHelper,
3748
+ ObservabilityManager,
3749
+ ReleaseMCPServerConnectionTool,
3750
+ RemoteAgent,
3751
+ ServerManager,
3752
+ StdioConnector,
3753
+ SystemMessage3 as SystemMessage,
3754
+ Telemetry,
3755
+ ToolMessage2 as ToolMessage,
3756
+ WebSocketConnector,
3757
+ createMCPServer,
3758
+ createOAuthMCPConfig,
3759
+ createReadableStreamFromGenerator,
3760
+ loadConfigFile,
3761
+ logger,
3762
+ onMcpAuthorization,
3763
+ setTelemetrySource,
3764
+ streamEventsToAISDK,
3765
+ streamEventsToAISDKWithTools,
3766
+ useMcp
3767
+ };