@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.
@@ -1,13 +1,12 @@
1
+ import { getSandboxProvider } from "../helper";
1
2
  import { createErrorResponse, createResponse } from "../utils";
2
3
  import { PackageSO } from "./package-so";
3
- const shouldUseSandbox = () => {
4
- return process.env.USE_MCP_SANDBOX === "true";
5
- };
6
4
  export const packageHandler = {
7
5
  executeTool: async (c) => {
8
6
  const requestBody = await c.req.json();
7
+ const provider = getSandboxProvider();
9
8
  try {
10
- const toolSO = new PackageSO(shouldUseSandbox());
9
+ const toolSO = new PackageSO(provider);
11
10
  const result = await toolSO.executeTool(requestBody);
12
11
  const response = createResponse(result);
13
12
  return c.json(response, 200);
@@ -35,8 +34,9 @@ export const packageHandler = {
35
34
  const errorResponse = createErrorResponse("Missing packageName query parameter", 400);
36
35
  return c.json(errorResponse, 200);
37
36
  }
37
+ const provider = getSandboxProvider();
38
38
  try {
39
- const toolSO = new PackageSO(shouldUseSandbox());
39
+ const toolSO = new PackageSO(provider);
40
40
  const result = await toolSO.getPackageDetail(packageName);
41
41
  const response = createResponse(result);
42
42
  return c.json(response, 200);
@@ -55,8 +55,9 @@ export const packageHandler = {
55
55
  const errorResponse = createErrorResponse("Missing packageName query parameter", 400);
56
56
  return c.json(errorResponse, 200);
57
57
  }
58
+ const provider = getSandboxProvider();
58
59
  try {
59
- const toolSO = new PackageSO(shouldUseSandbox());
60
+ const toolSO = new PackageSO(provider);
60
61
  const result = await toolSO.listTools(packageName);
61
62
  const response = createResponse(result);
62
63
  return c.json(response, 200);
@@ -1,16 +1,16 @@
1
1
  import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
2
  import { MCPSandboxClient } from "../sandbox/mcp-sandbox-client.js";
3
- import type { MCPServerPackageConfig, ToolExecute } from "../types";
3
+ import type { MCPSandboxProvider, MCPServerPackageConfig, ToolExecute } from "../types";
4
4
  export declare class PackageSO {
5
- private useSandbox;
6
- private sandboxClient;
5
+ private sandboxProvider;
7
6
  private static sandboxInstances;
8
7
  private static MAX_SANDBOXES;
9
- private static IDLE_CLOSE_MS;
10
- constructor(useSandbox?: boolean);
11
- static acquireSandbox(key?: string): Promise<MCPSandboxClient>;
12
- static releaseSandbox(key?: string): Promise<void>;
8
+ constructor(provider?: MCPSandboxProvider);
9
+ static acquireSandbox(runtime?: "node" | "python" | "java" | "go", provider?: MCPSandboxProvider): Promise<MCPSandboxClient>;
10
+ static releaseSandbox(runtime?: "node" | "python" | "java" | "go", provider?: MCPSandboxProvider): Promise<void>;
13
11
  static cleanupSandboxInstances(): Promise<void>;
12
+ private static getSandboxKey;
13
+ private isSandboxEnabled;
14
14
  executeTool(request: ToolExecute): Promise<unknown>;
15
15
  private executeToolInSandbox;
16
16
  listTools(packageName: string): Promise<Tool[]>;
@@ -5,66 +5,17 @@ import { MCPSandboxClient } from "../sandbox/mcp-sandbox-client.js";
5
5
  import { getDirname } from "../utils";
6
6
  const __dirname = getDirname(import.meta.url);
7
7
  export class PackageSO {
8
- constructor(useSandbox = false) {
9
- this.useSandbox = false;
10
- this.sandboxClient = null;
11
- this.useSandbox = useSandbox;
12
- if (useSandbox) {
13
- const sandboxKey = "default";
14
- const record = PackageSO.sandboxInstances.get(sandboxKey);
15
- if (record) {
16
- record.refCount++;
17
- record.lastUsedAt = Date.now();
18
- this.sandboxClient = record.client;
19
- // Cancel all idle close timer
20
- record.client.touch();
21
- }
22
- else {
23
- // Create a new instance if none exists (subject to max limit)
24
- this.sandboxClient = new MCPSandboxClient();
25
- const newRecord = {
26
- client: this.sandboxClient,
27
- refCount: 1,
28
- lastUsedAt: Date.now(),
29
- idleCloseMs: PackageSO.IDLE_CLOSE_MS,
30
- };
31
- // Try to insert, evict LRU idle instance if MAX is reached
32
- if (PackageSO.sandboxInstances.size >= PackageSO.MAX_SANDBOXES) {
33
- // Find the oldest idle instance (refCount === 0)
34
- let lruKey = null;
35
- let lruTime = Infinity;
36
- for (const [k, r] of PackageSO.sandboxInstances) {
37
- if (r.refCount === 0 && r.lastUsedAt < lruTime) {
38
- lruKey = k;
39
- lruTime = r.lastUsedAt;
40
- }
41
- }
42
- if (lruKey) {
43
- const evict = PackageSO.sandboxInstances.get(lruKey);
44
- // Immediately close and delete
45
- if (evict) {
46
- evict.client.kill().catch((e) => {
47
- console.error("[PackageSO] Error killing evicted sandbox:", e);
48
- });
49
- PackageSO.sandboxInstances.delete(lruKey);
50
- }
51
- }
52
- else {
53
- // No recyclable instances -> throw error to prevent exceeding system limit
54
- throw new Error("Cannot create new sandbox: max sandboxes reached and none are idle");
55
- }
56
- }
57
- PackageSO.sandboxInstances.set(sandboxKey, newRecord);
58
- }
59
- }
8
+ constructor(provider = "LOCAL") {
9
+ this.sandboxProvider = "LOCAL";
10
+ this.sandboxProvider = provider;
60
11
  }
61
12
  // Acquire / Release explicit APIs (for external or future use)
62
- static async acquireSandbox(key = "default") {
63
- const record = PackageSO.sandboxInstances.get(key);
13
+ static async acquireSandbox(runtime = "python", provider = "DAYTONA") {
14
+ const sandboxKey = PackageSO.getSandboxKey(runtime, provider);
15
+ const record = PackageSO.sandboxInstances.get(sandboxKey);
64
16
  if (record) {
65
17
  record.refCount++;
66
18
  record.lastUsedAt = Date.now();
67
- record.client.touch();
68
19
  return record.client;
69
20
  }
70
21
  // Create new instance (note MAX_SANDBOXES check, consistent with constructor logic)
@@ -91,25 +42,32 @@ export class PackageSO {
91
42
  throw new Error("Cannot create new sandbox: max sandboxes reached and none are idle");
92
43
  }
93
44
  }
94
- const client = new MCPSandboxClient();
45
+ const client = new MCPSandboxClient(runtime, provider);
95
46
  const newRecord = {
96
47
  client,
97
48
  refCount: 1,
98
49
  lastUsedAt: Date.now(),
99
- idleCloseMs: PackageSO.IDLE_CLOSE_MS,
50
+ provider,
100
51
  };
101
- PackageSO.sandboxInstances.set(key, newRecord);
52
+ PackageSO.sandboxInstances.set(sandboxKey, newRecord);
102
53
  return client;
103
54
  }
104
- static async releaseSandbox(key = "default") {
105
- const record = PackageSO.sandboxInstances.get(key);
55
+ static async releaseSandbox(runtime = "python", provider = "DAYTONA") {
56
+ const sandboxKey = PackageSO.getSandboxKey(runtime, provider);
57
+ const record = PackageSO.sandboxInstances.get(sandboxKey);
106
58
  if (!record)
107
59
  return;
108
60
  record.refCount = Math.max(0, record.refCount - 1);
109
61
  record.lastUsedAt = Date.now();
110
62
  if (record.refCount === 0) {
111
- // schedule idle close after IDLE_CLOSE_MS
112
- record.client.scheduleIdleClose(record.idleCloseMs || PackageSO.IDLE_CLOSE_MS);
63
+ try {
64
+ await record.client.kill();
65
+ PackageSO.sandboxInstances.delete(sandboxKey);
66
+ console.log(`[PackageSO] Sandbox ${sandboxKey} closed immediately after use`);
67
+ }
68
+ catch (error) {
69
+ console.error(`[PackageSO] Error closing sandbox ${sandboxKey}:`, error);
70
+ }
113
71
  }
114
72
  }
115
73
  // Cleanup all static sandbox instances safely
@@ -128,9 +86,15 @@ export class PackageSO {
128
86
  }
129
87
  await Promise.all(killers);
130
88
  }
89
+ static getSandboxKey(runtime, provider) {
90
+ return `sandbox-${provider}-${runtime}`;
91
+ }
92
+ isSandboxEnabled() {
93
+ return this.sandboxProvider === "DAYTONA" || this.sandboxProvider === "SANDOCK";
94
+ }
131
95
  async executeTool(request) {
132
96
  const mcpServerConfig = getPackageConfigByKey(request.packageName);
133
- if (this.useSandbox && mcpServerConfig.runtime === "node") {
97
+ if (this.isSandboxEnabled()) {
134
98
  try {
135
99
  const result = await this.executeToolInSandbox(request);
136
100
  return result;
@@ -153,15 +117,13 @@ export class PackageSO {
153
117
  }
154
118
  }
155
119
  async executeToolInSandbox(request) {
156
- if (!this.sandboxClient) {
157
- throw new Error("Sandbox client not initialized");
158
- }
120
+ const mcpServerConfig = getPackageConfigByKey(request.packageName);
121
+ const runtime = mcpServerConfig.runtime || "python"; // Default to python if not specified
122
+ const sandboxClient = await PackageSO.acquireSandbox(runtime, this.sandboxProvider);
159
123
  // Initialize if not already initialized (concurrency protection via MCPSandboxClient.initialize)
160
- await this.sandboxClient.initialize();
161
- // Mark usage
162
- this.sandboxClient.touch();
124
+ await sandboxClient.initialize();
163
125
  try {
164
- const result = await this.sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
126
+ const result = await sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
165
127
  console.log(`Tool ${request.toolKey} executed successfully in sandbox`);
166
128
  return result;
167
129
  }
@@ -169,9 +131,9 @@ export class PackageSO {
169
131
  // If it's a sandbox not found error, try reinitializing and retrying once
170
132
  if (error instanceof Error && error.message.includes("sandbox was not found")) {
171
133
  console.log("[PackageSO] Retrying tool execution after sandbox failure");
172
- await this.sandboxClient.initialize();
134
+ await sandboxClient.initialize();
173
135
  // Retry tool execution
174
- const result = await this.sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
136
+ const result = await sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
175
137
  console.log(`Tool ${request.toolKey} executed successfully in sandbox (retry)`);
176
138
  return result;
177
139
  }
@@ -179,12 +141,12 @@ export class PackageSO {
179
141
  }
180
142
  finally {
181
143
  // Release reference count
182
- await PackageSO.releaseSandbox("default");
144
+ await PackageSO.releaseSandbox(runtime, this.sandboxProvider);
183
145
  }
184
146
  }
185
147
  async listTools(packageName) {
186
148
  const mcpServerConfig = getPackageConfigByKey(packageName);
187
- if (this.useSandbox && mcpServerConfig.runtime === "node") {
149
+ if (this.isSandboxEnabled()) {
188
150
  try {
189
151
  const tools = await this.listToolsInSandbox(packageName);
190
152
  return tools;
@@ -210,14 +172,13 @@ export class PackageSO {
210
172
  }
211
173
  }
212
174
  async listToolsInSandbox(packageName) {
213
- if (!this.sandboxClient) {
214
- throw new Error("Sandbox client not initialized");
215
- }
216
- // Initialize only if sandbox is not initialized
217
- await this.sandboxClient.initialize();
218
- this.sandboxClient.touch();
175
+ const mcpServerConfig = getPackageConfigByKey(packageName);
176
+ const runtime = mcpServerConfig.runtime || "python";
177
+ const sandboxClient = await PackageSO.acquireSandbox(runtime, this.sandboxProvider);
219
178
  try {
220
- const tools = await this.sandboxClient.listTools(packageName);
179
+ // Initialize only if sandbox is not initialized
180
+ await sandboxClient.initialize();
181
+ const tools = await sandboxClient.listTools(packageName);
221
182
  console.log(`Tools list retrieved successfully for package ${packageName} in sandbox`);
222
183
  return tools;
223
184
  }
@@ -225,16 +186,16 @@ export class PackageSO {
225
186
  // If it's a sandbox not found error, try reinitializing and retrying once
226
187
  if (error instanceof Error && error.message.includes("sandbox was not found")) {
227
188
  console.log("[PackageSO] Retrying tools listing after sandbox failure");
228
- await this.sandboxClient.initialize();
189
+ await sandboxClient.initialize();
229
190
  // Retry listing tools
230
- const tools = await this.sandboxClient.listTools(packageName);
191
+ const tools = await sandboxClient.listTools(packageName);
231
192
  console.log(`Tools list retrieved successfully for package ${packageName} in sandbox (retry)`);
232
193
  return tools;
233
194
  }
234
195
  throw error;
235
196
  }
236
197
  finally {
237
- await PackageSO.releaseSandbox("default");
198
+ await PackageSO.releaseSandbox(runtime, this.sandboxProvider);
238
199
  }
239
200
  }
240
201
  async getPackageDetail(packageName) {
@@ -260,4 +221,3 @@ export class PackageSO {
260
221
  }
261
222
  PackageSO.sandboxInstances = new Map();
262
223
  PackageSO.MAX_SANDBOXES = 10;
263
- PackageSO.IDLE_CLOSE_MS = 5 * 60 * 1000;
package/dist/helper.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
2
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
- import type { MCPServerPackageConfig } from "./types";
3
+ import type { MCPSandboxProvider, MCPServerPackageConfig } from "./types";
4
4
  export declare const typedAllPackagesList: Record<string, {
5
5
  path: string;
6
6
  category?: string | undefined;
@@ -10,6 +10,7 @@ export declare const typedAllPackagesList: Record<string, {
10
10
  name?: string | undefined;
11
11
  }> | undefined;
12
12
  }>;
13
+ export declare function getSandboxProvider(): MCPSandboxProvider;
13
14
  export declare function getPackageConfigByKey(packageKey: string): MCPServerPackageConfig;
14
15
  export declare function getPackageJSON(packageName: string): any;
15
16
  export declare function getMcpClient(mcpServerConfig: MCPServerPackageConfig, env?: Record<string, string>): Promise<{
@@ -69,4 +70,5 @@ export declare function extractPackageName(dep: string): string;
69
70
  * @returns Array of Python dependency names
70
71
  */
71
72
  export declare function getPythonDependencies(): string[];
73
+ export declare function extractLastOuterJSON(str: string): string;
72
74
  export {};
package/dist/helper.js CHANGED
@@ -11,6 +11,14 @@ import { getDirname } from "../src/utils";
11
11
  import { MCPServerPackageConfigSchema, PackagesListSchema } from "./schema";
12
12
  const __dirname = getDirname(import.meta.url);
13
13
  export const typedAllPackagesList = PackagesListSchema.parse(allPackagesList);
14
+ export function getSandboxProvider() {
15
+ const provider = (process.env.MCP_SANDBOX_PROVIDER || "LOCAL").toUpperCase();
16
+ if (provider === "LOCAL" || provider === "DAYTONA" || provider === "SANDOCK") {
17
+ return provider;
18
+ }
19
+ console.warn(`[helper] Unsupported MCP_SANDBOX_PROVIDER value '${provider}', falling back to LOCAL mode`);
20
+ return "LOCAL";
21
+ }
14
22
  export function getPackageConfigByKey(packageKey) {
15
23
  const value = typedAllPackagesList[packageKey];
16
24
  if (!value) {
@@ -101,6 +109,7 @@ export function updatePackageJsonDependencies({ packageDeps, enableValidation =
101
109
  const packageJsonFile = "./package.json";
102
110
  const packageJSONStr = fs.readFileSync(packageJsonFile, "utf-8");
103
111
  const newDeps = {
112
+ "@daytonaio/sdk": "0.109.0",
104
113
  "@e2b/code-interpreter": "^2.0.0",
105
114
  "@modelcontextprotocol/sdk": "^1.12.0",
106
115
  "@hono/node-server": "1.15.0",
@@ -276,3 +285,28 @@ export function getPythonDependencies() {
276
285
  const deps = ((_a = data.project) === null || _a === void 0 ? void 0 : _a.dependencies) || [];
277
286
  return deps.map(extractPackageName);
278
287
  }
288
+ export function extractLastOuterJSON(str) {
289
+ let braceCount = 0;
290
+ let end = -1;
291
+ let start = -1;
292
+ for (let i = str.length - 1; i >= 0; i--) {
293
+ const ch = str[i];
294
+ if (ch === "}") {
295
+ if (end === -1)
296
+ end = i;
297
+ braceCount++;
298
+ }
299
+ else if (ch === "{") {
300
+ braceCount--;
301
+ if (braceCount === 0 && end !== -1) {
302
+ start = i;
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ if (start === -1 || end === -1) {
308
+ throw new Error("No valid JSON found in string");
309
+ }
310
+ const jsonStr = str.slice(start, end + 1);
311
+ return jsonStr;
312
+ }
@@ -1,37 +1,16 @@
1
1
  import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { MCPSandboxProvider } from "../types";
2
3
  export declare class MCPSandboxClient {
3
4
  private sandbox;
4
5
  private initializing;
5
6
  private readonly apiKey;
6
- private toolCache;
7
- private readonly E2B_SANDBOX_TIMEOUT_MS;
8
- private readonly TOOL_CACHE_TTL;
9
- TOOL_EXECUTION_TIMEOUT: number;
10
- private lastTouchTime;
11
- private readonly THROTTLE_DELAY_MS;
12
- createdAt: number | null;
13
- lastUsedAt: number | null;
14
- private ttlTimer;
15
- private autoCloseOnIdleTimer;
16
- private idleCloseMs;
17
- constructor(apiKey?: string);
7
+ private readonly provider;
8
+ private runtime;
9
+ constructor(runtime?: "node" | "python" | "java" | "go", provider?: MCPSandboxProvider);
18
10
  initialize(): Promise<void>;
19
- private setupTTLTimer;
20
- /**
21
- * Update sandbox last used time
22
- */
23
- touch(): void;
24
- /**
25
- * Actually perform the touch operation
26
- */
27
- private performTouch;
28
- scheduleIdleClose(idleMs: number): void;
29
11
  kill(): Promise<void>;
30
- clearPackageCache(packageKey: string): void;
31
- clearAllCache(): void;
32
12
  listTools(packageKey: string): Promise<Tool[]>;
33
13
  executeTool(packageKey: string, toolName: string, argumentsObj: Record<string, unknown>, envs?: Record<string, string>): Promise<unknown>;
34
- private runCodeWithTimeout;
35
14
  private generateMCPTestCode;
36
15
  private generateEnvVariables;
37
16
  }