mcp-use 1.11.0-canary.3 → 1.11.0-canary.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-FDWI2WVM.js → chunk-454ZT2R7.js} +15 -91
- package/dist/{chunk-BONN23WU.js → chunk-52OY3IIW.js} +2 -2
- package/dist/chunk-6RVQ5RGR.js +12 -0
- package/dist/chunk-BAFXO6MT.js +101 -0
- package/dist/{chunk-TZ7SHSRY.js → chunk-FONZ4CWK.js} +1 -1
- package/dist/{chunk-WFPXUU4A.js → chunk-FQJ6Z3U6.js} +1 -1
- package/dist/{chunk-YIZWQ5PM.js → chunk-JRFJXT2T.js} +1 -1
- package/dist/{chunk-DKLRVWPJ.js → chunk-WK34REFK.js} +3 -8
- package/dist/{chunk-KZL3RCT6.js → chunk-ZP4QTLQC.js} +1419 -88
- package/dist/index.cjs +4745 -4443
- package/dist/index.js +26 -1035
- package/dist/src/agents/index.cjs +2881 -157
- 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 +6 -4
- 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 +1632 -201
- package/dist/src/browser.js +18 -7
- package/dist/src/client/base.d.ts +1 -0
- package/dist/src/client/base.d.ts.map +1 -1
- package/dist/src/client/prompts.js +4 -3
- package/dist/src/react/index.cjs +12 -3
- package/dist/src/react/index.js +5 -4
- package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
- package/dist/src/server/index.cjs +91 -64
- package/dist/src/server/index.js +93 -66
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/types/common.d.ts +26 -0
- package/dist/src/server/types/common.d.ts.map +1 -1
- package/dist/src/session.d.ts +2 -2
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/{tool-execution-helpers-HNASWGXY.js → tool-execution-helpers-3RAOCSJ4.js} +2 -2
- package/package.json +5 -4
- /package/dist/{chunk-EW4MJSHA.js → chunk-H4BZVTGK.js} +0 -0
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CodeModeConnector
|
|
3
|
+
} from "./chunk-WK34REFK.js";
|
|
4
|
+
import {
|
|
5
|
+
BaseMCPClient,
|
|
6
|
+
ConnectionManager,
|
|
7
|
+
HttpConnector,
|
|
8
|
+
MCPSession
|
|
9
|
+
} from "./chunk-454ZT2R7.js";
|
|
10
|
+
import {
|
|
11
|
+
BaseConnector
|
|
12
|
+
} from "./chunk-JRFJXT2T.js";
|
|
13
|
+
import {
|
|
14
|
+
Tel,
|
|
2
15
|
Telemetry,
|
|
3
16
|
extractModelInfo,
|
|
4
17
|
getPackageVersion
|
|
5
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-FONZ4CWK.js";
|
|
6
19
|
import {
|
|
7
20
|
logger
|
|
8
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
|
|
@@ -1048,6 +1062,1024 @@ var LangChainAdapter = class extends BaseAdapter {
|
|
|
1048
1062
|
}
|
|
1049
1063
|
};
|
|
1050
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;
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
get publicIdentifier() {
|
|
1843
|
+
return {
|
|
1844
|
+
type: "stdio",
|
|
1845
|
+
"command&args": `${this.command} ${this.args.join(" ")}`
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
|
|
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
|
+
});
|
|
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");
|
|
1877
|
+
}
|
|
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 {
|
|
1884
|
+
static {
|
|
1885
|
+
__name(this, "MCPClient");
|
|
1886
|
+
}
|
|
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);
|
|
1955
|
+
}
|
|
1956
|
+
/**
|
|
1957
|
+
* Save configuration to a file (Node.js only)
|
|
1958
|
+
*/
|
|
1959
|
+
saveConfig(filepath) {
|
|
1960
|
+
const dir = path.dirname(filepath);
|
|
1961
|
+
if (!fs.existsSync(dir)) {
|
|
1962
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1963
|
+
}
|
|
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"
|
|
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 {
|
|
2011
|
+
try {
|
|
2012
|
+
this._codeExecutor = new VMCodeExecutor(
|
|
2013
|
+
this,
|
|
2014
|
+
this._executorOptions
|
|
2015
|
+
);
|
|
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
|
+
}
|
|
2032
|
+
}
|
|
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";
|
|
2068
|
+
});
|
|
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();
|
|
2080
|
+
}
|
|
2081
|
+
};
|
|
2082
|
+
|
|
1051
2083
|
// src/managers/tools/acquire_active_mcp_server.ts
|
|
1052
2084
|
import { z as z3 } from "zod";
|
|
1053
2085
|
|
|
@@ -1606,6 +2638,26 @@ var ObservabilityManager = class {
|
|
|
1606
2638
|
import { toJSONSchema } from "zod";
|
|
1607
2639
|
var API_CHATS_ENDPOINT = "/api/v1/chats";
|
|
1608
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");
|
|
1609
2661
|
var RemoteAgent = class {
|
|
1610
2662
|
static {
|
|
1611
2663
|
__name(this, "RemoteAgent");
|
|
@@ -1702,8 +2754,20 @@ var RemoteAgent = class {
|
|
|
1702
2754
|
throw new Error(`Failed to create chat session: ${String(e)}`);
|
|
1703
2755
|
}
|
|
1704
2756
|
}
|
|
1705
|
-
async run(
|
|
1706
|
-
|
|
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) {
|
|
1707
2771
|
logger.warn("External history is not yet supported for remote execution");
|
|
1708
2772
|
}
|
|
1709
2773
|
try {
|
|
@@ -1714,10 +2778,10 @@ var RemoteAgent = class {
|
|
|
1714
2778
|
const chatId = this.chatId;
|
|
1715
2779
|
const executionPayload = {
|
|
1716
2780
|
query,
|
|
1717
|
-
max_steps:
|
|
2781
|
+
max_steps: steps ?? 10
|
|
1718
2782
|
};
|
|
1719
|
-
if (
|
|
1720
|
-
executionPayload.output_schema = this.pydanticToJsonSchema(
|
|
2783
|
+
if (schema) {
|
|
2784
|
+
executionPayload.output_schema = this.pydanticToJsonSchema(schema);
|
|
1721
2785
|
logger.info(`\u{1F527} Using structured output with schema`);
|
|
1722
2786
|
}
|
|
1723
2787
|
const headers = {
|
|
@@ -1791,8 +2855,8 @@ Raw error: ${result}`
|
|
|
1791
2855
|
);
|
|
1792
2856
|
}
|
|
1793
2857
|
}
|
|
1794
|
-
if (
|
|
1795
|
-
return this.parseStructuredResponse(result,
|
|
2858
|
+
if (schema) {
|
|
2859
|
+
return this.parseStructuredResponse(result, schema);
|
|
1796
2860
|
}
|
|
1797
2861
|
if (typeof result === "object" && result !== null && "result" in result) {
|
|
1798
2862
|
return result.result;
|
|
@@ -1817,9 +2881,9 @@ Raw error: ${result}`
|
|
|
1817
2881
|
}
|
|
1818
2882
|
}
|
|
1819
2883
|
// eslint-disable-next-line require-yield
|
|
1820
|
-
async *stream(
|
|
2884
|
+
async *stream(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
1821
2885
|
const result = await this.run(
|
|
1822
|
-
|
|
2886
|
+
queryOrOptions,
|
|
1823
2887
|
maxSteps,
|
|
1824
2888
|
manageConnector,
|
|
1825
2889
|
externalHistory,
|
|
@@ -1832,6 +2896,144 @@ Raw error: ${result}`
|
|
|
1832
2896
|
}
|
|
1833
2897
|
};
|
|
1834
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
|
+
|
|
1835
3037
|
// src/agents/mcp_agent.ts
|
|
1836
3038
|
import {
|
|
1837
3039
|
AIMessage,
|
|
@@ -1935,6 +3137,26 @@ Here are the tools *currently* available to you (this list includes server manag
|
|
|
1935
3137
|
`;
|
|
1936
3138
|
|
|
1937
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");
|
|
1938
3160
|
var MCPAgent = class {
|
|
1939
3161
|
static {
|
|
1940
3162
|
__name(this, "MCPAgent");
|
|
@@ -1980,6 +3202,12 @@ var MCPAgent = class {
|
|
|
1980
3202
|
// Remote agent support
|
|
1981
3203
|
isRemote = false;
|
|
1982
3204
|
remoteAgent = null;
|
|
3205
|
+
// Simplified mode support
|
|
3206
|
+
isSimplifiedMode = false;
|
|
3207
|
+
llmString;
|
|
3208
|
+
llmConfig;
|
|
3209
|
+
mcpServersConfig;
|
|
3210
|
+
clientOwnedByAgent = false;
|
|
1983
3211
|
constructor(options) {
|
|
1984
3212
|
if (options.agentId) {
|
|
1985
3213
|
this.isRemote = true;
|
|
@@ -2013,9 +3241,36 @@ var MCPAgent = class {
|
|
|
2013
3241
|
"llm is required for local execution. For remote execution, provide agentId instead."
|
|
2014
3242
|
);
|
|
2015
3243
|
}
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
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
|
+
}
|
|
2019
3274
|
this.maxSteps = options.maxSteps ?? 5;
|
|
2020
3275
|
this.autoInitialize = options.autoInitialize ?? false;
|
|
2021
3276
|
this.memoryEnabled = options.memoryEnabled ?? true;
|
|
@@ -2028,28 +3283,30 @@ var MCPAgent = class {
|
|
|
2028
3283
|
this.useServerManager = options.useServerManager ?? false;
|
|
2029
3284
|
this.verbose = options.verbose ?? false;
|
|
2030
3285
|
this.observe = options.observe ?? true;
|
|
2031
|
-
if (!this.
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
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";
|
|
2041
3306
|
}
|
|
2042
|
-
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
2043
|
-
this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
|
|
2044
3307
|
} else {
|
|
2045
3308
|
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
2046
|
-
|
|
2047
|
-
this.telemetry = Telemetry.getInstance();
|
|
2048
|
-
if (this.llm) {
|
|
2049
|
-
const [provider, name] = extractModelInfo(this.llm);
|
|
2050
|
-
this.modelProvider = provider;
|
|
2051
|
-
this.modelName = name;
|
|
2052
|
-
} else {
|
|
3309
|
+
this.telemetry = Telemetry.getInstance();
|
|
2053
3310
|
this.modelProvider = "unknown";
|
|
2054
3311
|
this.modelName = "unknown";
|
|
2055
3312
|
}
|
|
@@ -2080,6 +3337,40 @@ var MCPAgent = class {
|
|
|
2080
3337
|
return;
|
|
2081
3338
|
}
|
|
2082
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
|
+
}
|
|
2083
3374
|
this.callbacks = await this.observabilityManager.getCallbacks();
|
|
2084
3375
|
const handlerNames = await this.observabilityManager.getHandlerNames();
|
|
2085
3376
|
if (handlerNames.length > 0) {
|
|
@@ -2622,33 +3913,47 @@ var MCPAgent = class {
|
|
|
2622
3913
|
}
|
|
2623
3914
|
}
|
|
2624
3915
|
}
|
|
2625
|
-
async run(
|
|
2626
|
-
|
|
2627
|
-
return this.remoteAgent.run(
|
|
2628
|
-
query,
|
|
2629
|
-
maxSteps,
|
|
2630
|
-
manageConnector,
|
|
2631
|
-
externalHistory,
|
|
2632
|
-
outputSchema
|
|
2633
|
-
);
|
|
2634
|
-
}
|
|
2635
|
-
const generator = this.stream(
|
|
3916
|
+
async run(queryOrOptions, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
3917
|
+
const {
|
|
2636
3918
|
query,
|
|
3919
|
+
maxSteps: steps,
|
|
3920
|
+
manageConnector: manage,
|
|
3921
|
+
externalHistory: history,
|
|
3922
|
+
outputSchema: schema
|
|
3923
|
+
} = normalizeRunOptions(
|
|
3924
|
+
queryOrOptions,
|
|
2637
3925
|
maxSteps,
|
|
2638
3926
|
manageConnector,
|
|
2639
3927
|
externalHistory,
|
|
2640
3928
|
outputSchema
|
|
2641
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);
|
|
2642
3934
|
return this._consumeAndReturn(generator);
|
|
2643
3935
|
}
|
|
2644
|
-
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
|
+
);
|
|
2645
3950
|
if (this.isRemote && this.remoteAgent) {
|
|
2646
3951
|
const result = await this.remoteAgent.run(
|
|
2647
3952
|
query,
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
3953
|
+
steps,
|
|
3954
|
+
manage,
|
|
3955
|
+
history,
|
|
3956
|
+
schema
|
|
2652
3957
|
);
|
|
2653
3958
|
return result;
|
|
2654
3959
|
}
|
|
@@ -2658,7 +3963,7 @@ var MCPAgent = class {
|
|
|
2658
3963
|
let finalOutput = null;
|
|
2659
3964
|
let stepsTaken = 0;
|
|
2660
3965
|
try {
|
|
2661
|
-
if (
|
|
3966
|
+
if (manage && !this._initialized) {
|
|
2662
3967
|
await this.initialize();
|
|
2663
3968
|
initializedHere = true;
|
|
2664
3969
|
} else if (!this._initialized && this.autoInitialize) {
|
|
@@ -2682,7 +3987,7 @@ var MCPAgent = class {
|
|
|
2682
3987
|
this._agentExecutor = this.createAgent();
|
|
2683
3988
|
}
|
|
2684
3989
|
}
|
|
2685
|
-
const historyToUse =
|
|
3990
|
+
const historyToUse = history ?? this.conversationHistory;
|
|
2686
3991
|
const langchainHistory = [];
|
|
2687
3992
|
for (const msg of historyToUse) {
|
|
2688
3993
|
if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
|
|
@@ -2823,13 +4128,13 @@ var MCPAgent = class {
|
|
|
2823
4128
|
this.addToHistory(msg);
|
|
2824
4129
|
}
|
|
2825
4130
|
}
|
|
2826
|
-
if (
|
|
4131
|
+
if (schema && finalOutput) {
|
|
2827
4132
|
try {
|
|
2828
4133
|
logger.info("\u{1F527} Attempting structured output...");
|
|
2829
4134
|
const structuredResult = await this._attemptStructuredOutput(
|
|
2830
4135
|
finalOutput,
|
|
2831
4136
|
this.llm,
|
|
2832
|
-
|
|
4137
|
+
schema
|
|
2833
4138
|
);
|
|
2834
4139
|
if (this.memoryEnabled) {
|
|
2835
4140
|
this.addToHistory(
|
|
@@ -2855,7 +4160,7 @@ var MCPAgent = class {
|
|
|
2855
4160
|
return finalOutput || "No output generated";
|
|
2856
4161
|
} catch (e) {
|
|
2857
4162
|
logger.error(`\u274C Error running query: ${e}`);
|
|
2858
|
-
if (initializedHere &&
|
|
4163
|
+
if (initializedHere && manage) {
|
|
2859
4164
|
logger.info("\u{1F9F9} Cleaning up resources after error");
|
|
2860
4165
|
await this.close();
|
|
2861
4166
|
}
|
|
@@ -2885,9 +4190,9 @@ var MCPAgent = class {
|
|
|
2885
4190
|
maxStepsConfigured: this.maxSteps,
|
|
2886
4191
|
memoryEnabled: this.memoryEnabled,
|
|
2887
4192
|
useServerManager: this.useServerManager,
|
|
2888
|
-
maxStepsUsed:
|
|
2889
|
-
manageConnector,
|
|
2890
|
-
externalHistoryUsed:
|
|
4193
|
+
maxStepsUsed: steps ?? null,
|
|
4194
|
+
manageConnector: manage ?? true,
|
|
4195
|
+
externalHistoryUsed: history !== void 0,
|
|
2891
4196
|
stepsTaken,
|
|
2892
4197
|
toolsUsedCount: this.toolsUsedNames.length,
|
|
2893
4198
|
toolsUsedNames: this.toolsUsedNames,
|
|
@@ -2896,7 +4201,7 @@ var MCPAgent = class {
|
|
|
2896
4201
|
errorType: success ? null : "execution_error",
|
|
2897
4202
|
conversationHistoryLength
|
|
2898
4203
|
});
|
|
2899
|
-
if (
|
|
4204
|
+
if (manage && !this.client && initializedHere) {
|
|
2900
4205
|
logger.info("\u{1F9F9} Closing agent after stream completion");
|
|
2901
4206
|
await this.close();
|
|
2902
4207
|
}
|
|
@@ -2924,15 +4229,28 @@ var MCPAgent = class {
|
|
|
2924
4229
|
this._agentExecutor = null;
|
|
2925
4230
|
this._tools = [];
|
|
2926
4231
|
if (this.client) {
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
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
|
+
}
|
|
2930
4244
|
} else {
|
|
2931
4245
|
for (const connector of this.connectors) {
|
|
2932
4246
|
logger.info("\u{1F504} Disconnecting connector");
|
|
2933
4247
|
await connector.disconnect();
|
|
2934
4248
|
}
|
|
2935
4249
|
}
|
|
4250
|
+
if (this.isSimplifiedMode && this.llm) {
|
|
4251
|
+
logger.debug("\u{1F504} Clearing LLM reference (simplified mode)");
|
|
4252
|
+
this.llm = void 0;
|
|
4253
|
+
}
|
|
2936
4254
|
if ("connectorToolMap" in this.adapter) {
|
|
2937
4255
|
this.adapter = new LangChainAdapter();
|
|
2938
4256
|
}
|
|
@@ -2941,16 +4259,12 @@ var MCPAgent = class {
|
|
|
2941
4259
|
logger.info("\u{1F44B} Agent closed successfully");
|
|
2942
4260
|
}
|
|
2943
4261
|
}
|
|
2944
|
-
|
|
2945
|
-
* Yields with pretty-printed output for code mode.
|
|
2946
|
-
* This method formats and displays tool executions in a user-friendly way with syntax highlighting.
|
|
2947
|
-
*/
|
|
2948
|
-
async *prettyStreamEvents(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
4262
|
+
async *prettyStreamEvents(queryOrOptions, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
2949
4263
|
const { prettyStreamEvents: prettyStream } = await import("./display-A5IEINAP.js");
|
|
2950
4264
|
const finalResponse = "";
|
|
2951
4265
|
for await (const _ of prettyStream(
|
|
2952
4266
|
this.streamEvents(
|
|
2953
|
-
|
|
4267
|
+
queryOrOptions,
|
|
2954
4268
|
maxSteps,
|
|
2955
4269
|
manageConnector,
|
|
2956
4270
|
externalHistory,
|
|
@@ -2961,22 +4275,32 @@ var MCPAgent = class {
|
|
|
2961
4275
|
}
|
|
2962
4276
|
return finalResponse;
|
|
2963
4277
|
}
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
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;
|
|
2969
4293
|
let initializedHere = false;
|
|
2970
4294
|
const startTime = Date.now();
|
|
2971
4295
|
let success = false;
|
|
2972
4296
|
let eventCount = 0;
|
|
2973
4297
|
let totalResponseLength = 0;
|
|
2974
4298
|
let finalResponse = "";
|
|
2975
|
-
if (
|
|
2976
|
-
query = this._enhanceQueryWithSchema(query,
|
|
4299
|
+
if (schema) {
|
|
4300
|
+
query = this._enhanceQueryWithSchema(query, schema);
|
|
2977
4301
|
}
|
|
2978
4302
|
try {
|
|
2979
|
-
if (
|
|
4303
|
+
if (manage && !this._initialized) {
|
|
2980
4304
|
await this.initialize();
|
|
2981
4305
|
initializedHere = true;
|
|
2982
4306
|
} else if (!this._initialized && this.autoInitialize) {
|
|
@@ -2987,14 +4311,14 @@ var MCPAgent = class {
|
|
|
2987
4311
|
if (!agentExecutor) {
|
|
2988
4312
|
throw new Error("MCP agent failed to initialize");
|
|
2989
4313
|
}
|
|
2990
|
-
this.maxSteps =
|
|
4314
|
+
this.maxSteps = steps ?? this.maxSteps;
|
|
2991
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);
|
|
2992
4316
|
logger.info(`\u{1F4AC} Received query for streamEvents: '${display_query}'`);
|
|
2993
4317
|
if (this.memoryEnabled) {
|
|
2994
4318
|
logger.info(`\u{1F504} Adding user message to history: ${display_query}`);
|
|
2995
4319
|
this.addToHistory(new HumanMessage({ content: query }));
|
|
2996
4320
|
}
|
|
2997
|
-
const historyToUse =
|
|
4321
|
+
const historyToUse = history ?? this.conversationHistory;
|
|
2998
4322
|
const langchainHistory = [];
|
|
2999
4323
|
for (const msg of historyToUse) {
|
|
3000
4324
|
if (this._isHumanMessageLike(msg) || this._isAIMessageLike(msg) || this._isToolMessageLike(msg)) {
|
|
@@ -3061,17 +4385,13 @@ var MCPAgent = class {
|
|
|
3061
4385
|
}
|
|
3062
4386
|
}
|
|
3063
4387
|
}
|
|
3064
|
-
if (
|
|
4388
|
+
if (schema && finalResponse) {
|
|
3065
4389
|
logger.info("\u{1F527} Attempting structured output conversion...");
|
|
3066
4390
|
try {
|
|
3067
4391
|
let conversionCompleted = false;
|
|
3068
4392
|
let conversionResult = null;
|
|
3069
4393
|
let conversionError = null;
|
|
3070
|
-
this._attemptStructuredOutput(
|
|
3071
|
-
finalResponse,
|
|
3072
|
-
this.llm,
|
|
3073
|
-
outputSchema
|
|
3074
|
-
).then((result) => {
|
|
4394
|
+
this._attemptStructuredOutput(finalResponse, this.llm, schema).then((result) => {
|
|
3075
4395
|
conversionCompleted = true;
|
|
3076
4396
|
conversionResult = result;
|
|
3077
4397
|
return result;
|
|
@@ -3126,7 +4446,7 @@ var MCPAgent = class {
|
|
|
3126
4446
|
success = true;
|
|
3127
4447
|
} catch (e) {
|
|
3128
4448
|
logger.error(`\u274C Error during streamEvents: ${e}`);
|
|
3129
|
-
if (initializedHere &&
|
|
4449
|
+
if (initializedHere && manage) {
|
|
3130
4450
|
logger.info(
|
|
3131
4451
|
"\u{1F9F9} Cleaning up resources after initialization error in streamEvents"
|
|
3132
4452
|
);
|
|
@@ -3157,15 +4477,15 @@ var MCPAgent = class {
|
|
|
3157
4477
|
maxStepsConfigured: this.maxSteps,
|
|
3158
4478
|
memoryEnabled: this.memoryEnabled,
|
|
3159
4479
|
useServerManager: this.useServerManager,
|
|
3160
|
-
maxStepsUsed:
|
|
3161
|
-
manageConnector,
|
|
3162
|
-
externalHistoryUsed:
|
|
4480
|
+
maxStepsUsed: steps ?? null,
|
|
4481
|
+
manageConnector: manage ?? true,
|
|
4482
|
+
externalHistoryUsed: history !== void 0,
|
|
3163
4483
|
response: `[STREAMED RESPONSE - ${totalResponseLength} chars]`,
|
|
3164
4484
|
executionTimeMs,
|
|
3165
4485
|
errorType: success ? null : "streaming_error",
|
|
3166
4486
|
conversationHistoryLength
|
|
3167
4487
|
});
|
|
3168
|
-
if (
|
|
4488
|
+
if (manage && !this.client && initializedHere) {
|
|
3169
4489
|
logger.info("\u{1F9F9} Closing agent after streamEvents completion");
|
|
3170
4490
|
await this.close();
|
|
3171
4491
|
}
|
|
@@ -3368,6 +4688,13 @@ ${formatPrompt}`
|
|
|
3368
4688
|
export {
|
|
3369
4689
|
BaseAdapter,
|
|
3370
4690
|
LangChainAdapter,
|
|
4691
|
+
BaseCodeExecutor,
|
|
4692
|
+
E2BCodeExecutor,
|
|
4693
|
+
isVMAvailable,
|
|
4694
|
+
VMCodeExecutor,
|
|
4695
|
+
StdioConnector,
|
|
4696
|
+
loadConfigFile,
|
|
4697
|
+
MCPClient,
|
|
3371
4698
|
AcquireActiveMCPServerTool,
|
|
3372
4699
|
AddMCPServerFromConfigTool,
|
|
3373
4700
|
ConnectMCPServerTool,
|
|
@@ -3376,5 +4703,9 @@ export {
|
|
|
3376
4703
|
ServerManager,
|
|
3377
4704
|
ObservabilityManager,
|
|
3378
4705
|
RemoteAgent,
|
|
4706
|
+
parseLLMString,
|
|
4707
|
+
createLLMFromString,
|
|
4708
|
+
isValidLLMString,
|
|
4709
|
+
getSupportedProviders,
|
|
3379
4710
|
MCPAgent
|
|
3380
4711
|
};
|