@toolsdk.ai/registry 1.0.113 → 1.0.114
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/api/package-handler.js +7 -6
- package/dist/api/package-so.d.ts +7 -7
- package/dist/api/package-so.js +45 -85
- package/dist/helper.d.ts +3 -1
- package/dist/helper.js +34 -0
- package/dist/sandbox/mcp-sandbox-client.d.ts +4 -25
- package/dist/sandbox/mcp-sandbox-client.js +92 -291
- package/dist/sandbox/mcp-sandbox-client.test.d.ts +1 -0
- package/dist/sandbox/mcp-sandbox-client.test.js +491 -0
- package/dist/types.d.ts +1 -0
- package/package.json +2 -1
- package/packages/search-data-extraction/ref-tools-mcp.json +7 -2
|
@@ -1,345 +1,138 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getPackageConfigByKey } from "../helper";
|
|
1
|
+
import { Daytona, Image } from "@daytonaio/sdk";
|
|
2
|
+
import { extractLastOuterJSON, getPackageConfigByKey } from "../helper";
|
|
3
3
|
export class MCPSandboxClient {
|
|
4
|
-
constructor(
|
|
4
|
+
constructor(runtime = "node", provider = "DAYTONA") {
|
|
5
5
|
this.sandbox = null;
|
|
6
6
|
this.initializing = null;
|
|
7
|
-
this.
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.lastTouchTime = null;
|
|
12
|
-
this.THROTTLE_DELAY_MS = 10 * 1000;
|
|
13
|
-
// Lifecycle and Auto-Recovery
|
|
14
|
-
this.createdAt = null;
|
|
15
|
-
this.lastUsedAt = null;
|
|
16
|
-
this.ttlTimer = null;
|
|
17
|
-
this.autoCloseOnIdleTimer = null;
|
|
18
|
-
this.idleCloseMs = null;
|
|
19
|
-
this.apiKey = apiKey || process.env.E2B_API_KEY || "e2b-api-key-placeholder";
|
|
7
|
+
this.runtime = "node";
|
|
8
|
+
this.apiKey = process.env.DAYTONA_API_KEY || "daytona-api-key-placeholder";
|
|
9
|
+
this.runtime = runtime;
|
|
10
|
+
this.provider = provider;
|
|
20
11
|
}
|
|
21
12
|
// Safe initialize: ensures concurrent calls don't create duplicate sandboxes
|
|
22
13
|
async initialize() {
|
|
23
14
|
if (this.sandbox) {
|
|
24
|
-
// this.touch();
|
|
25
|
-
// console.log("[MCPSandboxClient] Sandbox already initialized");
|
|
26
15
|
return;
|
|
27
16
|
}
|
|
28
17
|
if (this.initializing) {
|
|
29
18
|
// Wait for existing initialization to complete
|
|
30
19
|
await this.initializing;
|
|
31
|
-
// this.touch();
|
|
32
20
|
return;
|
|
33
21
|
}
|
|
34
|
-
const initLabel = `[MCPSandboxClient] Sandbox initialization ${Date.now()}-${(Math.random() * 1000000) | 0}`;
|
|
35
|
-
console.time(initLabel);
|
|
36
22
|
this.initializing = (async () => {
|
|
37
23
|
try {
|
|
38
|
-
|
|
24
|
+
const daytonaConfig = {
|
|
39
25
|
apiKey: this.apiKey,
|
|
40
|
-
|
|
26
|
+
};
|
|
27
|
+
if (this.provider === "SANDOCK") {
|
|
28
|
+
daytonaConfig.apiUrl = process.env.SANDOCK_DAYTONA_API_URL || process.env.DAYTONA_API_URL;
|
|
29
|
+
if (!daytonaConfig.apiUrl) {
|
|
30
|
+
console.warn("[MCPSandboxClient] SANDOCK provider selected but SANDOCK_DAYTONA_API_URL is not set. Falling back to default Daytona API URL.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const daytona = new Daytona(daytonaConfig);
|
|
34
|
+
// Create image with required dependencies
|
|
35
|
+
const declarativeImage = Image.base("node:20")
|
|
36
|
+
.runCommands("npm install -g pnpm", "mkdir -p /workspace", "cd /workspace && npm init -y", "cd /workspace && pnpm add @modelcontextprotocol/sdk")
|
|
37
|
+
.workdir("/workspace");
|
|
38
|
+
// const pnpmStoreVolume = await daytona.volume.get("pnpm-store-shared", true);
|
|
39
|
+
this.sandbox = await daytona.create({
|
|
40
|
+
language: "javascript",
|
|
41
|
+
image: declarativeImage,
|
|
42
|
+
// volumes: [
|
|
43
|
+
// {
|
|
44
|
+
// volumeId: pnpmStoreVolume.id,
|
|
45
|
+
// mountPath: "/pnpm-store",
|
|
46
|
+
// },
|
|
47
|
+
// ],
|
|
41
48
|
});
|
|
42
|
-
|
|
43
|
-
this.touch();
|
|
44
|
-
// After 1-hour forced session termination
|
|
45
|
-
this.setupTTLTimer();
|
|
46
|
-
console.log("[MCPSandboxClient] Sandbox created successfully");
|
|
49
|
+
console.log("[MCPSandboxClient] Daytona Sandbox created successfully");
|
|
47
50
|
}
|
|
48
51
|
finally {
|
|
49
52
|
this.initializing = null;
|
|
50
53
|
}
|
|
51
54
|
})();
|
|
52
55
|
await this.initializing;
|
|
53
|
-
console.timeEnd(initLabel);
|
|
54
|
-
}
|
|
55
|
-
setupTTLTimer() {
|
|
56
|
-
// Clean up existing timer
|
|
57
|
-
if (this.ttlTimer) {
|
|
58
|
-
clearTimeout(this.ttlTimer);
|
|
59
|
-
this.ttlTimer = null;
|
|
60
|
-
}
|
|
61
|
-
// E2B supports maximum 1-hour sessions, force close at 59m 30s for safety
|
|
62
|
-
const TTL_MS = 60 * 60 * 1000;
|
|
63
|
-
const safetyMs = 30 * 1000;
|
|
64
|
-
const remaining = Math.max(0, TTL_MS - (Date.now() - (this.createdAt || Date.now())));
|
|
65
|
-
this.ttlTimer = setTimeout(async () => {
|
|
66
|
-
console.warn("[MCPSandboxClient] Sandbox TTL reached, closing sandbox to avoid exceeding 1 hour.");
|
|
67
|
-
try {
|
|
68
|
-
await this.kill();
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
console.error("[MCPSandboxClient] Error while killing sandbox after TTL:", err);
|
|
72
|
-
}
|
|
73
|
-
}, remaining - safetyMs);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Update sandbox last used time
|
|
77
|
-
*/
|
|
78
|
-
touch() {
|
|
79
|
-
const now = Date.now();
|
|
80
|
-
// If this is the first call, or more than 10 seconds have passed since the last call
|
|
81
|
-
if (!this.lastTouchTime || now - this.lastTouchTime >= this.THROTTLE_DELAY_MS) {
|
|
82
|
-
this.lastTouchTime = now;
|
|
83
|
-
this.performTouch();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Actually perform the touch operation
|
|
88
|
-
*/
|
|
89
|
-
async performTouch() {
|
|
90
|
-
this.lastUsedAt = Date.now();
|
|
91
|
-
console.log(`[MCPSandboxClient] Sandbox touched at ${this.lastUsedAt}`);
|
|
92
|
-
// Reset E2B sandbox timeout
|
|
93
|
-
if (this.sandbox) {
|
|
94
|
-
console.log("[MCPSandboxClient] Resetting E2B sandbox timeout");
|
|
95
|
-
// const info = await this.sandbox.getInfo();
|
|
96
|
-
// console.log(`[MCPSandboxClient] E2B sandbox info: ${JSON.stringify(info, null, 2)}`);
|
|
97
|
-
this.sandbox.setTimeout(this.E2B_SANDBOX_TIMEOUT_MS).catch((err) => {
|
|
98
|
-
console.error("[MCPSandboxClient] Failed to reset E2B sandbox timeout:", err);
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
// Refresh timer if waiting for idle close
|
|
102
|
-
if (this.autoCloseOnIdleTimer && this.idleCloseMs) {
|
|
103
|
-
clearTimeout(this.autoCloseOnIdleTimer);
|
|
104
|
-
// Reschedule idle close (refresh timer)
|
|
105
|
-
this.autoCloseOnIdleTimer = setTimeout(async () => {
|
|
106
|
-
console.log("[MCPSandboxClient] Idle TTL reached, closing sandbox due to inactivity.");
|
|
107
|
-
try {
|
|
108
|
-
await this.kill();
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
console.error("[MCPSandboxClient] Error while killing sandbox on idle:", err);
|
|
112
|
-
}
|
|
113
|
-
}, this.idleCloseMs);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
// Schedule idle auto-close (called by PackageSO when refCount reaches 0)
|
|
117
|
-
scheduleIdleClose(idleMs) {
|
|
118
|
-
// Save idle close time for refresh
|
|
119
|
-
this.idleCloseMs = idleMs;
|
|
120
|
-
// Clear existing idle timer
|
|
121
|
-
if (this.autoCloseOnIdleTimer) {
|
|
122
|
-
clearTimeout(this.autoCloseOnIdleTimer);
|
|
123
|
-
}
|
|
124
|
-
// Set new idle timer
|
|
125
|
-
this.autoCloseOnIdleTimer = setTimeout(async () => {
|
|
126
|
-
console.log("[MCPSandboxClient] Idle TTL reached, closing sandbox due to inactivity.");
|
|
127
|
-
try {
|
|
128
|
-
await this.kill();
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
console.error("[MCPSandboxClient] Error while killing sandbox on idle:", err);
|
|
132
|
-
}
|
|
133
|
-
}, idleMs);
|
|
134
56
|
}
|
|
135
|
-
// Force close and cleanup
|
|
57
|
+
// Force close and cleanup
|
|
136
58
|
async kill() {
|
|
137
|
-
const killLabel = `[MCPSandboxClient] Sandbox closing ${Date.now()}-${(Math.random() * 1000000) | 0}`;
|
|
138
|
-
console.time(killLabel);
|
|
139
59
|
try {
|
|
140
|
-
if (this.ttlTimer) {
|
|
141
|
-
clearTimeout(this.ttlTimer);
|
|
142
|
-
this.ttlTimer = null;
|
|
143
|
-
}
|
|
144
|
-
if (this.autoCloseOnIdleTimer) {
|
|
145
|
-
clearTimeout(this.autoCloseOnIdleTimer);
|
|
146
|
-
this.autoCloseOnIdleTimer = null;
|
|
147
|
-
}
|
|
148
60
|
if (this.sandbox) {
|
|
149
|
-
|
|
150
|
-
await this.sandbox.kill();
|
|
151
|
-
}
|
|
152
|
-
catch (err) {
|
|
153
|
-
// sandbox.kill may throw, log error but continue cleaning local state
|
|
154
|
-
console.error("[MCPSandboxClient] Error during sandbox.kill():", err);
|
|
155
|
-
}
|
|
156
|
-
this.sandbox = null;
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
console.log("[MCPSandboxClient] No sandbox to close");
|
|
61
|
+
await this.sandbox.delete();
|
|
160
62
|
}
|
|
161
63
|
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.log(err.message);
|
|
66
|
+
}
|
|
162
67
|
finally {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.
|
|
166
|
-
this.lastUsedAt = null;
|
|
167
|
-
console.timeEnd(killLabel);
|
|
68
|
+
this.sandbox = null;
|
|
69
|
+
// clear cache
|
|
70
|
+
// this.toolCache.clear();
|
|
168
71
|
}
|
|
169
72
|
}
|
|
170
|
-
// Clear cache for specific package
|
|
171
|
-
clearPackageCache(packageKey) {
|
|
172
|
-
this.toolCache.delete(packageKey);
|
|
173
|
-
}
|
|
174
|
-
// Clear all tool caches
|
|
175
|
-
clearAllCache() {
|
|
176
|
-
this.toolCache.clear();
|
|
177
|
-
}
|
|
178
73
|
async listTools(packageKey) {
|
|
179
|
-
var _a;
|
|
180
|
-
const cached = this.toolCache.get(packageKey);
|
|
181
|
-
if (cached) {
|
|
182
|
-
const now = Date.now();
|
|
183
|
-
if (now - cached.timestamp < this.TOOL_CACHE_TTL) {
|
|
184
|
-
console.log(`[MCPSandboxClient] Returning cached tools for package: ${packageKey}`);
|
|
185
|
-
// Refresh cache expiration time
|
|
186
|
-
this.toolCache.set(packageKey, {
|
|
187
|
-
tools: cached.tools,
|
|
188
|
-
timestamp: Date.now(),
|
|
189
|
-
});
|
|
190
|
-
this.touch();
|
|
191
|
-
return cached.tools;
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
// Cache expired, remove it
|
|
195
|
-
this.toolCache.delete(packageKey);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
74
|
if (!this.sandbox) {
|
|
199
75
|
throw new Error("Sandbox not initialized. Call initialize() first.");
|
|
200
76
|
}
|
|
201
77
|
const mcpServerConfig = await getPackageConfigByKey(packageKey);
|
|
202
78
|
const testCode = this.generateMCPTestCode(mcpServerConfig, "listTools");
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
79
|
+
try {
|
|
80
|
+
const response = await this.sandbox.process.codeRun(testCode);
|
|
81
|
+
if (response.exitCode !== 0) {
|
|
82
|
+
throw new Error(`Failed to list tools: ${response.result}`);
|
|
83
|
+
}
|
|
84
|
+
const parsedResultStr = extractLastOuterJSON(response.result);
|
|
85
|
+
const result = JSON.parse(parsedResultStr);
|
|
86
|
+
return result.tools;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.error("[MCPSandboxClient] Error listing tools:", err);
|
|
90
|
+
throw err;
|
|
207
91
|
}
|
|
208
|
-
const stdout = ((_a = testResult.logs) === null || _a === void 0 ? void 0 : _a.stdout) || [];
|
|
209
|
-
const last = stdout[stdout.length - 1] || "{}";
|
|
210
|
-
const result = JSON.parse(last);
|
|
211
|
-
this.toolCache.set(packageKey, {
|
|
212
|
-
tools: result.tools,
|
|
213
|
-
timestamp: Date.now(),
|
|
214
|
-
});
|
|
215
|
-
this.touch();
|
|
216
|
-
return result.tools;
|
|
217
92
|
}
|
|
218
93
|
async executeTool(packageKey, toolName, argumentsObj, envs) {
|
|
219
94
|
if (!this.sandbox) {
|
|
220
95
|
throw new Error("Sandbox not initialized. Call initialize() first.");
|
|
221
96
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
97
|
+
const mcpServerConfig = await getPackageConfigByKey(packageKey);
|
|
98
|
+
const testCode = this.generateMCPTestCode(mcpServerConfig, "executeTool", toolName, argumentsObj, envs);
|
|
224
99
|
try {
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (testResult.error) {
|
|
229
|
-
console.error("[MCPSandboxClient] Failed to execute tool:", testResult.error);
|
|
230
|
-
throw new Error(`Failed to execute tool: ${testResult.error}`);
|
|
231
|
-
}
|
|
232
|
-
// Handle stderr output, log if there are error messages
|
|
233
|
-
if (testResult.logs.stderr && testResult.logs.stderr.length > 0) {
|
|
234
|
-
const stderrOutput = testResult.logs.stderr.join("\n");
|
|
235
|
-
console.error("[MCPSandboxClient] Tool execution stderr output:", stderrOutput);
|
|
100
|
+
const response = await this.sandbox.process.codeRun(testCode);
|
|
101
|
+
if (response.exitCode !== 0) {
|
|
102
|
+
throw new Error(`Failed to execute tool: ${response.result}`);
|
|
236
103
|
}
|
|
237
|
-
const
|
|
104
|
+
const parsedResultStr = extractLastOuterJSON(response.result);
|
|
105
|
+
const result = JSON.parse(parsedResultStr);
|
|
238
106
|
if (result.isError) {
|
|
239
107
|
console.error("[MCPSandboxClient] Tool execution error:", result.errorMessage);
|
|
240
108
|
throw new Error(result.errorMessage);
|
|
241
109
|
}
|
|
242
|
-
this.touch();
|
|
243
110
|
return result;
|
|
244
111
|
}
|
|
245
112
|
catch (err) {
|
|
246
|
-
if (err instanceof Error &&
|
|
247
|
-
(err.message.includes("sandbox was not found") || err.message.includes("terminated"))) {
|
|
248
|
-
console.warn("[MCPSandboxClient] Sandbox not found, cleaning up state and reinitializing");
|
|
249
|
-
await this.kill();
|
|
250
|
-
throw new Error("Sandbox was not found. Please retry the operation.");
|
|
251
|
-
}
|
|
252
113
|
console.error("[MCPSandboxClient] Error executing tool:", err);
|
|
253
114
|
throw err;
|
|
254
115
|
}
|
|
255
|
-
finally {
|
|
256
|
-
console.timeEnd(execLabel);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
// Add timeout protection to sandbox.runCode, kill sandbox on timeout
|
|
260
|
-
async runCodeWithTimeout(code, options) {
|
|
261
|
-
if (!this.sandbox)
|
|
262
|
-
throw new Error("Sandbox not initialized.");
|
|
263
|
-
const execPromise = this.sandbox.runCode(code, options);
|
|
264
|
-
const timeoutMs = this.TOOL_EXECUTION_TIMEOUT;
|
|
265
|
-
let timeoutHandle = null;
|
|
266
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
267
|
-
timeoutHandle = setTimeout(async () => {
|
|
268
|
-
const msg = `[MCPSandboxClient] runCode timeout after ${timeoutMs}ms`;
|
|
269
|
-
console.error(msg);
|
|
270
|
-
// After timeout, try to force kill sandbox to recycle resources and avoid subsequent calls using this stuck instance
|
|
271
|
-
try {
|
|
272
|
-
await this.kill();
|
|
273
|
-
}
|
|
274
|
-
catch (err) {
|
|
275
|
-
console.error("[MCPSandboxClient] Error killing sandbox after run timeout:", err);
|
|
276
|
-
}
|
|
277
|
-
reject(new Error(msg));
|
|
278
|
-
}, timeoutMs);
|
|
279
|
-
});
|
|
280
|
-
const label = `[MCPSandboxClient] Tool execution time ${Date.now()}-${(Math.random() * 1000000) | 0}`;
|
|
281
|
-
try {
|
|
282
|
-
console.time(label);
|
|
283
|
-
const result = (await Promise.race([execPromise, timeoutPromise]));
|
|
284
|
-
return result;
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
console.error("[MCPSandboxClient] runCodeWithTimeout error:", err);
|
|
288
|
-
throw err;
|
|
289
|
-
}
|
|
290
|
-
finally {
|
|
291
|
-
if (timeoutHandle)
|
|
292
|
-
clearTimeout(timeoutHandle);
|
|
293
|
-
console.timeEnd(label);
|
|
294
|
-
}
|
|
295
116
|
}
|
|
296
117
|
generateMCPTestCode(mcpServerConfig, operation, toolName, argumentsObj, envs) {
|
|
297
118
|
const commonCode = `
|
|
298
119
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
299
120
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
300
|
-
import fs from "node:fs";
|
|
301
|
-
|
|
302
|
-
function getPackageJSON(packageName) {
|
|
303
|
-
const packageJSONFilePath = \`/home/node_modules/\${packageName}/package.json\`;
|
|
304
|
-
|
|
305
|
-
if (!fs.existsSync(packageJSONFilePath)) {
|
|
306
|
-
throw new Error(\`Package '\${packageName}' not found in node_modules.\`);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const packageJSONStr = fs.readFileSync(packageJSONFilePath, "utf8");
|
|
310
|
-
const packageJSON = JSON.parse(packageJSONStr);
|
|
311
|
-
return packageJSON;
|
|
312
|
-
}
|
|
313
121
|
|
|
314
122
|
async function runMCP() {
|
|
315
123
|
let client;
|
|
316
124
|
try {
|
|
317
125
|
const packageName = "${mcpServerConfig.packageName}";
|
|
318
|
-
const packageJSON = getPackageJSON(packageName);
|
|
319
|
-
|
|
320
|
-
let binPath;
|
|
321
|
-
if (typeof packageJSON.bin === "string") {
|
|
322
|
-
binPath = packageJSON.bin;
|
|
323
|
-
} else if (typeof packageJSON.bin === "object") {
|
|
324
|
-
binPath = Object.values(packageJSON.bin)[0];
|
|
325
|
-
} else {
|
|
326
|
-
binPath = packageJSON.main;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (!binPath) {
|
|
330
|
-
throw new Error(\`Package \${packageName} does not have a valid bin path in package.json.\`);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const binFilePath = \`/home/node_modules/\${packageName}/\${binPath}\`;
|
|
334
|
-
const binArgs = ${JSON.stringify(mcpServerConfig.binArgs || [])};
|
|
335
126
|
|
|
336
127
|
const transport = new StdioClientTransport({
|
|
337
|
-
command: "
|
|
338
|
-
args: [
|
|
128
|
+
command: "pnpx",
|
|
129
|
+
args: ["--silent", packageName],
|
|
339
130
|
env: {
|
|
340
|
-
...
|
|
131
|
+
...Object.fromEntries(
|
|
341
132
|
Object.entries(process.env).filter(([_, v]) => v !== undefined)
|
|
342
|
-
)
|
|
133
|
+
),
|
|
134
|
+
PNPM_HOME: "/root/.local/share/pnpm",
|
|
135
|
+
PNPM_STORE_PATH: "/pnpm-store",
|
|
343
136
|
${this.generateEnvVariables(mcpServerConfig.env, envs)}
|
|
344
137
|
},
|
|
345
138
|
});
|
|
@@ -359,7 +152,7 @@ async function runMCP() {
|
|
|
359
152
|
await client.connect(transport);
|
|
360
153
|
`;
|
|
361
154
|
if (operation === "listTools") {
|
|
362
|
-
|
|
155
|
+
const toolsCode = `${commonCode}
|
|
363
156
|
const toolsObj = await client.listTools();
|
|
364
157
|
|
|
365
158
|
const result = {
|
|
@@ -367,50 +160,58 @@ async function runMCP() {
|
|
|
367
160
|
tools: toolsObj.tools
|
|
368
161
|
};
|
|
369
162
|
|
|
370
|
-
|
|
371
|
-
if (client) {
|
|
372
|
-
client.close();
|
|
373
|
-
}
|
|
374
|
-
return;
|
|
163
|
+
process.stdout.write(JSON.stringify(result));
|
|
375
164
|
} catch (error) {
|
|
376
165
|
console.error("Error in MCP test:", error);
|
|
166
|
+
process.exitCode = 1;
|
|
167
|
+
process.stdout.write(JSON.stringify({ error: error.message || "Unknown error occurred" }));
|
|
168
|
+
} finally {
|
|
377
169
|
if (client) {
|
|
378
|
-
|
|
170
|
+
try {
|
|
171
|
+
await client.close();
|
|
172
|
+
} catch (closeError) {
|
|
173
|
+
console.error("Error closing MCP client:", closeError);
|
|
174
|
+
}
|
|
379
175
|
}
|
|
380
|
-
throw error;
|
|
381
176
|
}
|
|
382
177
|
}
|
|
383
178
|
|
|
384
179
|
runMCP();
|
|
385
|
-
`;
|
|
180
|
+
`;
|
|
181
|
+
return toolsCode;
|
|
182
|
+
// } else if (operation === "executeTool" && toolName) {
|
|
386
183
|
}
|
|
387
184
|
else {
|
|
388
|
-
|
|
185
|
+
const toolExecuteCode = `${commonCode}
|
|
389
186
|
|
|
390
187
|
const result = await client.callTool({
|
|
391
188
|
name: "${toolName}",
|
|
392
189
|
arguments: ${JSON.stringify(argumentsObj)}
|
|
393
190
|
});
|
|
394
191
|
|
|
395
|
-
|
|
396
|
-
if (client) {
|
|
397
|
-
client.close();
|
|
398
|
-
}
|
|
399
|
-
return;
|
|
192
|
+
process.stdout.write(JSON.stringify(result));
|
|
400
193
|
} catch (error) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
console.log(JSON.stringify({
|
|
194
|
+
console.error("Error in MCP test:", error);
|
|
195
|
+
process.exitCode = 1;
|
|
196
|
+
process.stdout.write(JSON.stringify({
|
|
405
197
|
result: null,
|
|
406
198
|
isError: true,
|
|
407
199
|
errorMessage: error.message
|
|
408
200
|
}));
|
|
201
|
+
} finally {
|
|
202
|
+
if (client) {
|
|
203
|
+
try {
|
|
204
|
+
await client.close();
|
|
205
|
+
} catch (closeError) {
|
|
206
|
+
console.error("Error closing MCP client:", closeError);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
409
209
|
}
|
|
410
210
|
}
|
|
411
211
|
|
|
412
212
|
runMCP();
|
|
413
|
-
`;
|
|
213
|
+
`;
|
|
214
|
+
return toolExecuteCode;
|
|
414
215
|
}
|
|
415
216
|
}
|
|
416
217
|
generateEnvVariables(env, realEnvs) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|