mcp-use 1.10.6 → 1.11.0-canary.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-D5WOXLJ2.js → chunk-A4WWKMPI.js} +2 -2
- package/dist/{chunk-BLWPCOUZ.js → chunk-APOF62EA.js} +3 -8
- package/dist/{chunk-FDKY2O5P.js → chunk-BE23AOUV.js} +1693 -146
- package/dist/{chunk-34R6SIER.js → chunk-FRUZDWXH.js} +1 -1
- package/dist/{chunk-CPG2WZUL.js → chunk-JRGQRPTN.js} +1 -1
- package/dist/{chunk-JH3ZOGLI.js → chunk-K6YNB2Z3.js} +2 -2
- package/dist/{chunk-EEUJZMOP.js → chunk-LHRGDQ5C.js} +1 -1
- package/dist/{chunk-44DFBJUL.js → chunk-OIXS25J5.js} +21 -372
- package/dist/chunk-QH52FRP3.js +101 -0
- package/dist/chunk-TCLI6SPF.js +12 -0
- package/dist/{chunk-KIWNNI6F.js → chunk-XXCHNDUF.js} +16 -2
- package/dist/index.cjs +4841 -4594
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1047
- package/dist/{langfuse-N5Y5BSXK.js → langfuse-74RGPTAH.js} +2 -2
- package/dist/src/adapters/base.d.ts +44 -0
- package/dist/src/adapters/base.d.ts.map +1 -1
- package/dist/src/adapters/langchain_adapter.d.ts +12 -1
- package/dist/src/adapters/langchain_adapter.d.ts.map +1 -1
- package/dist/src/agents/index.cjs +3090 -159
- package/dist/src/agents/index.d.ts +2 -0
- package/dist/src/agents/index.d.ts.map +1 -1
- package/dist/src/agents/index.js +8 -6
- package/dist/src/agents/mcp_agent.d.ts +59 -37
- package/dist/src/agents/mcp_agent.d.ts.map +1 -1
- package/dist/src/agents/remote.d.ts +25 -0
- package/dist/src/agents/remote.d.ts.map +1 -1
- package/dist/src/agents/types.d.ts +76 -0
- package/dist/src/agents/types.d.ts.map +1 -1
- package/dist/src/agents/utils/index.d.ts +1 -0
- package/dist/src/agents/utils/index.d.ts.map +1 -1
- package/dist/src/agents/utils/llm_provider.d.ts +53 -0
- package/dist/src/agents/utils/llm_provider.d.ts.map +1 -0
- package/dist/src/browser.cjs +1878 -495
- package/dist/src/browser.d.ts +0 -1
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +21 -12
- package/dist/src/client/browser.d.ts +2 -2
- package/dist/src/client/browser.d.ts.map +1 -1
- package/dist/src/client/prompts.cjs +1 -1
- package/dist/src/client/prompts.js +5 -4
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/connectors/base.d.ts +8 -0
- package/dist/src/connectors/base.d.ts.map +1 -1
- package/dist/src/connectors/index.d.ts +0 -1
- package/dist/src/connectors/index.d.ts.map +1 -1
- package/dist/src/managers/server_manager.d.ts.map +1 -1
- package/dist/src/managers/tools/connect_mcp_server.d.ts.map +1 -1
- package/dist/src/react/index.cjs +34 -284
- package/dist/src/react/index.js +6 -5
- package/dist/src/react/types.d.ts +1 -3
- package/dist/src/react/types.d.ts.map +1 -1
- package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
- package/dist/src/server/index.cjs +24 -4
- package/dist/src/server/index.js +28 -8
- package/dist/src/server/sessions/session-manager.d.ts +6 -3
- package/dist/src/server/sessions/session-manager.d.ts.map +1 -1
- package/dist/src/session.d.ts +14 -0
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/task_managers/index.d.ts +0 -1
- package/dist/src/task_managers/index.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/{tool-execution-helpers-4X6A63AS.js → tool-execution-helpers-MZUMRG5S.js} +3 -3
- package/package.json +20 -11
- package/dist/src/connectors/websocket.d.ts +0 -38
- package/dist/src/connectors/websocket.d.ts.map +0 -1
- package/dist/src/task_managers/websocket.d.ts +0 -18
- package/dist/src/task_managers/websocket.d.ts.map +0 -1
- /package/dist/{chunk-EW4MJSHA.js → chunk-H4BZVTGK.js} +0 -0
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CodeModeConnector
|
|
3
|
+
} from "./chunk-APOF62EA.js";
|
|
4
|
+
import {
|
|
5
|
+
BaseMCPClient,
|
|
6
|
+
ConnectionManager,
|
|
7
|
+
HttpConnector,
|
|
8
|
+
MCPSession
|
|
9
|
+
} from "./chunk-OIXS25J5.js";
|
|
10
|
+
import {
|
|
11
|
+
BaseConnector
|
|
12
|
+
} from "./chunk-XXCHNDUF.js";
|
|
13
|
+
import {
|
|
14
|
+
Tel,
|
|
2
15
|
Telemetry,
|
|
3
16
|
extractModelInfo,
|
|
4
17
|
getPackageVersion
|
|
5
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-K6YNB2Z3.js";
|
|
6
19
|
import {
|
|
7
20
|
logger
|
|
8
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-FRUZDWXH.js";
|
|
9
22
|
import {
|
|
10
|
-
__name
|
|
23
|
+
__name,
|
|
24
|
+
__require
|
|
11
25
|
} from "./chunk-3GQAWCBQ.js";
|
|
12
26
|
|
|
13
27
|
// src/adapters/base.ts
|
|
@@ -93,6 +107,98 @@ var BaseAdapter = class {
|
|
|
93
107
|
logger.debug(`Available tools: ${tools.length}`);
|
|
94
108
|
return tools;
|
|
95
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Dynamically load resources for a specific connector.
|
|
112
|
+
*
|
|
113
|
+
* @param connector The connector to load resources for.
|
|
114
|
+
* @returns The list of resources that were loaded in the target framework's format.
|
|
115
|
+
*/
|
|
116
|
+
async loadResourcesForConnector(connector) {
|
|
117
|
+
const connectorResources = [];
|
|
118
|
+
const success = await this.ensureConnectorInitialized(connector);
|
|
119
|
+
if (!success) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const resourcesResult = await connector.listAllResources();
|
|
124
|
+
const resources = resourcesResult?.resources || [];
|
|
125
|
+
if (this.convertResource) {
|
|
126
|
+
for (const resource of resources) {
|
|
127
|
+
const converted = this.convertResource(resource, connector);
|
|
128
|
+
if (converted) {
|
|
129
|
+
connectorResources.push(converted);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
logger.debug(
|
|
134
|
+
`Loaded ${connectorResources.length} new resources for connector: ${connectorResources.map((r) => r?.name ?? String(r)).join(", ")}`
|
|
135
|
+
);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
logger.warn(`Error loading resources for connector: ${err}`);
|
|
138
|
+
}
|
|
139
|
+
return connectorResources;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Dynamically load prompts for a specific connector.
|
|
143
|
+
*
|
|
144
|
+
* @param connector The connector to load prompts for.
|
|
145
|
+
* @returns The list of prompts that were loaded in the target framework's format.
|
|
146
|
+
*/
|
|
147
|
+
async loadPromptsForConnector(connector) {
|
|
148
|
+
const connectorPrompts = [];
|
|
149
|
+
const success = await this.ensureConnectorInitialized(connector);
|
|
150
|
+
if (!success) {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const promptsResult = await connector.listPrompts();
|
|
155
|
+
const prompts = promptsResult?.prompts || [];
|
|
156
|
+
if (this.convertPrompt) {
|
|
157
|
+
for (const prompt of prompts) {
|
|
158
|
+
const converted = this.convertPrompt(prompt, connector);
|
|
159
|
+
if (converted) {
|
|
160
|
+
connectorPrompts.push(converted);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
logger.debug(
|
|
165
|
+
`Loaded ${connectorPrompts.length} new prompts for connector: ${connectorPrompts.map((p) => p?.name ?? String(p)).join(", ")}`
|
|
166
|
+
);
|
|
167
|
+
} catch (err) {
|
|
168
|
+
logger.warn(`Error loading prompts for connector: ${err}`);
|
|
169
|
+
}
|
|
170
|
+
return connectorPrompts;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Create resources from MCP resources in all provided connectors.
|
|
174
|
+
*
|
|
175
|
+
* @param connectors List of MCP connectors to create resources from.
|
|
176
|
+
* @returns A promise that resolves with all converted resources.
|
|
177
|
+
*/
|
|
178
|
+
async createResourcesFromConnectors(connectors) {
|
|
179
|
+
const resources = [];
|
|
180
|
+
for (const connector of connectors) {
|
|
181
|
+
const connectorResources = await this.loadResourcesForConnector(connector);
|
|
182
|
+
resources.push(...connectorResources);
|
|
183
|
+
}
|
|
184
|
+
logger.debug(`Available resources: ${resources.length}`);
|
|
185
|
+
return resources;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create prompts from MCP prompts in all provided connectors.
|
|
189
|
+
*
|
|
190
|
+
* @param connectors List of MCP connectors to create prompts from.
|
|
191
|
+
* @returns A promise that resolves with all converted prompts.
|
|
192
|
+
*/
|
|
193
|
+
async createPromptsFromConnectors(connectors) {
|
|
194
|
+
const prompts = [];
|
|
195
|
+
for (const connector of connectors) {
|
|
196
|
+
const connectorPrompts = await this.loadPromptsForConnector(connector);
|
|
197
|
+
prompts.push(...connectorPrompts);
|
|
198
|
+
}
|
|
199
|
+
logger.debug(`Available prompts: ${prompts.length}`);
|
|
200
|
+
return prompts;
|
|
201
|
+
}
|
|
96
202
|
/**
|
|
97
203
|
* Check if a connector is initialized and has tools.
|
|
98
204
|
*
|
|
@@ -799,67 +905,1178 @@ var JSONSchemaToZod = class {
|
|
|
799
905
|
...baseSchema.properties,
|
|
800
906
|
...addSchema.properties
|
|
801
907
|
};
|
|
802
|
-
merged.properties = mergedProperties;
|
|
803
|
-
}
|
|
804
|
-
if (baseSchema.required && addSchema.required) {
|
|
805
|
-
const mergedRequired = [
|
|
806
|
-
.../* @__PURE__ */ new Set([...baseSchema.required, ...addSchema.required])
|
|
807
|
-
];
|
|
808
|
-
merged.required = mergedRequired;
|
|
908
|
+
merged.properties = mergedProperties;
|
|
909
|
+
}
|
|
910
|
+
if (baseSchema.required && addSchema.required) {
|
|
911
|
+
const mergedRequired = [
|
|
912
|
+
.../* @__PURE__ */ new Set([...baseSchema.required, ...addSchema.required])
|
|
913
|
+
];
|
|
914
|
+
merged.required = mergedRequired;
|
|
915
|
+
}
|
|
916
|
+
return merged;
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
|
|
920
|
+
// src/adapters/langchain_adapter.ts
|
|
921
|
+
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
922
|
+
import { z as z2 } from "zod";
|
|
923
|
+
function schemaToZod(schema) {
|
|
924
|
+
try {
|
|
925
|
+
return JSONSchemaToZod.convert(schema);
|
|
926
|
+
} catch (err) {
|
|
927
|
+
logger.warn(`Failed to convert JSON schema to Zod: ${err}`);
|
|
928
|
+
return z2.any();
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
__name(schemaToZod, "schemaToZod");
|
|
932
|
+
var LangChainAdapter = class extends BaseAdapter {
|
|
933
|
+
static {
|
|
934
|
+
__name(this, "LangChainAdapter");
|
|
935
|
+
}
|
|
936
|
+
constructor(disallowedTools = []) {
|
|
937
|
+
super(disallowedTools);
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Convert a single MCP tool specification into a LangChainJS structured tool.
|
|
941
|
+
*/
|
|
942
|
+
convertTool(mcpTool, connector) {
|
|
943
|
+
if (this.disallowedTools.includes(mcpTool.name)) {
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
const argsSchema = mcpTool.inputSchema ? schemaToZod(mcpTool.inputSchema) : z2.object({}).optional();
|
|
947
|
+
const tool = new DynamicStructuredTool({
|
|
948
|
+
name: mcpTool.name ?? "NO NAME",
|
|
949
|
+
description: mcpTool.description ?? "",
|
|
950
|
+
// Blank is acceptable but discouraged.
|
|
951
|
+
schema: argsSchema,
|
|
952
|
+
func: /* @__PURE__ */ __name(async (input) => {
|
|
953
|
+
logger.debug(
|
|
954
|
+
`MCP tool "${mcpTool.name}" received input: ${JSON.stringify(input)}`
|
|
955
|
+
);
|
|
956
|
+
try {
|
|
957
|
+
const result = await connector.callTool(
|
|
958
|
+
mcpTool.name,
|
|
959
|
+
input
|
|
960
|
+
);
|
|
961
|
+
return JSON.stringify(result);
|
|
962
|
+
} catch (err) {
|
|
963
|
+
logger.error(`Error executing MCP tool: ${err.message}`);
|
|
964
|
+
return `Error executing MCP tool: ${String(err)}`;
|
|
965
|
+
}
|
|
966
|
+
}, "func")
|
|
967
|
+
});
|
|
968
|
+
return tool;
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Convert a single MCP resource into a LangChainJS structured tool.
|
|
972
|
+
* Each resource becomes an async tool that returns its content when called.
|
|
973
|
+
*/
|
|
974
|
+
convertResource(mcpResource, connector) {
|
|
975
|
+
const sanitizeName = /* @__PURE__ */ __name((name) => {
|
|
976
|
+
return name.replace(/[^A-Za-z0-9_]+/g, "_").toLowerCase().replace(/^_+|_+$/g, "");
|
|
977
|
+
}, "sanitizeName");
|
|
978
|
+
const resourceName = sanitizeName(
|
|
979
|
+
mcpResource.name || `resource_${mcpResource.uri}`
|
|
980
|
+
);
|
|
981
|
+
const resourceUri = mcpResource.uri;
|
|
982
|
+
const tool = new DynamicStructuredTool({
|
|
983
|
+
name: resourceName,
|
|
984
|
+
description: mcpResource.description || `Return the content of the resource located at URI ${resourceUri}.`,
|
|
985
|
+
schema: z2.object({}).optional(),
|
|
986
|
+
// Resources take no arguments
|
|
987
|
+
func: /* @__PURE__ */ __name(async () => {
|
|
988
|
+
logger.debug(`Resource tool: "${resourceName}" called`);
|
|
989
|
+
try {
|
|
990
|
+
const result = await connector.readResource(resourceUri);
|
|
991
|
+
if (result.contents && result.contents.length > 0) {
|
|
992
|
+
return result.contents.map((content) => {
|
|
993
|
+
if (typeof content === "string") {
|
|
994
|
+
return content;
|
|
995
|
+
}
|
|
996
|
+
if (content.text) {
|
|
997
|
+
return content.text;
|
|
998
|
+
}
|
|
999
|
+
if (content.uri) {
|
|
1000
|
+
return content.uri;
|
|
1001
|
+
}
|
|
1002
|
+
return JSON.stringify(content);
|
|
1003
|
+
}).join("\n");
|
|
1004
|
+
}
|
|
1005
|
+
return "Resource is empty or unavailable";
|
|
1006
|
+
} catch (err) {
|
|
1007
|
+
logger.error(`Error reading resource: ${err.message}`);
|
|
1008
|
+
return `Error reading resource: ${String(err)}`;
|
|
1009
|
+
}
|
|
1010
|
+
}, "func")
|
|
1011
|
+
});
|
|
1012
|
+
return tool;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Convert a single MCP prompt into a LangChainJS structured tool.
|
|
1016
|
+
* The resulting tool executes getPrompt on the connector with the prompt's name
|
|
1017
|
+
* and the user-provided arguments (if any).
|
|
1018
|
+
*/
|
|
1019
|
+
convertPrompt(mcpPrompt, connector) {
|
|
1020
|
+
let argsSchema = z2.object({}).optional();
|
|
1021
|
+
if (mcpPrompt.arguments && mcpPrompt.arguments.length > 0) {
|
|
1022
|
+
const schemaFields = {};
|
|
1023
|
+
for (const arg of mcpPrompt.arguments) {
|
|
1024
|
+
const zodType = z2.string();
|
|
1025
|
+
if (arg.required !== false) {
|
|
1026
|
+
schemaFields[arg.name] = zodType;
|
|
1027
|
+
} else {
|
|
1028
|
+
schemaFields[arg.name] = zodType.optional();
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
argsSchema = Object.keys(schemaFields).length > 0 ? z2.object(schemaFields) : z2.object({}).optional();
|
|
1032
|
+
}
|
|
1033
|
+
const tool = new DynamicStructuredTool({
|
|
1034
|
+
name: mcpPrompt.name,
|
|
1035
|
+
description: mcpPrompt.description || "",
|
|
1036
|
+
schema: argsSchema,
|
|
1037
|
+
func: /* @__PURE__ */ __name(async (input) => {
|
|
1038
|
+
logger.debug(
|
|
1039
|
+
`Prompt tool: "${mcpPrompt.name}" called with args: ${JSON.stringify(input)}`
|
|
1040
|
+
);
|
|
1041
|
+
try {
|
|
1042
|
+
const result = await connector.getPrompt(mcpPrompt.name, input);
|
|
1043
|
+
if (result.messages && result.messages.length > 0) {
|
|
1044
|
+
return result.messages.map((msg) => {
|
|
1045
|
+
if (typeof msg === "string") {
|
|
1046
|
+
return msg;
|
|
1047
|
+
}
|
|
1048
|
+
if (msg.content) {
|
|
1049
|
+
return typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
1050
|
+
}
|
|
1051
|
+
return JSON.stringify(msg);
|
|
1052
|
+
}).join("\n");
|
|
1053
|
+
}
|
|
1054
|
+
return "Prompt returned no messages";
|
|
1055
|
+
} catch (err) {
|
|
1056
|
+
logger.error(`Error getting prompt: ${err.message}`);
|
|
1057
|
+
return `Error getting prompt: ${String(err)}`;
|
|
1058
|
+
}
|
|
1059
|
+
}, "func")
|
|
1060
|
+
});
|
|
1061
|
+
return tool;
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
// src/client/executors/base.ts
|
|
1066
|
+
var BaseCodeExecutor = class {
|
|
1067
|
+
static {
|
|
1068
|
+
__name(this, "BaseCodeExecutor");
|
|
1069
|
+
}
|
|
1070
|
+
client;
|
|
1071
|
+
_connecting = false;
|
|
1072
|
+
constructor(client) {
|
|
1073
|
+
this.client = client;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Ensure all configured MCP servers are connected before execution.
|
|
1077
|
+
* Prevents race conditions with a connection lock.
|
|
1078
|
+
*/
|
|
1079
|
+
async ensureServersConnected() {
|
|
1080
|
+
const configuredServers = this.client.getServerNames();
|
|
1081
|
+
const activeSessions = Object.keys(this.client.getAllActiveSessions());
|
|
1082
|
+
const missingServers = configuredServers.filter(
|
|
1083
|
+
(s) => !activeSessions.includes(s)
|
|
1084
|
+
);
|
|
1085
|
+
if (missingServers.length > 0 && !this._connecting) {
|
|
1086
|
+
this._connecting = true;
|
|
1087
|
+
try {
|
|
1088
|
+
logger.debug(
|
|
1089
|
+
`Connecting to configured servers for code execution: ${missingServers.join(", ")}`
|
|
1090
|
+
);
|
|
1091
|
+
await this.client.createAllSessions();
|
|
1092
|
+
} finally {
|
|
1093
|
+
this._connecting = false;
|
|
1094
|
+
}
|
|
1095
|
+
} else if (missingServers.length > 0 && this._connecting) {
|
|
1096
|
+
logger.debug("Waiting for ongoing server connection...");
|
|
1097
|
+
const startWait = Date.now();
|
|
1098
|
+
while (this._connecting && Date.now() - startWait < 5e3) {
|
|
1099
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Get tool namespace information from all active MCP sessions.
|
|
1105
|
+
* Filters out the internal code_mode server.
|
|
1106
|
+
*/
|
|
1107
|
+
getToolNamespaces() {
|
|
1108
|
+
const namespaces = [];
|
|
1109
|
+
const activeSessions = this.client.getAllActiveSessions();
|
|
1110
|
+
for (const [serverName, session] of Object.entries(activeSessions)) {
|
|
1111
|
+
if (serverName === "code_mode") continue;
|
|
1112
|
+
try {
|
|
1113
|
+
const connector = session.connector;
|
|
1114
|
+
let tools;
|
|
1115
|
+
try {
|
|
1116
|
+
tools = connector.tools;
|
|
1117
|
+
} catch (e) {
|
|
1118
|
+
logger.warn(`Tools not available for server ${serverName}: ${e}`);
|
|
1119
|
+
continue;
|
|
1120
|
+
}
|
|
1121
|
+
if (!tools || tools.length === 0) continue;
|
|
1122
|
+
namespaces.push({ serverName, tools, session });
|
|
1123
|
+
} catch (e) {
|
|
1124
|
+
logger.warn(`Failed to load tools for server ${serverName}: ${e}`);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
return namespaces;
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Create a search function for discovering available MCP tools.
|
|
1131
|
+
* Used by code execution environments to find tools at runtime.
|
|
1132
|
+
*/
|
|
1133
|
+
createSearchToolsFunction() {
|
|
1134
|
+
return async (query = "", detailLevel = "full") => {
|
|
1135
|
+
const allTools = [];
|
|
1136
|
+
const allNamespaces = /* @__PURE__ */ new Set();
|
|
1137
|
+
const queryLower = query.toLowerCase();
|
|
1138
|
+
const activeSessions = this.client.getAllActiveSessions();
|
|
1139
|
+
for (const [serverName, session] of Object.entries(activeSessions)) {
|
|
1140
|
+
if (serverName === "code_mode") continue;
|
|
1141
|
+
try {
|
|
1142
|
+
const tools = session.connector.tools;
|
|
1143
|
+
if (tools && tools.length > 0) {
|
|
1144
|
+
allNamespaces.add(serverName);
|
|
1145
|
+
}
|
|
1146
|
+
for (const tool of tools) {
|
|
1147
|
+
if (detailLevel === "names") {
|
|
1148
|
+
allTools.push({ name: tool.name, server: serverName });
|
|
1149
|
+
} else if (detailLevel === "descriptions") {
|
|
1150
|
+
allTools.push({
|
|
1151
|
+
name: tool.name,
|
|
1152
|
+
server: serverName,
|
|
1153
|
+
description: tool.description
|
|
1154
|
+
});
|
|
1155
|
+
} else {
|
|
1156
|
+
allTools.push({
|
|
1157
|
+
name: tool.name,
|
|
1158
|
+
server: serverName,
|
|
1159
|
+
description: tool.description,
|
|
1160
|
+
input_schema: tool.inputSchema
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
} catch (e) {
|
|
1165
|
+
logger.warn(`Failed to search tools in server ${serverName}: ${e}`);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
let filteredTools = allTools;
|
|
1169
|
+
if (query) {
|
|
1170
|
+
filteredTools = allTools.filter((tool) => {
|
|
1171
|
+
const nameMatch = tool.name.toLowerCase().includes(queryLower);
|
|
1172
|
+
const descMatch = tool.description?.toLowerCase().includes(queryLower);
|
|
1173
|
+
const serverMatch = tool.server.toLowerCase().includes(queryLower);
|
|
1174
|
+
return nameMatch || descMatch || serverMatch;
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
return {
|
|
1178
|
+
meta: {
|
|
1179
|
+
total_tools: allTools.length,
|
|
1180
|
+
namespaces: Array.from(allNamespaces).sort(),
|
|
1181
|
+
result_count: filteredTools.length
|
|
1182
|
+
},
|
|
1183
|
+
results: filteredTools
|
|
1184
|
+
};
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
// src/client/executors/e2b.ts
|
|
1190
|
+
var E2BCodeExecutor = class extends BaseCodeExecutor {
|
|
1191
|
+
static {
|
|
1192
|
+
__name(this, "E2BCodeExecutor");
|
|
1193
|
+
}
|
|
1194
|
+
e2bApiKey;
|
|
1195
|
+
codeExecSandbox = null;
|
|
1196
|
+
SandboxClass = null;
|
|
1197
|
+
timeoutMs;
|
|
1198
|
+
constructor(client, options) {
|
|
1199
|
+
super(client);
|
|
1200
|
+
this.e2bApiKey = options.apiKey;
|
|
1201
|
+
this.timeoutMs = options.timeoutMs ?? 3e5;
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Lazy load E2B Sandbox class.
|
|
1205
|
+
* This allows the library to work without E2B installed.
|
|
1206
|
+
*/
|
|
1207
|
+
async ensureSandboxClass() {
|
|
1208
|
+
if (this.SandboxClass) return;
|
|
1209
|
+
try {
|
|
1210
|
+
const e2b = await import("@e2b/code-interpreter");
|
|
1211
|
+
this.SandboxClass = e2b.Sandbox;
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
throw new Error(
|
|
1214
|
+
"@e2b/code-interpreter is not installed. The E2B code executor requires this optional dependency. Install it with: yarn add @e2b/code-interpreter"
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Get or create a dedicated sandbox for code execution.
|
|
1220
|
+
*/
|
|
1221
|
+
async getOrCreateCodeExecSandbox() {
|
|
1222
|
+
if (this.codeExecSandbox) return this.codeExecSandbox;
|
|
1223
|
+
await this.ensureSandboxClass();
|
|
1224
|
+
logger.debug("Starting E2B sandbox for code execution...");
|
|
1225
|
+
this.codeExecSandbox = await this.SandboxClass.create("base", {
|
|
1226
|
+
apiKey: this.e2bApiKey,
|
|
1227
|
+
timeoutMs: this.timeoutMs
|
|
1228
|
+
});
|
|
1229
|
+
return this.codeExecSandbox;
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Generate the shim code that exposes tools to the sandbox environment.
|
|
1233
|
+
* Creates a bridge that intercepts tool calls and sends them back to host.
|
|
1234
|
+
*/
|
|
1235
|
+
generateShim(tools) {
|
|
1236
|
+
let shim = `
|
|
1237
|
+
// MCP Bridge Shim
|
|
1238
|
+
global.__callMcpTool = async (server, tool, args) => {
|
|
1239
|
+
const id = Math.random().toString(36).substring(7);
|
|
1240
|
+
console.log(JSON.stringify({
|
|
1241
|
+
type: '__MCP_TOOL_CALL__',
|
|
1242
|
+
id,
|
|
1243
|
+
server,
|
|
1244
|
+
tool,
|
|
1245
|
+
args
|
|
1246
|
+
}));
|
|
1247
|
+
|
|
1248
|
+
const resultPath = \`/tmp/mcp_result_\${id}.json\`;
|
|
1249
|
+
const fs = require('fs');
|
|
1250
|
+
|
|
1251
|
+
// Poll for result file
|
|
1252
|
+
let attempts = 0;
|
|
1253
|
+
while (attempts < 300) { // 30 seconds timeout
|
|
1254
|
+
if (fs.existsSync(resultPath)) {
|
|
1255
|
+
const content = fs.readFileSync(resultPath, 'utf8');
|
|
1256
|
+
const result = JSON.parse(content);
|
|
1257
|
+
fs.unlinkSync(resultPath); // Clean up
|
|
1258
|
+
|
|
1259
|
+
if (result.error) {
|
|
1260
|
+
throw new Error(result.error);
|
|
1261
|
+
}
|
|
1262
|
+
return result.data;
|
|
1263
|
+
}
|
|
1264
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
1265
|
+
attempts++;
|
|
1266
|
+
}
|
|
1267
|
+
throw new Error('Tool execution timed out');
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
// Global search_tools helper
|
|
1271
|
+
global.search_tools = async (query, detailLevel = 'full') => {
|
|
1272
|
+
const allTools = ${JSON.stringify(
|
|
1273
|
+
Object.entries(tools).flatMap(
|
|
1274
|
+
([server, serverTools]) => serverTools.map((tool) => ({
|
|
1275
|
+
name: tool.name,
|
|
1276
|
+
description: tool.description,
|
|
1277
|
+
server,
|
|
1278
|
+
input_schema: tool.inputSchema
|
|
1279
|
+
}))
|
|
1280
|
+
)
|
|
1281
|
+
)};
|
|
1282
|
+
|
|
1283
|
+
const filtered = allTools.filter(tool => {
|
|
1284
|
+
if (!query) return true;
|
|
1285
|
+
const q = query.toLowerCase();
|
|
1286
|
+
return tool.name.toLowerCase().includes(q) ||
|
|
1287
|
+
(tool.description && tool.description.toLowerCase().includes(q));
|
|
1288
|
+
});
|
|
1289
|
+
|
|
1290
|
+
if (detailLevel === 'names') {
|
|
1291
|
+
return filtered.map(t => ({ name: t.name, server: t.server }));
|
|
1292
|
+
} else if (detailLevel === 'descriptions') {
|
|
1293
|
+
return filtered.map(t => ({ name: t.name, server: t.server, description: t.description }));
|
|
1294
|
+
}
|
|
1295
|
+
return filtered;
|
|
1296
|
+
};
|
|
1297
|
+
`;
|
|
1298
|
+
for (const [serverName, serverTools] of Object.entries(tools)) {
|
|
1299
|
+
if (!serverTools || serverTools.length === 0) continue;
|
|
1300
|
+
const safeServerName = serverName.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
1301
|
+
shim += `
|
|
1302
|
+
global['${serverName}'] = {`;
|
|
1303
|
+
for (const tool of serverTools) {
|
|
1304
|
+
shim += `
|
|
1305
|
+
'${tool.name}': async (args) => await global.__callMcpTool('${serverName}', '${tool.name}', args),`;
|
|
1306
|
+
}
|
|
1307
|
+
shim += `
|
|
1308
|
+
};
|
|
1309
|
+
|
|
1310
|
+
// Also expose as safe name if different
|
|
1311
|
+
if ('${safeServerName}' !== '${serverName}') {
|
|
1312
|
+
global['${safeServerName}'] = global['${serverName}'];
|
|
1313
|
+
}
|
|
1314
|
+
`;
|
|
1315
|
+
}
|
|
1316
|
+
return shim;
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Build the tool catalog for the shim.
|
|
1320
|
+
* Returns a map of server names to their available tools.
|
|
1321
|
+
*/
|
|
1322
|
+
buildToolCatalog() {
|
|
1323
|
+
const catalog = {};
|
|
1324
|
+
const namespaces = this.getToolNamespaces();
|
|
1325
|
+
for (const { serverName, tools } of namespaces) {
|
|
1326
|
+
catalog[serverName] = tools;
|
|
1327
|
+
}
|
|
1328
|
+
return catalog;
|
|
1329
|
+
}
|
|
1330
|
+
/**
|
|
1331
|
+
* Execute JavaScript/TypeScript code in an E2B sandbox with MCP tool access.
|
|
1332
|
+
* Tool calls are proxied back to the host via the bridge pattern.
|
|
1333
|
+
*
|
|
1334
|
+
* @param code - Code to execute
|
|
1335
|
+
* @param timeout - Execution timeout in milliseconds (default: 30000)
|
|
1336
|
+
*/
|
|
1337
|
+
async execute(code, timeout = 3e4) {
|
|
1338
|
+
const startTime = Date.now();
|
|
1339
|
+
let result = null;
|
|
1340
|
+
let error = null;
|
|
1341
|
+
let logs = [];
|
|
1342
|
+
try {
|
|
1343
|
+
await this.ensureServersConnected();
|
|
1344
|
+
const sandbox = await this.getOrCreateCodeExecSandbox();
|
|
1345
|
+
const toolCatalog = this.buildToolCatalog();
|
|
1346
|
+
const shim = this.generateShim(toolCatalog);
|
|
1347
|
+
const wrappedCode = `
|
|
1348
|
+
${shim}
|
|
1349
|
+
|
|
1350
|
+
(async () => {
|
|
1351
|
+
try {
|
|
1352
|
+
const func = async () => {
|
|
1353
|
+
${code}
|
|
1354
|
+
};
|
|
1355
|
+
const result = await func();
|
|
1356
|
+
console.log('__MCP_RESULT_START__');
|
|
1357
|
+
console.log(JSON.stringify(result));
|
|
1358
|
+
console.log('__MCP_RESULT_END__');
|
|
1359
|
+
} catch (e) {
|
|
1360
|
+
console.error(e);
|
|
1361
|
+
process.exit(1);
|
|
1362
|
+
}
|
|
1363
|
+
})();
|
|
1364
|
+
`;
|
|
1365
|
+
const filename = `exec_${Date.now()}.js`;
|
|
1366
|
+
await sandbox.files.write(filename, wrappedCode);
|
|
1367
|
+
const execution = await sandbox.commands.run(`node ${filename}`, {
|
|
1368
|
+
timeoutMs: timeout,
|
|
1369
|
+
onStdout: /* @__PURE__ */ __name(async (data) => {
|
|
1370
|
+
try {
|
|
1371
|
+
const lines = data.split("\n");
|
|
1372
|
+
for (const line of lines) {
|
|
1373
|
+
if (line.trim().startsWith('{"type":"__MCP_TOOL_CALL__"')) {
|
|
1374
|
+
const call = JSON.parse(line);
|
|
1375
|
+
if (call.type === "__MCP_TOOL_CALL__") {
|
|
1376
|
+
try {
|
|
1377
|
+
logger.debug(
|
|
1378
|
+
`[E2B Bridge] Calling tool ${call.server}.${call.tool}`
|
|
1379
|
+
);
|
|
1380
|
+
const activeSessions = this.client.getAllActiveSessions();
|
|
1381
|
+
const session = activeSessions[call.server];
|
|
1382
|
+
if (!session) {
|
|
1383
|
+
throw new Error(`Server ${call.server} not found`);
|
|
1384
|
+
}
|
|
1385
|
+
const toolResult = await session.connector.callTool(
|
|
1386
|
+
call.tool,
|
|
1387
|
+
call.args
|
|
1388
|
+
);
|
|
1389
|
+
let extractedResult = toolResult;
|
|
1390
|
+
if (toolResult.content && toolResult.content.length > 0) {
|
|
1391
|
+
const item = toolResult.content[0];
|
|
1392
|
+
if (item.type === "text") {
|
|
1393
|
+
try {
|
|
1394
|
+
extractedResult = JSON.parse(item.text);
|
|
1395
|
+
} catch {
|
|
1396
|
+
extractedResult = item.text;
|
|
1397
|
+
}
|
|
1398
|
+
} else {
|
|
1399
|
+
extractedResult = item;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
const resultPath = `/tmp/mcp_result_${call.id}.json`;
|
|
1403
|
+
await sandbox.files.write(
|
|
1404
|
+
resultPath,
|
|
1405
|
+
JSON.stringify({ data: extractedResult })
|
|
1406
|
+
);
|
|
1407
|
+
} catch (err) {
|
|
1408
|
+
logger.error(
|
|
1409
|
+
`[E2B Bridge] Tool execution failed: ${err.message}`
|
|
1410
|
+
);
|
|
1411
|
+
const resultPath = `/tmp/mcp_result_${call.id}.json`;
|
|
1412
|
+
await sandbox.files.write(
|
|
1413
|
+
resultPath,
|
|
1414
|
+
JSON.stringify({
|
|
1415
|
+
error: err.message || String(err)
|
|
1416
|
+
})
|
|
1417
|
+
);
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
} catch (e) {
|
|
1423
|
+
}
|
|
1424
|
+
}, "onStdout")
|
|
1425
|
+
});
|
|
1426
|
+
logs = [execution.stdout, execution.stderr].filter(Boolean);
|
|
1427
|
+
if (execution.exitCode !== 0) {
|
|
1428
|
+
error = execution.stderr || "Execution failed";
|
|
1429
|
+
} else {
|
|
1430
|
+
const stdout = execution.stdout;
|
|
1431
|
+
const startMarker = "__MCP_RESULT_START__";
|
|
1432
|
+
const endMarker = "__MCP_RESULT_END__";
|
|
1433
|
+
const startIndex = stdout.indexOf(startMarker);
|
|
1434
|
+
const endIndex = stdout.indexOf(endMarker);
|
|
1435
|
+
if (startIndex !== -1 && endIndex !== -1) {
|
|
1436
|
+
const jsonStr = stdout.substring(startIndex + startMarker.length, endIndex).trim();
|
|
1437
|
+
try {
|
|
1438
|
+
result = JSON.parse(jsonStr);
|
|
1439
|
+
} catch (e) {
|
|
1440
|
+
result = jsonStr;
|
|
1441
|
+
}
|
|
1442
|
+
logs = logs.map((log) => {
|
|
1443
|
+
let cleaned = log.replace(
|
|
1444
|
+
new RegExp(startMarker + "[\\s\\S]*?" + endMarker),
|
|
1445
|
+
"[Result captured]"
|
|
1446
|
+
);
|
|
1447
|
+
cleaned = cleaned.split("\n").filter((l) => !l.includes("__MCP_TOOL_CALL__")).join("\n");
|
|
1448
|
+
return cleaned;
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
} catch (e) {
|
|
1453
|
+
error = e.message || String(e);
|
|
1454
|
+
if (error && (error.includes("timeout") || error.includes("timed out"))) {
|
|
1455
|
+
error = "Script execution timed out";
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
return {
|
|
1459
|
+
result,
|
|
1460
|
+
logs,
|
|
1461
|
+
error,
|
|
1462
|
+
execution_time: (Date.now() - startTime) / 1e3
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* Clean up the E2B sandbox.
|
|
1467
|
+
* Should be called when the executor is no longer needed.
|
|
1468
|
+
*/
|
|
1469
|
+
async cleanup() {
|
|
1470
|
+
if (this.codeExecSandbox) {
|
|
1471
|
+
try {
|
|
1472
|
+
await this.codeExecSandbox.kill();
|
|
1473
|
+
this.codeExecSandbox = null;
|
|
1474
|
+
logger.debug("E2B code execution sandbox stopped");
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
logger.error("Failed to stop E2B code execution sandbox:", error);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
|
|
1482
|
+
// src/client/executors/vm.ts
|
|
1483
|
+
var vm = null;
|
|
1484
|
+
var vmCheckAttempted = false;
|
|
1485
|
+
function getVMModuleName() {
|
|
1486
|
+
return ["node", "vm"].join(":");
|
|
1487
|
+
}
|
|
1488
|
+
__name(getVMModuleName, "getVMModuleName");
|
|
1489
|
+
function tryLoadVM() {
|
|
1490
|
+
if (vmCheckAttempted) {
|
|
1491
|
+
return vm !== null;
|
|
1492
|
+
}
|
|
1493
|
+
vmCheckAttempted = true;
|
|
1494
|
+
try {
|
|
1495
|
+
const nodeRequire = typeof __require !== "undefined" ? __require : null;
|
|
1496
|
+
if (nodeRequire) {
|
|
1497
|
+
vm = nodeRequire(getVMModuleName());
|
|
1498
|
+
return true;
|
|
1499
|
+
}
|
|
1500
|
+
} catch (error) {
|
|
1501
|
+
logger.debug("node:vm module not available via require");
|
|
1502
|
+
}
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
__name(tryLoadVM, "tryLoadVM");
|
|
1506
|
+
async function tryLoadVMAsync() {
|
|
1507
|
+
if (vm !== null) {
|
|
1508
|
+
return true;
|
|
1509
|
+
}
|
|
1510
|
+
if (!vmCheckAttempted) {
|
|
1511
|
+
if (tryLoadVM()) {
|
|
1512
|
+
return true;
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
try {
|
|
1516
|
+
vm = await import(
|
|
1517
|
+
/* @vite-ignore */
|
|
1518
|
+
getVMModuleName()
|
|
1519
|
+
);
|
|
1520
|
+
return true;
|
|
1521
|
+
} catch (error) {
|
|
1522
|
+
logger.debug(
|
|
1523
|
+
"node:vm module not available in this environment (e.g., Deno)"
|
|
1524
|
+
);
|
|
1525
|
+
return false;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
__name(tryLoadVMAsync, "tryLoadVMAsync");
|
|
1529
|
+
function isVMAvailable() {
|
|
1530
|
+
tryLoadVM();
|
|
1531
|
+
return vm !== null;
|
|
1532
|
+
}
|
|
1533
|
+
__name(isVMAvailable, "isVMAvailable");
|
|
1534
|
+
var VMCodeExecutor = class extends BaseCodeExecutor {
|
|
1535
|
+
static {
|
|
1536
|
+
__name(this, "VMCodeExecutor");
|
|
1537
|
+
}
|
|
1538
|
+
defaultTimeout;
|
|
1539
|
+
memoryLimitMb;
|
|
1540
|
+
constructor(client, options) {
|
|
1541
|
+
super(client);
|
|
1542
|
+
this.defaultTimeout = options?.timeoutMs ?? 3e4;
|
|
1543
|
+
this.memoryLimitMb = options?.memoryLimitMb;
|
|
1544
|
+
tryLoadVM();
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Ensure VM module is loaded before execution
|
|
1548
|
+
*/
|
|
1549
|
+
async ensureVMLoaded() {
|
|
1550
|
+
if (vm !== null) {
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
const loaded = await tryLoadVMAsync();
|
|
1554
|
+
if (!loaded) {
|
|
1555
|
+
throw new Error(
|
|
1556
|
+
"node:vm module is not available in this environment. Please use E2B executor instead or run in a Node.js environment."
|
|
1557
|
+
);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Execute JavaScript/TypeScript code with access to MCP tools.
|
|
1562
|
+
*
|
|
1563
|
+
* @param code - Code to execute
|
|
1564
|
+
* @param timeout - Execution timeout in milliseconds (default: configured timeout or 30000)
|
|
1565
|
+
*/
|
|
1566
|
+
async execute(code, timeout) {
|
|
1567
|
+
const effectiveTimeout = timeout ?? this.defaultTimeout;
|
|
1568
|
+
await this.ensureVMLoaded();
|
|
1569
|
+
await this.ensureServersConnected();
|
|
1570
|
+
const logs = [];
|
|
1571
|
+
const startTime = Date.now();
|
|
1572
|
+
let result = null;
|
|
1573
|
+
let error = null;
|
|
1574
|
+
try {
|
|
1575
|
+
const context = await this._buildContext(logs);
|
|
1576
|
+
const wrappedCode = `
|
|
1577
|
+
(async () => {
|
|
1578
|
+
try {
|
|
1579
|
+
${code}
|
|
1580
|
+
} catch (e) {
|
|
1581
|
+
throw e;
|
|
1582
|
+
}
|
|
1583
|
+
})()
|
|
1584
|
+
`;
|
|
1585
|
+
const script = new vm.Script(wrappedCode, {
|
|
1586
|
+
filename: "agent_code.js"
|
|
1587
|
+
});
|
|
1588
|
+
const promise = script.runInNewContext(context, {
|
|
1589
|
+
timeout: effectiveTimeout,
|
|
1590
|
+
displayErrors: true
|
|
1591
|
+
});
|
|
1592
|
+
result = await promise;
|
|
1593
|
+
} catch (e) {
|
|
1594
|
+
error = e.message || String(e);
|
|
1595
|
+
if (e.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || e.message === "Script execution timed out." || typeof error === "string" && (error.includes("timed out") || error.includes("timeout"))) {
|
|
1596
|
+
error = "Script execution timed out";
|
|
1597
|
+
}
|
|
1598
|
+
if (e.stack) {
|
|
1599
|
+
logger.debug(`Code execution error stack: ${e.stack}`);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
const executionTime = (Date.now() - startTime) / 1e3;
|
|
1603
|
+
return {
|
|
1604
|
+
result,
|
|
1605
|
+
logs,
|
|
1606
|
+
error,
|
|
1607
|
+
execution_time: executionTime
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Build the VM execution context with MCP tools and standard globals.
|
|
1612
|
+
*
|
|
1613
|
+
* @param logs - Array to capture console output
|
|
1614
|
+
*/
|
|
1615
|
+
async _buildContext(logs) {
|
|
1616
|
+
const logHandler = /* @__PURE__ */ __name((...args) => {
|
|
1617
|
+
logs.push(
|
|
1618
|
+
args.map(
|
|
1619
|
+
(arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
|
|
1620
|
+
).join(" ")
|
|
1621
|
+
);
|
|
1622
|
+
}, "logHandler");
|
|
1623
|
+
const sandbox = {
|
|
1624
|
+
console: {
|
|
1625
|
+
log: logHandler,
|
|
1626
|
+
error: /* @__PURE__ */ __name((...args) => {
|
|
1627
|
+
logHandler("[ERROR]", ...args);
|
|
1628
|
+
}, "error"),
|
|
1629
|
+
warn: /* @__PURE__ */ __name((...args) => {
|
|
1630
|
+
logHandler("[WARN]", ...args);
|
|
1631
|
+
}, "warn"),
|
|
1632
|
+
info: logHandler,
|
|
1633
|
+
debug: logHandler
|
|
1634
|
+
},
|
|
1635
|
+
// Standard globals
|
|
1636
|
+
Object,
|
|
1637
|
+
Array,
|
|
1638
|
+
String,
|
|
1639
|
+
Number,
|
|
1640
|
+
Boolean,
|
|
1641
|
+
Date,
|
|
1642
|
+
Math,
|
|
1643
|
+
JSON,
|
|
1644
|
+
RegExp,
|
|
1645
|
+
Map,
|
|
1646
|
+
Set,
|
|
1647
|
+
Promise,
|
|
1648
|
+
parseInt,
|
|
1649
|
+
parseFloat,
|
|
1650
|
+
isNaN,
|
|
1651
|
+
isFinite,
|
|
1652
|
+
encodeURI,
|
|
1653
|
+
decodeURI,
|
|
1654
|
+
encodeURIComponent,
|
|
1655
|
+
decodeURIComponent,
|
|
1656
|
+
setTimeout,
|
|
1657
|
+
clearTimeout,
|
|
1658
|
+
// Helper for tools
|
|
1659
|
+
search_tools: this.createSearchToolsFunction(),
|
|
1660
|
+
__tool_namespaces: []
|
|
1661
|
+
};
|
|
1662
|
+
const toolNamespaces = {};
|
|
1663
|
+
const namespaceInfos = this.getToolNamespaces();
|
|
1664
|
+
for (const { serverName, tools, session } of namespaceInfos) {
|
|
1665
|
+
const serverNamespace = {};
|
|
1666
|
+
for (const tool of tools) {
|
|
1667
|
+
const toolName = tool.name;
|
|
1668
|
+
serverNamespace[toolName] = async (args) => {
|
|
1669
|
+
const result = await session.connector.callTool(toolName, args || {});
|
|
1670
|
+
if (result.content && result.content.length > 0) {
|
|
1671
|
+
const item = result.content[0];
|
|
1672
|
+
if (item.type === "text") {
|
|
1673
|
+
try {
|
|
1674
|
+
return JSON.parse(item.text);
|
|
1675
|
+
} catch {
|
|
1676
|
+
return item.text;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return item;
|
|
1680
|
+
}
|
|
1681
|
+
return result;
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
sandbox[serverName] = serverNamespace;
|
|
1685
|
+
toolNamespaces[serverName] = true;
|
|
1686
|
+
}
|
|
1687
|
+
sandbox.__tool_namespaces = Object.keys(toolNamespaces);
|
|
1688
|
+
return vm.createContext(sandbox);
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Clean up resources.
|
|
1692
|
+
* VM executor doesn't need cleanup, but method kept for interface consistency.
|
|
1693
|
+
*/
|
|
1694
|
+
async cleanup() {
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
|
|
1698
|
+
// src/connectors/stdio.ts
|
|
1699
|
+
import process2 from "process";
|
|
1700
|
+
import { Client } from "@mcp-use/modelcontextprotocol-sdk/client/index.js";
|
|
1701
|
+
|
|
1702
|
+
// src/task_managers/stdio.ts
|
|
1703
|
+
import { StdioClientTransport } from "@mcp-use/modelcontextprotocol-sdk/client/stdio.js";
|
|
1704
|
+
var StdioConnectionManager = class extends ConnectionManager {
|
|
1705
|
+
static {
|
|
1706
|
+
__name(this, "StdioConnectionManager");
|
|
1707
|
+
}
|
|
1708
|
+
serverParams;
|
|
1709
|
+
errlog;
|
|
1710
|
+
_transport = null;
|
|
1711
|
+
/**
|
|
1712
|
+
* Create a new stdio connection manager.
|
|
1713
|
+
*
|
|
1714
|
+
* @param serverParams Parameters for the stdio server process.
|
|
1715
|
+
* @param errlog Stream to which the server's stderr should be piped.
|
|
1716
|
+
* Defaults to `process.stderr`.
|
|
1717
|
+
*/
|
|
1718
|
+
constructor(serverParams, errlog = process.stderr) {
|
|
1719
|
+
super();
|
|
1720
|
+
this.serverParams = serverParams;
|
|
1721
|
+
this.errlog = errlog;
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Establish the stdio connection by spawning the server process and starting
|
|
1725
|
+
* the SDK's transport. Returns the live `StdioClientTransport` instance.
|
|
1726
|
+
*/
|
|
1727
|
+
async establishConnection() {
|
|
1728
|
+
this._transport = new StdioClientTransport(this.serverParams);
|
|
1729
|
+
if (this._transport.stderr && typeof this._transport.stderr.pipe === "function") {
|
|
1730
|
+
this._transport.stderr.pipe(
|
|
1731
|
+
this.errlog
|
|
1732
|
+
);
|
|
1733
|
+
}
|
|
1734
|
+
logger.debug(`${this.constructor.name} connected successfully`);
|
|
1735
|
+
return this._transport;
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* Close the stdio connection, making sure the transport cleans up the child
|
|
1739
|
+
* process and associated resources.
|
|
1740
|
+
*/
|
|
1741
|
+
async closeConnection(_connection) {
|
|
1742
|
+
if (this._transport) {
|
|
1743
|
+
try {
|
|
1744
|
+
await this._transport.close();
|
|
1745
|
+
} catch (e) {
|
|
1746
|
+
logger.warn(`Error closing stdio transport: ${e}`);
|
|
1747
|
+
} finally {
|
|
1748
|
+
this._transport = null;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
};
|
|
1753
|
+
|
|
1754
|
+
// src/connectors/stdio.ts
|
|
1755
|
+
var StdioConnector = class extends BaseConnector {
|
|
1756
|
+
static {
|
|
1757
|
+
__name(this, "StdioConnector");
|
|
1758
|
+
}
|
|
1759
|
+
command;
|
|
1760
|
+
args;
|
|
1761
|
+
env;
|
|
1762
|
+
errlog;
|
|
1763
|
+
clientInfo;
|
|
1764
|
+
constructor({
|
|
1765
|
+
command = "npx",
|
|
1766
|
+
args = [],
|
|
1767
|
+
env,
|
|
1768
|
+
errlog = process2.stderr,
|
|
1769
|
+
...rest
|
|
1770
|
+
} = {}) {
|
|
1771
|
+
super(rest);
|
|
1772
|
+
this.command = command;
|
|
1773
|
+
this.args = args;
|
|
1774
|
+
this.env = env;
|
|
1775
|
+
this.errlog = errlog;
|
|
1776
|
+
this.clientInfo = rest.clientInfo ?? {
|
|
1777
|
+
name: "stdio-connector",
|
|
1778
|
+
version: "1.0.0"
|
|
1779
|
+
};
|
|
1780
|
+
}
|
|
1781
|
+
/** Establish connection to the MCP implementation. */
|
|
1782
|
+
async connect() {
|
|
1783
|
+
if (this.connected) {
|
|
1784
|
+
logger.debug("Already connected to MCP implementation");
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
logger.debug(`Connecting to MCP implementation via stdio: ${this.command}`);
|
|
1788
|
+
try {
|
|
1789
|
+
let mergedEnv;
|
|
1790
|
+
if (this.env) {
|
|
1791
|
+
mergedEnv = {};
|
|
1792
|
+
for (const [key, value] of Object.entries(process2.env)) {
|
|
1793
|
+
if (value !== void 0) {
|
|
1794
|
+
mergedEnv[key] = value;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
Object.assign(mergedEnv, this.env);
|
|
1798
|
+
}
|
|
1799
|
+
const serverParams = {
|
|
1800
|
+
command: this.command,
|
|
1801
|
+
args: this.args,
|
|
1802
|
+
env: mergedEnv
|
|
1803
|
+
};
|
|
1804
|
+
this.connectionManager = new StdioConnectionManager(
|
|
1805
|
+
serverParams,
|
|
1806
|
+
this.errlog
|
|
1807
|
+
);
|
|
1808
|
+
const transport = await this.connectionManager.start();
|
|
1809
|
+
const clientOptions = {
|
|
1810
|
+
...this.opts.clientOptions || {},
|
|
1811
|
+
capabilities: {
|
|
1812
|
+
...this.opts.clientOptions?.capabilities || {},
|
|
1813
|
+
roots: { listChanged: true },
|
|
1814
|
+
// Always advertise roots capability
|
|
1815
|
+
// Add sampling capability if callback is provided
|
|
1816
|
+
...this.opts.samplingCallback ? { sampling: {} } : {},
|
|
1817
|
+
// Add elicitation capability if callback is provided
|
|
1818
|
+
...this.opts.elicitationCallback ? { elicitation: { form: {}, url: {} } } : {}
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
this.client = new Client(this.clientInfo, clientOptions);
|
|
1822
|
+
await this.client.connect(transport);
|
|
1823
|
+
this.connected = true;
|
|
1824
|
+
this.setupNotificationHandler();
|
|
1825
|
+
this.setupRootsHandler();
|
|
1826
|
+
this.setupSamplingHandler();
|
|
1827
|
+
this.setupElicitationHandler();
|
|
1828
|
+
logger.debug(
|
|
1829
|
+
`Successfully connected to MCP implementation: ${this.command}`
|
|
1830
|
+
);
|
|
1831
|
+
this.trackConnectorInit({
|
|
1832
|
+
serverCommand: this.command,
|
|
1833
|
+
serverArgs: this.args,
|
|
1834
|
+
publicIdentifier: `${this.command} ${this.args.join(" ")}`
|
|
1835
|
+
});
|
|
1836
|
+
} catch (err) {
|
|
1837
|
+
logger.error(`Failed to connect to MCP implementation: ${err}`);
|
|
1838
|
+
await this.cleanupResources();
|
|
1839
|
+
throw err;
|
|
809
1840
|
}
|
|
810
|
-
|
|
1841
|
+
}
|
|
1842
|
+
get publicIdentifier() {
|
|
1843
|
+
return {
|
|
1844
|
+
type: "stdio",
|
|
1845
|
+
"command&args": `${this.command} ${this.args.join(" ")}`
|
|
1846
|
+
};
|
|
811
1847
|
}
|
|
812
1848
|
};
|
|
813
1849
|
|
|
814
|
-
// src/
|
|
815
|
-
import {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
1850
|
+
// src/config.ts
|
|
1851
|
+
import { readFileSync } from "fs";
|
|
1852
|
+
function loadConfigFile(filepath) {
|
|
1853
|
+
const raw = readFileSync(filepath, "utf-8");
|
|
1854
|
+
return JSON.parse(raw);
|
|
1855
|
+
}
|
|
1856
|
+
__name(loadConfigFile, "loadConfigFile");
|
|
1857
|
+
function createConnectorFromConfig(serverConfig, connectorOptions) {
|
|
1858
|
+
if ("command" in serverConfig && "args" in serverConfig) {
|
|
1859
|
+
return new StdioConnector({
|
|
1860
|
+
command: serverConfig.command,
|
|
1861
|
+
args: serverConfig.args,
|
|
1862
|
+
env: serverConfig.env,
|
|
1863
|
+
...connectorOptions
|
|
1864
|
+
});
|
|
823
1865
|
}
|
|
1866
|
+
if ("url" in serverConfig) {
|
|
1867
|
+
const transport = serverConfig.transport || "http";
|
|
1868
|
+
return new HttpConnector(serverConfig.url, {
|
|
1869
|
+
headers: serverConfig.headers,
|
|
1870
|
+
authToken: serverConfig.auth_token || serverConfig.authToken,
|
|
1871
|
+
// Only force SSE if explicitly requested
|
|
1872
|
+
preferSse: serverConfig.preferSse || transport === "sse",
|
|
1873
|
+
...connectorOptions
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
throw new Error("Cannot determine connector type from config");
|
|
824
1877
|
}
|
|
825
|
-
__name(
|
|
826
|
-
|
|
1878
|
+
__name(createConnectorFromConfig, "createConnectorFromConfig");
|
|
1879
|
+
|
|
1880
|
+
// src/client.ts
|
|
1881
|
+
import fs from "fs";
|
|
1882
|
+
import path from "path";
|
|
1883
|
+
var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
827
1884
|
static {
|
|
828
|
-
__name(this, "
|
|
1885
|
+
__name(this, "MCPClient");
|
|
829
1886
|
}
|
|
830
|
-
|
|
831
|
-
|
|
1887
|
+
/**
|
|
1888
|
+
* Get the mcp-use package version.
|
|
1889
|
+
* Works in all environments (Node.js, browser, Cloudflare Workers, Deno, etc.)
|
|
1890
|
+
*/
|
|
1891
|
+
static getPackageVersion() {
|
|
1892
|
+
return getPackageVersion();
|
|
1893
|
+
}
|
|
1894
|
+
codeMode = false;
|
|
1895
|
+
_codeExecutor = null;
|
|
1896
|
+
_customCodeExecutor = null;
|
|
1897
|
+
_codeExecutorConfig = "vm";
|
|
1898
|
+
_executorOptions;
|
|
1899
|
+
_samplingCallback;
|
|
1900
|
+
_elicitationCallback;
|
|
1901
|
+
constructor(config, options) {
|
|
1902
|
+
if (config) {
|
|
1903
|
+
if (typeof config === "string") {
|
|
1904
|
+
super(loadConfigFile(config));
|
|
1905
|
+
} else {
|
|
1906
|
+
super(config);
|
|
1907
|
+
}
|
|
1908
|
+
} else {
|
|
1909
|
+
super();
|
|
1910
|
+
}
|
|
1911
|
+
let codeModeEnabled = false;
|
|
1912
|
+
let executorConfig = "vm";
|
|
1913
|
+
let executorOptions;
|
|
1914
|
+
if (options?.codeMode) {
|
|
1915
|
+
if (typeof options.codeMode === "boolean") {
|
|
1916
|
+
codeModeEnabled = options.codeMode;
|
|
1917
|
+
} else {
|
|
1918
|
+
codeModeEnabled = options.codeMode.enabled;
|
|
1919
|
+
executorConfig = options.codeMode.executor ?? "vm";
|
|
1920
|
+
executorOptions = options.codeMode.executorOptions;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
this.codeMode = codeModeEnabled;
|
|
1924
|
+
this._codeExecutorConfig = executorConfig;
|
|
1925
|
+
this._executorOptions = executorOptions;
|
|
1926
|
+
this._samplingCallback = options?.samplingCallback;
|
|
1927
|
+
this._elicitationCallback = options?.elicitationCallback;
|
|
1928
|
+
if (this.codeMode) {
|
|
1929
|
+
this._setupCodeModeConnector();
|
|
1930
|
+
}
|
|
1931
|
+
this._trackClientInit();
|
|
1932
|
+
}
|
|
1933
|
+
_trackClientInit() {
|
|
1934
|
+
const servers = Object.keys(this.config.mcpServers ?? {});
|
|
1935
|
+
const hasSamplingCallback = !!this._samplingCallback;
|
|
1936
|
+
const hasElicitationCallback = !!this._elicitationCallback;
|
|
1937
|
+
Tel.getInstance().trackMCPClientInit({
|
|
1938
|
+
codeMode: this.codeMode,
|
|
1939
|
+
sandbox: false,
|
|
1940
|
+
// Sandbox not supported in TS yet
|
|
1941
|
+
allCallbacks: hasSamplingCallback && hasElicitationCallback,
|
|
1942
|
+
verify: false,
|
|
1943
|
+
// No verify option in TS client
|
|
1944
|
+
servers,
|
|
1945
|
+
numServers: servers.length,
|
|
1946
|
+
isBrowser: false
|
|
1947
|
+
// Node.js MCPClient
|
|
1948
|
+
}).catch((e) => logger.debug(`Failed to track MCPClient init: ${e}`));
|
|
1949
|
+
}
|
|
1950
|
+
static fromDict(cfg, options) {
|
|
1951
|
+
return new _MCPClient(cfg, options);
|
|
1952
|
+
}
|
|
1953
|
+
static fromConfigFile(path2, options) {
|
|
1954
|
+
return new _MCPClient(loadConfigFile(path2), options);
|
|
832
1955
|
}
|
|
833
1956
|
/**
|
|
834
|
-
*
|
|
1957
|
+
* Save configuration to a file (Node.js only)
|
|
835
1958
|
*/
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
1959
|
+
saveConfig(filepath) {
|
|
1960
|
+
const dir = path.dirname(filepath);
|
|
1961
|
+
if (!fs.existsSync(dir)) {
|
|
1962
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
839
1963
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
1964
|
+
fs.writeFileSync(filepath, JSON.stringify(this.config, null, 2), "utf-8");
|
|
1965
|
+
}
|
|
1966
|
+
/**
|
|
1967
|
+
* Create a connector from server configuration (Node.js version)
|
|
1968
|
+
* Supports all connector types including StdioConnector
|
|
1969
|
+
*/
|
|
1970
|
+
createConnectorFromConfig(serverConfig) {
|
|
1971
|
+
return createConnectorFromConfig(serverConfig, {
|
|
1972
|
+
samplingCallback: this._samplingCallback,
|
|
1973
|
+
elicitationCallback: this._elicitationCallback
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
_setupCodeModeConnector() {
|
|
1977
|
+
logger.debug("Code mode connector initialized as internal meta server");
|
|
1978
|
+
const connector = new CodeModeConnector(this);
|
|
1979
|
+
const session = new MCPSession(connector);
|
|
1980
|
+
this.sessions["code_mode"] = session;
|
|
1981
|
+
this.activeSessions.push("code_mode");
|
|
1982
|
+
}
|
|
1983
|
+
_ensureCodeExecutor() {
|
|
1984
|
+
if (!this._codeExecutor) {
|
|
1985
|
+
const config = this._codeExecutorConfig;
|
|
1986
|
+
if (config instanceof BaseCodeExecutor) {
|
|
1987
|
+
this._codeExecutor = config;
|
|
1988
|
+
} else if (typeof config === "function") {
|
|
1989
|
+
this._customCodeExecutor = config;
|
|
1990
|
+
throw new Error(
|
|
1991
|
+
"Custom executor function should be handled in executeCode"
|
|
849
1992
|
);
|
|
1993
|
+
} else if (config === "e2b") {
|
|
1994
|
+
const opts = this._executorOptions;
|
|
1995
|
+
if (!opts?.apiKey) {
|
|
1996
|
+
logger.warn("E2B executor requires apiKey. Falling back to VM.");
|
|
1997
|
+
try {
|
|
1998
|
+
this._codeExecutor = new VMCodeExecutor(
|
|
1999
|
+
this,
|
|
2000
|
+
this._executorOptions
|
|
2001
|
+
);
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
throw new Error(
|
|
2004
|
+
"VM executor is not available in this environment and E2B API key is not provided. Please provide an E2B API key or run in a Node.js environment."
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
} else {
|
|
2008
|
+
this._codeExecutor = new E2BCodeExecutor(this, opts);
|
|
2009
|
+
}
|
|
2010
|
+
} else {
|
|
850
2011
|
try {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
2012
|
+
this._codeExecutor = new VMCodeExecutor(
|
|
2013
|
+
this,
|
|
2014
|
+
this._executorOptions
|
|
854
2015
|
);
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
2016
|
+
} catch (error) {
|
|
2017
|
+
const e2bOpts = this._executorOptions;
|
|
2018
|
+
const e2bApiKey = e2bOpts?.apiKey || process.env.E2B_API_KEY;
|
|
2019
|
+
if (e2bApiKey) {
|
|
2020
|
+
logger.info(
|
|
2021
|
+
"VM executor not available in this environment. Falling back to E2B."
|
|
2022
|
+
);
|
|
2023
|
+
this._codeExecutor = new E2BCodeExecutor(this, {
|
|
2024
|
+
...e2bOpts,
|
|
2025
|
+
apiKey: e2bApiKey
|
|
2026
|
+
});
|
|
2027
|
+
} else {
|
|
2028
|
+
throw new Error(
|
|
2029
|
+
"VM executor is not available in this environment. Please provide an E2B API key via executorOptions or E2B_API_KEY environment variable, or run in a Node.js environment."
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
859
2032
|
}
|
|
860
|
-
}
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
return this._codeExecutor;
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* Execute code in code mode
|
|
2039
|
+
*/
|
|
2040
|
+
async executeCode(code, timeout) {
|
|
2041
|
+
if (!this.codeMode) {
|
|
2042
|
+
throw new Error("Code execution mode is not enabled");
|
|
2043
|
+
}
|
|
2044
|
+
if (this._customCodeExecutor) {
|
|
2045
|
+
return this._customCodeExecutor(code, timeout);
|
|
2046
|
+
}
|
|
2047
|
+
return this._ensureCodeExecutor().execute(code, timeout);
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Search available tools (used by code mode)
|
|
2051
|
+
*/
|
|
2052
|
+
async searchTools(query = "", detailLevel = "full") {
|
|
2053
|
+
if (!this.codeMode) {
|
|
2054
|
+
throw new Error("Code execution mode is not enabled");
|
|
2055
|
+
}
|
|
2056
|
+
return this._ensureCodeExecutor().createSearchToolsFunction()(
|
|
2057
|
+
query,
|
|
2058
|
+
detailLevel
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Override getServerNames to exclude internal code_mode server
|
|
2063
|
+
*/
|
|
2064
|
+
getServerNames() {
|
|
2065
|
+
const isCodeModeEnabled = this.codeMode;
|
|
2066
|
+
return super.getServerNames().filter((name) => {
|
|
2067
|
+
return !isCodeModeEnabled || name !== "code_mode";
|
|
861
2068
|
});
|
|
862
|
-
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* Close the client and clean up resources including code executors.
|
|
2072
|
+
* This ensures E2B sandboxes and other resources are properly released.
|
|
2073
|
+
*/
|
|
2074
|
+
async close() {
|
|
2075
|
+
if (this._codeExecutor) {
|
|
2076
|
+
await this._codeExecutor.cleanup();
|
|
2077
|
+
this._codeExecutor = null;
|
|
2078
|
+
}
|
|
2079
|
+
await this.closeAllSessions();
|
|
863
2080
|
}
|
|
864
2081
|
};
|
|
865
2082
|
|
|
@@ -992,15 +2209,21 @@ var ConnectMCPServerTool = class extends MCPServerTool {
|
|
|
992
2209
|
session = await this.manager.client.createSession(serverName);
|
|
993
2210
|
}
|
|
994
2211
|
this.manager.activeServer = serverName;
|
|
995
|
-
if (this.manager.serverTools[serverName]) {
|
|
2212
|
+
if (!this.manager.serverTools[serverName]) {
|
|
996
2213
|
const connector = session.connector;
|
|
997
2214
|
const tools = await this.manager.adapter.createToolsFromConnectors([connector]);
|
|
998
|
-
this.manager.
|
|
2215
|
+
const resources = await this.manager.adapter.createResourcesFromConnectors([connector]);
|
|
2216
|
+
const prompts = await this.manager.adapter.createPromptsFromConnectors([connector]);
|
|
2217
|
+
const allItems = [...tools, ...resources, ...prompts];
|
|
2218
|
+
this.manager.serverTools[serverName] = allItems;
|
|
999
2219
|
this.manager.initializedServers[serverName] = true;
|
|
2220
|
+
logger.debug(
|
|
2221
|
+
`Loaded ${allItems.length} items for server '${serverName}': ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`
|
|
2222
|
+
);
|
|
1000
2223
|
}
|
|
1001
2224
|
const serverTools = this.manager.serverTools[serverName] || [];
|
|
1002
2225
|
const numTools = serverTools.length;
|
|
1003
|
-
return `Connected to MCP server '${serverName}'. ${numTools} tools are now available.`;
|
|
2226
|
+
return `Connected to MCP server '${serverName}'. ${numTools} tools, resources, and prompts are now available.`;
|
|
1004
2227
|
} catch (error) {
|
|
1005
2228
|
logger.error(
|
|
1006
2229
|
`Error connecting to server '${serverName}': ${String(error)}`
|
|
@@ -1161,21 +2384,30 @@ var ServerManager = class {
|
|
|
1161
2384
|
if (session) {
|
|
1162
2385
|
const connector = session.connector;
|
|
1163
2386
|
let tools = [];
|
|
2387
|
+
let resources = [];
|
|
2388
|
+
let prompts = [];
|
|
1164
2389
|
try {
|
|
1165
2390
|
tools = await this.adapter.createToolsFromConnectors([connector]);
|
|
2391
|
+
resources = await this.adapter.createResourcesFromConnectors([
|
|
2392
|
+
connector
|
|
2393
|
+
]);
|
|
2394
|
+
prompts = await this.adapter.createPromptsFromConnectors([
|
|
2395
|
+
connector
|
|
2396
|
+
]);
|
|
1166
2397
|
} catch (toolFetchError) {
|
|
1167
2398
|
logger.error(
|
|
1168
|
-
`Failed to create tools from connector for server '${serverName}': ${toolFetchError}`
|
|
2399
|
+
`Failed to create tools/resources/prompts from connector for server '${serverName}': ${toolFetchError}`
|
|
1169
2400
|
);
|
|
1170
2401
|
continue;
|
|
1171
2402
|
}
|
|
2403
|
+
const allItems = [...tools, ...resources, ...prompts];
|
|
1172
2404
|
const cachedTools = this.serverTools[serverName];
|
|
1173
|
-
const toolsChanged = !cachedTools || !isEqual(cachedTools,
|
|
2405
|
+
const toolsChanged = !cachedTools || !isEqual(cachedTools, allItems);
|
|
1174
2406
|
if (toolsChanged) {
|
|
1175
|
-
this.serverTools[serverName] =
|
|
2407
|
+
this.serverTools[serverName] = allItems;
|
|
1176
2408
|
this.initializedServers[serverName] = true;
|
|
1177
2409
|
logger.debug(
|
|
1178
|
-
`Prefetched ${
|
|
2410
|
+
`Prefetched ${allItems.length} items for server '${serverName}': ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts.`
|
|
1179
2411
|
);
|
|
1180
2412
|
} else {
|
|
1181
2413
|
logger.debug(
|
|
@@ -1244,9 +2476,9 @@ var ObservabilityManager = class {
|
|
|
1244
2476
|
return;
|
|
1245
2477
|
}
|
|
1246
2478
|
try {
|
|
1247
|
-
const { langfuseHandler: langfuseHandler2, langfuseInitPromise: langfuseInitPromise2 } = await import("./langfuse-
|
|
2479
|
+
const { langfuseHandler: langfuseHandler2, langfuseInitPromise: langfuseInitPromise2 } = await import("./langfuse-74RGPTAH.js");
|
|
1248
2480
|
if (this.agentId || this.metadata || this.metadataProvider || this.tagsProvider) {
|
|
1249
|
-
const { initializeLangfuse } = await import("./langfuse-
|
|
2481
|
+
const { initializeLangfuse } = await import("./langfuse-74RGPTAH.js");
|
|
1250
2482
|
await initializeLangfuse(
|
|
1251
2483
|
this.agentId,
|
|
1252
2484
|
this.metadata,
|
|
@@ -1406,6 +2638,26 @@ var ObservabilityManager = class {
|
|
|
1406
2638
|
import { toJSONSchema } from "zod";
|
|
1407
2639
|
var API_CHATS_ENDPOINT = "/api/v1/chats";
|
|
1408
2640
|
var API_CHAT_EXECUTE_ENDPOINT = "/api/v1/chats/{chat_id}/execute";
|
|
2641
|
+
function normalizeRemoteRunOptions(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
2642
|
+
if (typeof queryOrOptions === "object" && queryOrOptions !== null) {
|
|
2643
|
+
const options = queryOrOptions;
|
|
2644
|
+
return {
|
|
2645
|
+
query: options.prompt,
|
|
2646
|
+
maxSteps: options.maxSteps,
|
|
2647
|
+
manageConnector: options.manageConnector,
|
|
2648
|
+
externalHistory: options.externalHistory,
|
|
2649
|
+
outputSchema: options.schema
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
return {
|
|
2653
|
+
query: queryOrOptions,
|
|
2654
|
+
maxSteps,
|
|
2655
|
+
manageConnector,
|
|
2656
|
+
externalHistory,
|
|
2657
|
+
outputSchema
|
|
2658
|
+
};
|
|
2659
|
+
}
|
|
2660
|
+
__name(normalizeRemoteRunOptions, "normalizeRemoteRunOptions");
|
|
1409
2661
|
var RemoteAgent = class {
|
|
1410
2662
|
static {
|
|
1411
2663
|
__name(this, "RemoteAgent");
|
|
@@ -1502,8 +2754,20 @@ var RemoteAgent = class {
|
|
|
1502
2754
|
throw new Error(`Failed to create chat session: ${String(e)}`);
|
|
1503
2755
|
}
|
|
1504
2756
|
}
|
|
1505
|
-
async run(
|
|
1506
|
-
|
|
2757
|
+
async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
2758
|
+
const {
|
|
2759
|
+
query,
|
|
2760
|
+
maxSteps: steps,
|
|
2761
|
+
externalHistory: history,
|
|
2762
|
+
outputSchema: schema
|
|
2763
|
+
} = normalizeRemoteRunOptions(
|
|
2764
|
+
queryOrOptions,
|
|
2765
|
+
maxSteps,
|
|
2766
|
+
manageConnector,
|
|
2767
|
+
externalHistory,
|
|
2768
|
+
outputSchema
|
|
2769
|
+
);
|
|
2770
|
+
if (history !== void 0) {
|
|
1507
2771
|
logger.warn("External history is not yet supported for remote execution");
|
|
1508
2772
|
}
|
|
1509
2773
|
try {
|
|
@@ -1514,10 +2778,10 @@ var RemoteAgent = class {
|
|
|
1514
2778
|
const chatId = this.chatId;
|
|
1515
2779
|
const executionPayload = {
|
|
1516
2780
|
query,
|
|
1517
|
-
max_steps:
|
|
2781
|
+
max_steps: steps ?? 10
|
|
1518
2782
|
};
|
|
1519
|
-
if (
|
|
1520
|
-
executionPayload.output_schema = this.pydanticToJsonSchema(
|
|
2783
|
+
if (schema) {
|
|
2784
|
+
executionPayload.output_schema = this.pydanticToJsonSchema(schema);
|
|
1521
2785
|
logger.info(`\u{1F527} Using structured output with schema`);
|
|
1522
2786
|
}
|
|
1523
2787
|
const headers = {
|
|
@@ -1591,8 +2855,8 @@ Raw error: ${result}`
|
|
|
1591
2855
|
);
|
|
1592
2856
|
}
|
|
1593
2857
|
}
|
|
1594
|
-
if (
|
|
1595
|
-
return this.parseStructuredResponse(result,
|
|
2858
|
+
if (schema) {
|
|
2859
|
+
return this.parseStructuredResponse(result, schema);
|
|
1596
2860
|
}
|
|
1597
2861
|
if (typeof result === "object" && result !== null && "result" in result) {
|
|
1598
2862
|
return result.result;
|
|
@@ -1617,9 +2881,9 @@ Raw error: ${result}`
|
|
|
1617
2881
|
}
|
|
1618
2882
|
}
|
|
1619
2883
|
// eslint-disable-next-line require-yield
|
|
1620
|
-
async *stream(
|
|
2884
|
+
async *stream(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
1621
2885
|
const result = await this.run(
|
|
1622
|
-
|
|
2886
|
+
queryOrOptions,
|
|
1623
2887
|
maxSteps,
|
|
1624
2888
|
manageConnector,
|
|
1625
2889
|
externalHistory,
|
|
@@ -1632,6 +2896,144 @@ Raw error: ${result}`
|
|
|
1632
2896
|
}
|
|
1633
2897
|
};
|
|
1634
2898
|
|
|
2899
|
+
// src/agents/utils/llm_provider.ts
|
|
2900
|
+
var PROVIDER_CONFIG = {
|
|
2901
|
+
openai: {
|
|
2902
|
+
package: "@langchain/openai",
|
|
2903
|
+
className: "ChatOpenAI",
|
|
2904
|
+
envVars: ["OPENAI_API_KEY"],
|
|
2905
|
+
defaultModel: "gpt-4o"
|
|
2906
|
+
},
|
|
2907
|
+
anthropic: {
|
|
2908
|
+
package: "@langchain/anthropic",
|
|
2909
|
+
className: "ChatAnthropic",
|
|
2910
|
+
envVars: ["ANTHROPIC_API_KEY"],
|
|
2911
|
+
defaultModel: "claude-3-5-sonnet-20241022"
|
|
2912
|
+
},
|
|
2913
|
+
google: {
|
|
2914
|
+
package: "@langchain/google-genai",
|
|
2915
|
+
className: "ChatGoogleGenerativeAI",
|
|
2916
|
+
envVars: ["GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
|
|
2917
|
+
defaultModel: "gemini-pro"
|
|
2918
|
+
},
|
|
2919
|
+
groq: {
|
|
2920
|
+
package: "@langchain/groq",
|
|
2921
|
+
className: "ChatGroq",
|
|
2922
|
+
envVars: ["GROQ_API_KEY"],
|
|
2923
|
+
defaultModel: "llama-3.1-70b-versatile"
|
|
2924
|
+
}
|
|
2925
|
+
};
|
|
2926
|
+
function parseLLMString(llmString) {
|
|
2927
|
+
const parts = llmString.split("/");
|
|
2928
|
+
if (parts.length !== 2) {
|
|
2929
|
+
throw new Error(
|
|
2930
|
+
`Invalid LLM string format. Expected 'provider/model', got '${llmString}'. Examples: 'openai/gpt-4', 'anthropic/claude-3-5-sonnet-20241022', 'google/gemini-pro', 'groq/llama-3.1-70b-versatile'`
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
const [provider, model] = parts;
|
|
2934
|
+
if (!provider || !model) {
|
|
2935
|
+
throw new Error(
|
|
2936
|
+
`Invalid LLM string format. Both provider and model must be non-empty. Got '${llmString}'`
|
|
2937
|
+
);
|
|
2938
|
+
}
|
|
2939
|
+
const normalizedProvider = provider.toLowerCase();
|
|
2940
|
+
if (!(normalizedProvider in PROVIDER_CONFIG)) {
|
|
2941
|
+
const supportedProviders = Object.keys(PROVIDER_CONFIG).join(", ");
|
|
2942
|
+
throw new Error(
|
|
2943
|
+
`Unsupported LLM provider '${provider}'. Supported providers: ${supportedProviders}`
|
|
2944
|
+
);
|
|
2945
|
+
}
|
|
2946
|
+
return { provider: normalizedProvider, model };
|
|
2947
|
+
}
|
|
2948
|
+
__name(parseLLMString, "parseLLMString");
|
|
2949
|
+
function getAPIKey(provider, config) {
|
|
2950
|
+
if (config?.apiKey) {
|
|
2951
|
+
return config.apiKey;
|
|
2952
|
+
}
|
|
2953
|
+
const providerConfig = PROVIDER_CONFIG[provider];
|
|
2954
|
+
for (const envVar of providerConfig.envVars) {
|
|
2955
|
+
const apiKey = process.env[envVar];
|
|
2956
|
+
if (apiKey) {
|
|
2957
|
+
logger.debug(
|
|
2958
|
+
`Using API key from environment variable ${envVar} for provider ${provider}`
|
|
2959
|
+
);
|
|
2960
|
+
return apiKey;
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
const envVarsStr = providerConfig.envVars.join(" or ");
|
|
2964
|
+
throw new Error(
|
|
2965
|
+
`API key not found for provider '${provider}'. Set ${envVarsStr} environment variable or pass apiKey in llmConfig. Example: new MCPAgent({ llm: '${provider}/model', llmConfig: { apiKey: 'your-key' } })`
|
|
2966
|
+
);
|
|
2967
|
+
}
|
|
2968
|
+
__name(getAPIKey, "getAPIKey");
|
|
2969
|
+
async function createLLMFromString(llmString, config) {
|
|
2970
|
+
logger.info(`Creating LLM from string: ${llmString}`);
|
|
2971
|
+
const { provider, model } = parseLLMString(llmString);
|
|
2972
|
+
const providerConfig = PROVIDER_CONFIG[provider];
|
|
2973
|
+
const apiKey = getAPIKey(provider, config);
|
|
2974
|
+
let providerModule;
|
|
2975
|
+
try {
|
|
2976
|
+
logger.debug(`Importing package ${providerConfig.package}...`);
|
|
2977
|
+
providerModule = await import(providerConfig.package);
|
|
2978
|
+
} catch (error) {
|
|
2979
|
+
if (error?.code === "MODULE_NOT_FOUND" || error?.message?.includes("Cannot find module") || error?.message?.includes("Cannot find package")) {
|
|
2980
|
+
throw new Error(
|
|
2981
|
+
`Package '${providerConfig.package}' is not installed. Install it with: npm install ${providerConfig.package} or yarn add ${providerConfig.package}`
|
|
2982
|
+
);
|
|
2983
|
+
}
|
|
2984
|
+
throw new Error(
|
|
2985
|
+
`Failed to import ${providerConfig.package}: ${error?.message || error}`
|
|
2986
|
+
);
|
|
2987
|
+
}
|
|
2988
|
+
const LLMClass = providerModule[providerConfig.className];
|
|
2989
|
+
if (!LLMClass) {
|
|
2990
|
+
throw new Error(
|
|
2991
|
+
`Could not find ${providerConfig.className} in package ${providerConfig.package}. This might be a version compatibility issue.`
|
|
2992
|
+
);
|
|
2993
|
+
}
|
|
2994
|
+
const llmConfig = {
|
|
2995
|
+
model,
|
|
2996
|
+
apiKey,
|
|
2997
|
+
...config
|
|
2998
|
+
};
|
|
2999
|
+
if (config?.apiKey) {
|
|
3000
|
+
delete llmConfig.apiKey;
|
|
3001
|
+
llmConfig.apiKey = apiKey;
|
|
3002
|
+
}
|
|
3003
|
+
if (provider === "anthropic") {
|
|
3004
|
+
llmConfig.model = model;
|
|
3005
|
+
} else if (provider === "google") {
|
|
3006
|
+
llmConfig.model = model;
|
|
3007
|
+
} else if (provider === "openai") {
|
|
3008
|
+
llmConfig.model = model;
|
|
3009
|
+
} else if (provider === "groq") {
|
|
3010
|
+
llmConfig.model = model;
|
|
3011
|
+
}
|
|
3012
|
+
try {
|
|
3013
|
+
const llmInstance = new LLMClass(llmConfig);
|
|
3014
|
+
logger.info(`Successfully created ${provider} LLM with model ${model}`);
|
|
3015
|
+
return llmInstance;
|
|
3016
|
+
} catch (error) {
|
|
3017
|
+
throw new Error(
|
|
3018
|
+
`Failed to instantiate ${providerConfig.className} with model '${model}': ${error?.message || error}`
|
|
3019
|
+
);
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
__name(createLLMFromString, "createLLMFromString");
|
|
3023
|
+
function isValidLLMString(llmString) {
|
|
3024
|
+
try {
|
|
3025
|
+
parseLLMString(llmString);
|
|
3026
|
+
return true;
|
|
3027
|
+
} catch {
|
|
3028
|
+
return false;
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
__name(isValidLLMString, "isValidLLMString");
|
|
3032
|
+
function getSupportedProviders() {
|
|
3033
|
+
return Object.keys(PROVIDER_CONFIG);
|
|
3034
|
+
}
|
|
3035
|
+
__name(getSupportedProviders, "getSupportedProviders");
|
|
3036
|
+
|
|
1635
3037
|
// src/agents/mcp_agent.ts
|
|
1636
3038
|
import {
|
|
1637
3039
|
AIMessage,
|
|
@@ -1735,6 +3137,26 @@ Here are the tools *currently* available to you (this list includes server manag
|
|
|
1735
3137
|
`;
|
|
1736
3138
|
|
|
1737
3139
|
// src/agents/mcp_agent.ts
|
|
3140
|
+
function normalizeRunOptions(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
3141
|
+
if (typeof queryOrOptions === "object" && queryOrOptions !== null) {
|
|
3142
|
+
const options = queryOrOptions;
|
|
3143
|
+
return {
|
|
3144
|
+
query: options.prompt,
|
|
3145
|
+
maxSteps: options.maxSteps,
|
|
3146
|
+
manageConnector: options.manageConnector,
|
|
3147
|
+
externalHistory: options.externalHistory,
|
|
3148
|
+
outputSchema: options.schema
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
return {
|
|
3152
|
+
query: queryOrOptions,
|
|
3153
|
+
maxSteps,
|
|
3154
|
+
manageConnector,
|
|
3155
|
+
externalHistory,
|
|
3156
|
+
outputSchema
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3159
|
+
__name(normalizeRunOptions, "normalizeRunOptions");
|
|
1738
3160
|
var MCPAgent = class {
|
|
1739
3161
|
static {
|
|
1740
3162
|
__name(this, "MCPAgent");
|
|
@@ -1780,6 +3202,12 @@ var MCPAgent = class {
|
|
|
1780
3202
|
// Remote agent support
|
|
1781
3203
|
isRemote = false;
|
|
1782
3204
|
remoteAgent = null;
|
|
3205
|
+
// Simplified mode support
|
|
3206
|
+
isSimplifiedMode = false;
|
|
3207
|
+
llmString;
|
|
3208
|
+
llmConfig;
|
|
3209
|
+
mcpServersConfig;
|
|
3210
|
+
clientOwnedByAgent = false;
|
|
1783
3211
|
constructor(options) {
|
|
1784
3212
|
if (options.agentId) {
|
|
1785
3213
|
this.isRemote = true;
|
|
@@ -1813,9 +3241,36 @@ var MCPAgent = class {
|
|
|
1813
3241
|
"llm is required for local execution. For remote execution, provide agentId instead."
|
|
1814
3242
|
);
|
|
1815
3243
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
3244
|
+
const isSimplifiedMode = typeof options.llm === "string";
|
|
3245
|
+
if (isSimplifiedMode) {
|
|
3246
|
+
this.isSimplifiedMode = true;
|
|
3247
|
+
this.llmString = options.llm;
|
|
3248
|
+
this.llmConfig = options.llmConfig;
|
|
3249
|
+
this.mcpServersConfig = options.mcpServers;
|
|
3250
|
+
if (!this.mcpServersConfig || Object.keys(this.mcpServersConfig).length === 0) {
|
|
3251
|
+
throw new Error(
|
|
3252
|
+
"Simplified mode requires 'mcpServers' configuration. Provide an object with server configurations, e.g., { filesystem: { command: 'npx', args: [...] } }"
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
this.llm = void 0;
|
|
3256
|
+
this.client = void 0;
|
|
3257
|
+
this.clientOwnedByAgent = true;
|
|
3258
|
+
this.connectors = [];
|
|
3259
|
+
logger.info(
|
|
3260
|
+
`\u{1F3AF} Simplified mode enabled: LLM will be created from '${this.llmString}'`
|
|
3261
|
+
);
|
|
3262
|
+
} else {
|
|
3263
|
+
this.isSimplifiedMode = false;
|
|
3264
|
+
this.llm = options.llm;
|
|
3265
|
+
this.client = options.client;
|
|
3266
|
+
this.connectors = options.connectors ?? [];
|
|
3267
|
+
this.clientOwnedByAgent = false;
|
|
3268
|
+
if (!this.client && this.connectors.length === 0) {
|
|
3269
|
+
throw new Error(
|
|
3270
|
+
"Explicit mode requires either 'client' or at least one 'connector'. Alternatively, use simplified mode with 'llm' as a string and 'mcpServers' config."
|
|
3271
|
+
);
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
1819
3274
|
this.maxSteps = options.maxSteps ?? 5;
|
|
1820
3275
|
this.autoInitialize = options.autoInitialize ?? false;
|
|
1821
3276
|
this.memoryEnabled = options.memoryEnabled ?? true;
|
|
@@ -1828,28 +3283,30 @@ var MCPAgent = class {
|
|
|
1828
3283
|
this.useServerManager = options.useServerManager ?? false;
|
|
1829
3284
|
this.verbose = options.verbose ?? false;
|
|
1830
3285
|
this.observe = options.observe ?? true;
|
|
1831
|
-
if (!this.
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
3286
|
+
if (!this.isSimplifiedMode) {
|
|
3287
|
+
if (this.useServerManager) {
|
|
3288
|
+
if (!this.client) {
|
|
3289
|
+
throw new Error(
|
|
3290
|
+
"'client' must be provided when 'useServerManager' is true."
|
|
3291
|
+
);
|
|
3292
|
+
}
|
|
3293
|
+
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
3294
|
+
this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
|
|
3295
|
+
} else {
|
|
3296
|
+
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
3297
|
+
}
|
|
3298
|
+
this.telemetry = Telemetry.getInstance();
|
|
3299
|
+
if (this.llm) {
|
|
3300
|
+
const [provider, name] = extractModelInfo(this.llm);
|
|
3301
|
+
this.modelProvider = provider;
|
|
3302
|
+
this.modelName = name;
|
|
3303
|
+
} else {
|
|
3304
|
+
this.modelProvider = "unknown";
|
|
3305
|
+
this.modelName = "unknown";
|
|
1841
3306
|
}
|
|
1842
|
-
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
1843
|
-
this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
|
|
1844
3307
|
} else {
|
|
1845
3308
|
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
1846
|
-
|
|
1847
|
-
this.telemetry = Telemetry.getInstance();
|
|
1848
|
-
if (this.llm) {
|
|
1849
|
-
const [provider, name] = extractModelInfo(this.llm);
|
|
1850
|
-
this.modelProvider = provider;
|
|
1851
|
-
this.modelName = name;
|
|
1852
|
-
} else {
|
|
3309
|
+
this.telemetry = Telemetry.getInstance();
|
|
1853
3310
|
this.modelProvider = "unknown";
|
|
1854
3311
|
this.modelName = "unknown";
|
|
1855
3312
|
}
|
|
@@ -1880,6 +3337,40 @@ var MCPAgent = class {
|
|
|
1880
3337
|
return;
|
|
1881
3338
|
}
|
|
1882
3339
|
logger.info("\u{1F680} Initializing MCP agent and connecting to services...");
|
|
3340
|
+
if (this.isSimplifiedMode) {
|
|
3341
|
+
logger.info(
|
|
3342
|
+
"\u{1F3AF} Simplified mode: Creating client and LLM from configuration..."
|
|
3343
|
+
);
|
|
3344
|
+
if (this.mcpServersConfig) {
|
|
3345
|
+
logger.info(
|
|
3346
|
+
`Creating MCPClient with ${Object.keys(this.mcpServersConfig).length} server(s)...`
|
|
3347
|
+
);
|
|
3348
|
+
this.client = new MCPClient({ mcpServers: this.mcpServersConfig });
|
|
3349
|
+
logger.info("\u2705 MCPClient created successfully");
|
|
3350
|
+
}
|
|
3351
|
+
if (this.llmString) {
|
|
3352
|
+
logger.info(`Creating LLM from string: ${this.llmString}...`);
|
|
3353
|
+
try {
|
|
3354
|
+
this.llm = await createLLMFromString(this.llmString, this.llmConfig);
|
|
3355
|
+
logger.info("\u2705 LLM created successfully");
|
|
3356
|
+
const [provider, name] = extractModelInfo(this.llm);
|
|
3357
|
+
this.modelProvider = provider;
|
|
3358
|
+
this.modelName = name;
|
|
3359
|
+
} catch (error) {
|
|
3360
|
+
throw new Error(
|
|
3361
|
+
`Failed to create LLM from string '${this.llmString}': ${error?.message || error}`
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
if (this.useServerManager) {
|
|
3366
|
+
if (!this.client) {
|
|
3367
|
+
throw new Error(
|
|
3368
|
+
"'client' must be available when 'useServerManager' is true."
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
this.serverManager = new ServerManager(this.client, this.adapter);
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
1883
3374
|
this.callbacks = await this.observabilityManager.getCallbacks();
|
|
1884
3375
|
const handlerNames = await this.observabilityManager.getHandlerNames();
|
|
1885
3376
|
if (handlerNames.length > 0) {
|
|
@@ -1923,9 +3414,18 @@ var MCPAgent = class {
|
|
|
1923
3414
|
);
|
|
1924
3415
|
}
|
|
1925
3416
|
} else {
|
|
1926
|
-
|
|
3417
|
+
const tools = await this.adapter.createToolsFromConnectors(
|
|
3418
|
+
Object.values(this.sessions).map((session) => session.connector)
|
|
3419
|
+
);
|
|
3420
|
+
const resources = await this.adapter.createResourcesFromConnectors(
|
|
3421
|
+
Object.values(this.sessions).map((session) => session.connector)
|
|
3422
|
+
);
|
|
3423
|
+
const prompts = await this.adapter.createPromptsFromConnectors(
|
|
3424
|
+
Object.values(this.sessions).map((session) => session.connector)
|
|
3425
|
+
);
|
|
3426
|
+
this._tools = [...tools, ...resources, ...prompts];
|
|
1927
3427
|
logger.info(
|
|
1928
|
-
`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain
|
|
3428
|
+
`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain items from client: ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`
|
|
1929
3429
|
);
|
|
1930
3430
|
}
|
|
1931
3431
|
this._tools.push(...this.additionalTools);
|
|
@@ -1938,12 +3438,19 @@ var MCPAgent = class {
|
|
|
1938
3438
|
await connector.connect();
|
|
1939
3439
|
}
|
|
1940
3440
|
}
|
|
1941
|
-
|
|
3441
|
+
const tools = await this.adapter.createToolsFromConnectors(
|
|
3442
|
+
this.connectors
|
|
3443
|
+
);
|
|
3444
|
+
const resources = await this.adapter.createResourcesFromConnectors(
|
|
3445
|
+
this.connectors
|
|
3446
|
+
);
|
|
3447
|
+
const prompts = await this.adapter.createPromptsFromConnectors(
|
|
1942
3448
|
this.connectors
|
|
1943
3449
|
);
|
|
3450
|
+
this._tools = [...tools, ...resources, ...prompts];
|
|
1944
3451
|
this._tools.push(...this.additionalTools);
|
|
1945
3452
|
logger.info(
|
|
1946
|
-
`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain
|
|
3453
|
+
`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain items from connectors: ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`
|
|
1947
3454
|
);
|
|
1948
3455
|
}
|
|
1949
3456
|
logger.info(`\u{1F9F0} Found ${this._tools.length} tools across all connectors`);
|
|
@@ -2406,33 +3913,47 @@ var MCPAgent = class {
|
|
|
2406
3913
|
}
|
|
2407
3914
|
}
|
|
2408
3915
|
}
|
|
2409
|
-
async run(
|
|
2410
|
-
|
|
2411
|
-
return this.remoteAgent.run(
|
|
2412
|
-
query,
|
|
2413
|
-
maxSteps,
|
|
2414
|
-
manageConnector,
|
|
2415
|
-
externalHistory,
|
|
2416
|
-
outputSchema
|
|
2417
|
-
);
|
|
2418
|
-
}
|
|
2419
|
-
const generator = this.stream(
|
|
3916
|
+
async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
3917
|
+
const {
|
|
2420
3918
|
query,
|
|
3919
|
+
maxSteps: steps,
|
|
3920
|
+
manageConnector: manage,
|
|
3921
|
+
externalHistory: history,
|
|
3922
|
+
outputSchema: schema
|
|
3923
|
+
} = normalizeRunOptions(
|
|
3924
|
+
queryOrOptions,
|
|
2421
3925
|
maxSteps,
|
|
2422
3926
|
manageConnector,
|
|
2423
3927
|
externalHistory,
|
|
2424
3928
|
outputSchema
|
|
2425
3929
|
);
|
|
3930
|
+
if (this.isRemote && this.remoteAgent) {
|
|
3931
|
+
return this.remoteAgent.run(query, steps, manage, history, schema);
|
|
3932
|
+
}
|
|
3933
|
+
const generator = this.stream(query, steps, manage, history, schema);
|
|
2426
3934
|
return this._consumeAndReturn(generator);
|
|
2427
3935
|
}
|
|
2428
|
-
async *stream(
|
|
3936
|
+
async *stream(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
3937
|
+
const {
|
|
3938
|
+
query,
|
|
3939
|
+
maxSteps: steps,
|
|
3940
|
+
manageConnector: manage,
|
|
3941
|
+
externalHistory: history,
|
|
3942
|
+
outputSchema: schema
|
|
3943
|
+
} = normalizeRunOptions(
|
|
3944
|
+
queryOrOptions,
|
|
3945
|
+
maxSteps,
|
|
3946
|
+
manageConnector,
|
|
3947
|
+
externalHistory,
|
|
3948
|
+
outputSchema
|
|
3949
|
+
);
|
|
2429
3950
|
if (this.isRemote && this.remoteAgent) {
|
|
2430
3951
|
const result = await this.remoteAgent.run(
|
|
2431
3952
|
query,
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
3953
|
+
steps,
|
|
3954
|
+
manage,
|
|
3955
|
+
history,
|
|
3956
|
+
schema
|
|
2436
3957
|
);
|
|
2437
3958
|
return result;
|
|
2438
3959
|
}
|
|
@@ -2442,7 +3963,7 @@ var MCPAgent = class {
|
|
|
2442
3963
|
let finalOutput = null;
|
|
2443
3964
|
let stepsTaken = 0;
|
|
2444
3965
|
try {
|
|
2445
|
-
if (
|
|
3966
|
+
if (manage && !this._initialized) {
|
|
2446
3967
|
await this.initialize();
|
|
2447
3968
|
initializedHere = true;
|
|
2448
3969
|
} else if (!this._initialized && this.autoInitialize) {
|
|
@@ -2466,7 +3987,7 @@ var MCPAgent = class {
|
|
|
2466
3987
|
this._agentExecutor = this.createAgent();
|
|
2467
3988
|
}
|
|
2468
3989
|
}
|
|
2469
|
-
const historyToUse =
|
|
3990
|
+
const historyToUse = history ?? this.conversationHistory;
|
|
2470
3991
|
const langchainHistory = [];
|
|
2471
3992
|
for (const msg of historyToUse) {
|
|
2472
3993
|
if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
|
|
@@ -2607,13 +4128,13 @@ var MCPAgent = class {
|
|
|
2607
4128
|
this.addToHistory(msg);
|
|
2608
4129
|
}
|
|
2609
4130
|
}
|
|
2610
|
-
if (
|
|
4131
|
+
if (schema && finalOutput) {
|
|
2611
4132
|
try {
|
|
2612
4133
|
logger.info("\u{1F527} Attempting structured output...");
|
|
2613
4134
|
const structuredResult = await this._attemptStructuredOutput(
|
|
2614
4135
|
finalOutput,
|
|
2615
4136
|
this.llm,
|
|
2616
|
-
|
|
4137
|
+
schema
|
|
2617
4138
|
);
|
|
2618
4139
|
if (this.memoryEnabled) {
|
|
2619
4140
|
this.addToHistory(
|
|
@@ -2639,7 +4160,7 @@ var MCPAgent = class {
|
|
|
2639
4160
|
return finalOutput || "No output generated";
|
|
2640
4161
|
} catch (e) {
|
|
2641
4162
|
logger.error(`\u274C Error running query: ${e}`);
|
|
2642
|
-
if (initializedHere &&
|
|
4163
|
+
if (initializedHere && manage) {
|
|
2643
4164
|
logger.info("\u{1F9F9} Cleaning up resources after error");
|
|
2644
4165
|
await this.close();
|
|
2645
4166
|
}
|
|
@@ -2669,9 +4190,9 @@ var MCPAgent = class {
|
|
|
2669
4190
|
maxStepsConfigured: this.maxSteps,
|
|
2670
4191
|
memoryEnabled: this.memoryEnabled,
|
|
2671
4192
|
useServerManager: this.useServerManager,
|
|
2672
|
-
maxStepsUsed:
|
|
2673
|
-
manageConnector,
|
|
2674
|
-
externalHistoryUsed:
|
|
4193
|
+
maxStepsUsed: steps ?? null,
|
|
4194
|
+
manageConnector: manage ?? true,
|
|
4195
|
+
externalHistoryUsed: history !== void 0,
|
|
2675
4196
|
stepsTaken,
|
|
2676
4197
|
toolsUsedCount: this.toolsUsedNames.length,
|
|
2677
4198
|
toolsUsedNames: this.toolsUsedNames,
|
|
@@ -2680,7 +4201,7 @@ var MCPAgent = class {
|
|
|
2680
4201
|
errorType: success ? null : "execution_error",
|
|
2681
4202
|
conversationHistoryLength
|
|
2682
4203
|
});
|
|
2683
|
-
if (
|
|
4204
|
+
if (manage && !this.client && initializedHere) {
|
|
2684
4205
|
logger.info("\u{1F9F9} Closing agent after stream completion");
|
|
2685
4206
|
await this.close();
|
|
2686
4207
|
}
|
|
@@ -2708,15 +4229,28 @@ var MCPAgent = class {
|
|
|
2708
4229
|
this._agentExecutor = null;
|
|
2709
4230
|
this._tools = [];
|
|
2710
4231
|
if (this.client) {
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
4232
|
+
if (this.clientOwnedByAgent) {
|
|
4233
|
+
logger.info(
|
|
4234
|
+
"\u{1F504} Closing internally-created client (simplified mode) and cleaning up resources"
|
|
4235
|
+
);
|
|
4236
|
+
await this.client.close();
|
|
4237
|
+
this.sessions = {};
|
|
4238
|
+
this.client = void 0;
|
|
4239
|
+
} else {
|
|
4240
|
+
logger.info("\u{1F504} Closing client and cleaning up resources");
|
|
4241
|
+
await this.client.close();
|
|
4242
|
+
this.sessions = {};
|
|
4243
|
+
}
|
|
2714
4244
|
} else {
|
|
2715
4245
|
for (const connector of this.connectors) {
|
|
2716
4246
|
logger.info("\u{1F504} Disconnecting connector");
|
|
2717
4247
|
await connector.disconnect();
|
|
2718
4248
|
}
|
|
2719
4249
|
}
|
|
4250
|
+
if (this.isSimplifiedMode && this.llm) {
|
|
4251
|
+
logger.debug("\u{1F504} Clearing LLM reference (simplified mode)");
|
|
4252
|
+
this.llm = void 0;
|
|
4253
|
+
}
|
|
2720
4254
|
if ("connectorToolMap" in this.adapter) {
|
|
2721
4255
|
this.adapter = new LangChainAdapter();
|
|
2722
4256
|
}
|
|
@@ -2725,16 +4259,12 @@ var MCPAgent = class {
|
|
|
2725
4259
|
logger.info("\u{1F44B} Agent closed successfully");
|
|
2726
4260
|
}
|
|
2727
4261
|
}
|
|
2728
|
-
|
|
2729
|
-
* Yields with pretty-printed output for code mode.
|
|
2730
|
-
* This method formats and displays tool executions in a user-friendly way with syntax highlighting.
|
|
2731
|
-
*/
|
|
2732
|
-
async *prettyStreamEvents(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
4262
|
+
async *prettyStreamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
2733
4263
|
const { prettyStreamEvents: prettyStream } = await import("./display-A5IEINAP.js");
|
|
2734
4264
|
const finalResponse = "";
|
|
2735
4265
|
for await (const _ of prettyStream(
|
|
2736
4266
|
this.streamEvents(
|
|
2737
|
-
|
|
4267
|
+
queryOrOptions,
|
|
2738
4268
|
maxSteps,
|
|
2739
4269
|
manageConnector,
|
|
2740
4270
|
externalHistory,
|
|
@@ -2745,22 +4275,32 @@ var MCPAgent = class {
|
|
|
2745
4275
|
}
|
|
2746
4276
|
return finalResponse;
|
|
2747
4277
|
}
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
4278
|
+
async *streamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
4279
|
+
const normalized = normalizeRunOptions(
|
|
4280
|
+
queryOrOptions,
|
|
4281
|
+
maxSteps,
|
|
4282
|
+
manageConnector,
|
|
4283
|
+
externalHistory,
|
|
4284
|
+
outputSchema
|
|
4285
|
+
);
|
|
4286
|
+
let { query } = normalized;
|
|
4287
|
+
const {
|
|
4288
|
+
maxSteps: steps,
|
|
4289
|
+
manageConnector: manage,
|
|
4290
|
+
externalHistory: history,
|
|
4291
|
+
outputSchema: schema
|
|
4292
|
+
} = normalized;
|
|
2753
4293
|
let initializedHere = false;
|
|
2754
4294
|
const startTime = Date.now();
|
|
2755
4295
|
let success = false;
|
|
2756
4296
|
let eventCount = 0;
|
|
2757
4297
|
let totalResponseLength = 0;
|
|
2758
4298
|
let finalResponse = "";
|
|
2759
|
-
if (
|
|
2760
|
-
query = this._enhanceQueryWithSchema(query,
|
|
4299
|
+
if (schema) {
|
|
4300
|
+
query = this._enhanceQueryWithSchema(query, schema);
|
|
2761
4301
|
}
|
|
2762
4302
|
try {
|
|
2763
|
-
if (
|
|
4303
|
+
if (manage && !this._initialized) {
|
|
2764
4304
|
await this.initialize();
|
|
2765
4305
|
initializedHere = true;
|
|
2766
4306
|
} else if (!this._initialized && this.autoInitialize) {
|
|
@@ -2771,14 +4311,14 @@ var MCPAgent = class {
|
|
|
2771
4311
|
if (!agentExecutor) {
|
|
2772
4312
|
throw new Error("MCP agent failed to initialize");
|
|
2773
4313
|
}
|
|
2774
|
-
this.maxSteps =
|
|
4314
|
+
this.maxSteps = steps ?? this.maxSteps;
|
|
2775
4315
|
const display_query = typeof query === "string" && query.length > 50 ? `${query.slice(0, 50).replace(/\n/g, " ")}...` : typeof query === "string" ? query.replace(/\n/g, " ") : String(query);
|
|
2776
4316
|
logger.info(`\u{1F4AC} Received query for streamEvents: '${display_query}'`);
|
|
2777
4317
|
if (this.memoryEnabled) {
|
|
2778
4318
|
logger.info(`\u{1F504} Adding user message to history: ${display_query}`);
|
|
2779
4319
|
this.addToHistory(new HumanMessage({ content: query }));
|
|
2780
4320
|
}
|
|
2781
|
-
const historyToUse =
|
|
4321
|
+
const historyToUse = history ?? this.conversationHistory;
|
|
2782
4322
|
const langchainHistory = [];
|
|
2783
4323
|
for (const msg of historyToUse) {
|
|
2784
4324
|
if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
|
|
@@ -2845,17 +4385,13 @@ var MCPAgent = class {
|
|
|
2845
4385
|
}
|
|
2846
4386
|
}
|
|
2847
4387
|
}
|
|
2848
|
-
if (
|
|
4388
|
+
if (schema && finalResponse) {
|
|
2849
4389
|
logger.info("\u{1F527} Attempting structured output conversion...");
|
|
2850
4390
|
try {
|
|
2851
4391
|
let conversionCompleted = false;
|
|
2852
4392
|
let conversionResult = null;
|
|
2853
4393
|
let conversionError = null;
|
|
2854
|
-
this._attemptStructuredOutput(
|
|
2855
|
-
finalResponse,
|
|
2856
|
-
this.llm,
|
|
2857
|
-
outputSchema
|
|
2858
|
-
).then((result) => {
|
|
4394
|
+
this._attemptStructuredOutput(finalResponse, this.llm, schema).then((result) => {
|
|
2859
4395
|
conversionCompleted = true;
|
|
2860
4396
|
conversionResult = result;
|
|
2861
4397
|
return result;
|
|
@@ -2910,7 +4446,7 @@ var MCPAgent = class {
|
|
|
2910
4446
|
success = true;
|
|
2911
4447
|
} catch (e) {
|
|
2912
4448
|
logger.error(`\u274C Error during streamEvents: ${e}`);
|
|
2913
|
-
if (initializedHere &&
|
|
4449
|
+
if (initializedHere && manage) {
|
|
2914
4450
|
logger.info(
|
|
2915
4451
|
"\u{1F9F9} Cleaning up resources after initialization error in streamEvents"
|
|
2916
4452
|
);
|
|
@@ -2941,15 +4477,15 @@ var MCPAgent = class {
|
|
|
2941
4477
|
maxStepsConfigured: this.maxSteps,
|
|
2942
4478
|
memoryEnabled: this.memoryEnabled,
|
|
2943
4479
|
useServerManager: this.useServerManager,
|
|
2944
|
-
maxStepsUsed:
|
|
2945
|
-
manageConnector,
|
|
2946
|
-
externalHistoryUsed:
|
|
4480
|
+
maxStepsUsed: steps ?? null,
|
|
4481
|
+
manageConnector: manage ?? true,
|
|
4482
|
+
externalHistoryUsed: history !== void 0,
|
|
2947
4483
|
response: `[STREAMED RESPONSE - ${totalResponseLength} chars]`,
|
|
2948
4484
|
executionTimeMs,
|
|
2949
4485
|
errorType: success ? null : "streaming_error",
|
|
2950
4486
|
conversationHistoryLength
|
|
2951
4487
|
});
|
|
2952
|
-
if (
|
|
4488
|
+
if (manage && !this.client && initializedHere) {
|
|
2953
4489
|
logger.info("\u{1F9F9} Closing agent after streamEvents completion");
|
|
2954
4490
|
await this.close();
|
|
2955
4491
|
}
|
|
@@ -3152,6 +4688,13 @@ ${formatPrompt}`
|
|
|
3152
4688
|
export {
|
|
3153
4689
|
BaseAdapter,
|
|
3154
4690
|
LangChainAdapter,
|
|
4691
|
+
BaseCodeExecutor,
|
|
4692
|
+
E2BCodeExecutor,
|
|
4693
|
+
isVMAvailable,
|
|
4694
|
+
VMCodeExecutor,
|
|
4695
|
+
StdioConnector,
|
|
4696
|
+
loadConfigFile,
|
|
4697
|
+
MCPClient,
|
|
3155
4698
|
AcquireActiveMCPServerTool,
|
|
3156
4699
|
AddMCPServerFromConfigTool,
|
|
3157
4700
|
ConnectMCPServerTool,
|
|
@@ -3160,5 +4703,9 @@ export {
|
|
|
3160
4703
|
ServerManager,
|
|
3161
4704
|
ObservabilityManager,
|
|
3162
4705
|
RemoteAgent,
|
|
4706
|
+
parseLLMString,
|
|
4707
|
+
createLLMFromString,
|
|
4708
|
+
isValidLLMString,
|
|
4709
|
+
getSupportedProviders,
|
|
3163
4710
|
MCPAgent
|
|
3164
4711
|
};
|