@toolsdk.ai/registry 1.0.113 → 1.0.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +66 -11
  2. package/dist/api/index.d.ts +1 -1
  3. package/dist/api/index.js +23 -25
  4. package/dist/domains/config/config-route.d.ts +2 -0
  5. package/dist/domains/config/config-route.js +31 -0
  6. package/dist/domains/config/config-schema.d.ts +57 -0
  7. package/dist/domains/config/config-schema.js +10 -0
  8. package/dist/domains/config/config-types.d.ts +3 -0
  9. package/dist/domains/executor/executor-factory.d.ts +9 -0
  10. package/dist/domains/executor/executor-factory.js +17 -0
  11. package/dist/domains/executor/executor-types.d.ts +15 -0
  12. package/dist/domains/executor/local-executor.d.ts +12 -0
  13. package/dist/domains/executor/local-executor.js +48 -0
  14. package/dist/domains/executor/sandbox-executor.d.ts +16 -0
  15. package/dist/domains/executor/sandbox-executor.js +83 -0
  16. package/dist/domains/package/package-handler.d.ts +17 -0
  17. package/dist/domains/package/package-handler.js +58 -0
  18. package/dist/domains/package/package-repository.d.ts +9 -0
  19. package/dist/domains/package/package-repository.js +26 -0
  20. package/dist/domains/package/package-route.d.ts +2 -0
  21. package/dist/{api → domains/package}/package-route.js +38 -52
  22. package/dist/domains/package/package-schema.d.ts +244 -0
  23. package/dist/domains/package/package-schema.js +52 -0
  24. package/dist/domains/package/package-so.d.ts +78 -0
  25. package/dist/domains/package/package-so.js +61 -0
  26. package/dist/domains/package/package-so.test.js +378 -0
  27. package/dist/domains/package/package-types.d.ts +9 -0
  28. package/dist/domains/package/package-types.js +1 -0
  29. package/dist/domains/sandbox/clients/daytona-client.d.ts +17 -0
  30. package/dist/domains/sandbox/clients/daytona-client.js +112 -0
  31. package/dist/domains/sandbox/clients/sandock-client.d.ts +19 -0
  32. package/dist/domains/sandbox/clients/sandock-client.js +178 -0
  33. package/dist/domains/sandbox/sandbox-factory.d.ts +8 -0
  34. package/dist/domains/sandbox/sandbox-factory.js +23 -0
  35. package/dist/domains/sandbox/sandbox-pool-so.d.ts +25 -0
  36. package/dist/domains/sandbox/sandbox-pool-so.js +123 -0
  37. package/dist/domains/sandbox/sandbox-types.d.ts +25 -0
  38. package/dist/domains/sandbox/sandbox-types.js +1 -0
  39. package/dist/domains/sandbox/sandbox-utils.d.ts +3 -0
  40. package/dist/domains/sandbox/sandbox-utils.js +109 -0
  41. package/dist/domains/search/search-handler.d.ts +47 -0
  42. package/dist/domains/search/search-handler.js +113 -0
  43. package/dist/domains/search/search-route.d.ts +2 -0
  44. package/dist/domains/search/search-route.js +101 -0
  45. package/dist/domains/search/search-schema.d.ts +384 -0
  46. package/dist/domains/search/search-schema.js +99 -0
  47. package/dist/domains/search/search-so.d.ts +55 -0
  48. package/dist/{search/search-service.js → domains/search/search-so.js} +200 -297
  49. package/dist/shared/config/environment.d.ts +16 -0
  50. package/dist/shared/config/environment.js +41 -0
  51. package/dist/shared/schemas/common-schema.d.ts +249 -0
  52. package/dist/{schema.js → shared/schemas/common-schema.js} +37 -80
  53. package/dist/shared/schemas/index.d.ts +1 -0
  54. package/dist/shared/schemas/index.js +1 -0
  55. package/dist/shared/scripts-helpers/index.d.ts +60 -0
  56. package/dist/shared/scripts-helpers/index.js +61 -0
  57. package/dist/shared/utils/file-util.d.ts +1 -0
  58. package/dist/shared/utils/file-util.js +5 -0
  59. package/dist/shared/utils/index.d.ts +5 -0
  60. package/dist/shared/utils/index.js +5 -0
  61. package/dist/shared/utils/mcp-client-util.d.ts +31 -0
  62. package/dist/shared/utils/mcp-client-util.js +79 -0
  63. package/dist/shared/utils/package-util.d.ts +6 -0
  64. package/dist/shared/utils/package-util.js +53 -0
  65. package/dist/shared/utils/promise-util.d.ts +1 -0
  66. package/dist/shared/utils/promise-util.js +14 -0
  67. package/dist/{utils.d.ts → shared/utils/response-util.d.ts} +6 -2
  68. package/dist/{utils.js → shared/utils/response-util.js} +1 -6
  69. package/dist/shared/utils/string-util.d.ts +1 -0
  70. package/dist/shared/utils/string-util.js +25 -0
  71. package/dist/shared/utils/validation-util.d.ts +12 -0
  72. package/dist/shared/utils/validation-util.js +99 -0
  73. package/indexes/categories-list.json +1 -0
  74. package/indexes/packages-list.json +6 -0
  75. package/package.json +9 -2
  76. package/packages/developer-tools/neurolink.json +23 -0
  77. package/packages/search-data-extraction/ref-tools-mcp.json +7 -2
  78. package/README.dev.md +0 -195
  79. package/dist/api/package-handler.d.ts +0 -18
  80. package/dist/api/package-handler.js +0 -72
  81. package/dist/api/package-route.d.ts +0 -2
  82. package/dist/api/package-so.d.ts +0 -19
  83. package/dist/api/package-so.js +0 -263
  84. package/dist/api/package.test.js +0 -19
  85. package/dist/helper.d.ts +0 -72
  86. package/dist/helper.js +0 -278
  87. package/dist/sandbox/mcp-sandbox-client.d.ts +0 -37
  88. package/dist/sandbox/mcp-sandbox-client.js +0 -428
  89. package/dist/schema.d.ts +0 -806
  90. package/dist/search/search-route.d.ts +0 -3
  91. package/dist/search/search-route.js +0 -305
  92. package/dist/search/search-service.d.ts +0 -120
  93. package/dist/search/search.test.js +0 -100
  94. package/dist/types.d.ts +0 -27
  95. /package/dist/{api/package.test.d.ts → domains/config/config-types.js} +0 -0
  96. /package/dist/{search/search.test.d.ts → domains/executor/executor-types.js} +0 -0
  97. /package/dist/{types.js → domains/package/package-so.test.d.ts} +0 -0
@@ -0,0 +1,378 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { PackageSO } from "./package-so";
3
+ describe("PackageSO", () => {
4
+ let mockRepository;
5
+ let mockExecutor;
6
+ beforeEach(() => {
7
+ // Mock PackageRepository
8
+ mockRepository = {
9
+ getPackageConfig: vi.fn(),
10
+ getAllPackages: vi.fn(),
11
+ exists: vi.fn(),
12
+ };
13
+ // Mock ToolExecutor
14
+ mockExecutor = {
15
+ listTools: vi.fn(),
16
+ executeTool: vi.fn(),
17
+ };
18
+ });
19
+ describe("init", () => {
20
+ it("should successfully initialize PackageSO instance", async () => {
21
+ // Arrange
22
+ const packageName = "@modelcontextprotocol/server-filesystem";
23
+ const mockConfig = {
24
+ type: "mcp-server",
25
+ runtime: "node",
26
+ packageName,
27
+ name: "Filesystem Server",
28
+ description: "A server for filesystem operations",
29
+ };
30
+ const mockPackageInfo = {
31
+ path: "path/to/package",
32
+ category: "filesystem",
33
+ validated: true,
34
+ };
35
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
36
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({
37
+ [packageName]: mockPackageInfo,
38
+ });
39
+ // Act
40
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
41
+ // Assert
42
+ expect(packageSO.packageName).toBe(packageName);
43
+ expect(packageSO.name).toBe("Filesystem Server");
44
+ expect(packageSO.description).toBe("A server for filesystem operations");
45
+ expect(packageSO.category).toBe("filesystem");
46
+ expect(packageSO.validated).toBe(true);
47
+ expect(mockRepository.getPackageConfig).toHaveBeenCalledWith(packageName);
48
+ expect(mockRepository.getAllPackages).toHaveBeenCalled();
49
+ });
50
+ it("should handle case when package config exists but packageInfo does not", async () => {
51
+ // Arrange
52
+ const packageName = "@test/new-package";
53
+ const mockConfig = {
54
+ type: "mcp-server",
55
+ runtime: "node",
56
+ packageName,
57
+ name: "New Package",
58
+ description: "A new package",
59
+ };
60
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
61
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
62
+ // Act
63
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
64
+ // Assert
65
+ expect(packageSO.packageName).toBe(packageName);
66
+ expect(packageSO.name).toBe("New Package");
67
+ expect(packageSO.category).toBeUndefined();
68
+ expect(packageSO.validated).toBeUndefined();
69
+ });
70
+ it("should handle null description", async () => {
71
+ // Arrange
72
+ const packageName = "@test/package";
73
+ const mockConfig = {
74
+ type: "mcp-server",
75
+ runtime: "node",
76
+ packageName,
77
+ name: "Test Package",
78
+ description: null,
79
+ };
80
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
81
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
82
+ // Act
83
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
84
+ // Assert
85
+ expect(packageSO.description).toBeNull();
86
+ });
87
+ });
88
+ describe("getTools", () => {
89
+ it("should successfully return tools list", async () => {
90
+ // Arrange
91
+ const packageName = "@test/package";
92
+ const mockConfig = {
93
+ type: "mcp-server",
94
+ runtime: "node",
95
+ packageName,
96
+ name: "Test Package",
97
+ description: "Test description",
98
+ };
99
+ const mockTools = [
100
+ {
101
+ name: "read_file",
102
+ description: "Read a file",
103
+ inputSchema: {
104
+ type: "object",
105
+ properties: {
106
+ path: { type: "string" },
107
+ },
108
+ },
109
+ },
110
+ {
111
+ name: "write_file",
112
+ description: "Write a file",
113
+ inputSchema: {
114
+ type: "object",
115
+ properties: {
116
+ path: { type: "string" },
117
+ content: { type: "string" },
118
+ },
119
+ },
120
+ },
121
+ ];
122
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
123
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
124
+ vi.spyOn(mockExecutor, "listTools").mockResolvedValue(mockTools);
125
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
126
+ // Act
127
+ const tools = await packageSO.getTools();
128
+ // Assert
129
+ expect(tools).toEqual(mockTools);
130
+ expect(tools).toHaveLength(2);
131
+ expect(mockExecutor.listTools).toHaveBeenCalledWith(packageName);
132
+ expect(mockExecutor.listTools).toHaveBeenCalledTimes(1);
133
+ });
134
+ it("should throw error when executor fails", async () => {
135
+ // Arrange
136
+ const packageName = "@test/package";
137
+ const mockConfig = {
138
+ type: "mcp-server",
139
+ runtime: "node",
140
+ packageName,
141
+ name: "Test Package",
142
+ description: "Test description",
143
+ };
144
+ const errorMessage = "Failed to list tools";
145
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
146
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
147
+ vi.spyOn(mockExecutor, "listTools").mockRejectedValue(new Error(errorMessage));
148
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
149
+ // Act & Assert
150
+ await expect(packageSO.getTools()).rejects.toThrow(errorMessage);
151
+ });
152
+ });
153
+ describe("executeTool", () => {
154
+ it("should successfully execute tool", async () => {
155
+ // Arrange
156
+ const packageName = "@test/package";
157
+ const toolKey = "read_file";
158
+ const inputData = { path: "/tmp/test.txt" };
159
+ const envs = { ENV_VAR: "test_value" };
160
+ const mockResult = { content: "file content", success: true };
161
+ const mockConfig = {
162
+ type: "mcp-server",
163
+ runtime: "node",
164
+ packageName,
165
+ name: "Test Package",
166
+ description: "Test description",
167
+ };
168
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
169
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
170
+ vi.spyOn(mockExecutor, "executeTool").mockResolvedValue(mockResult);
171
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
172
+ // Act
173
+ const result = await packageSO.executeTool(toolKey, inputData, envs);
174
+ // Assert
175
+ expect(result).toEqual(mockResult);
176
+ expect(mockExecutor.executeTool).toHaveBeenCalledWith({
177
+ packageName,
178
+ toolKey,
179
+ inputData,
180
+ envs,
181
+ });
182
+ expect(mockExecutor.executeTool).toHaveBeenCalledTimes(1);
183
+ });
184
+ it("should execute normally without envs parameter", async () => {
185
+ // Arrange
186
+ const packageName = "@test/package";
187
+ const toolKey = "read_file";
188
+ const inputData = { path: "/tmp/test.txt" };
189
+ const mockResult = { content: "file content" };
190
+ const mockConfig = {
191
+ type: "mcp-server",
192
+ runtime: "node",
193
+ packageName,
194
+ name: "Test Package",
195
+ description: "Test description",
196
+ };
197
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
198
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
199
+ vi.spyOn(mockExecutor, "executeTool").mockResolvedValue(mockResult);
200
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
201
+ // Act
202
+ const result = await packageSO.executeTool(toolKey, inputData);
203
+ // Assert
204
+ expect(result).toEqual(mockResult);
205
+ expect(mockExecutor.executeTool).toHaveBeenCalledWith({
206
+ packageName,
207
+ toolKey,
208
+ inputData,
209
+ envs: undefined,
210
+ });
211
+ });
212
+ it("should throw error when tool execution fails", async () => {
213
+ // Arrange
214
+ const packageName = "@test/package";
215
+ const toolKey = "unknown_tool";
216
+ const inputData = { param: "value" };
217
+ const errorMessage = "Unknown tool: unknown_tool";
218
+ const mockConfig = {
219
+ type: "mcp-server",
220
+ runtime: "node",
221
+ packageName,
222
+ name: "Test Package",
223
+ description: "Test description",
224
+ };
225
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
226
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
227
+ vi.spyOn(mockExecutor, "executeTool").mockRejectedValue(new Error(errorMessage));
228
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
229
+ // Act & Assert
230
+ await expect(packageSO.executeTool(toolKey, inputData)).rejects.toThrow(errorMessage);
231
+ });
232
+ });
233
+ describe("getDetailWithTools", () => {
234
+ it("should return complete package details with tools list", async () => {
235
+ // Arrange
236
+ const packageName = "@test/package";
237
+ const mockConfig = {
238
+ type: "mcp-server",
239
+ runtime: "node",
240
+ packageName,
241
+ name: "Test Package",
242
+ description: "A test package for demonstration",
243
+ };
244
+ const mockPackageInfo = {
245
+ path: "path/to/package",
246
+ category: "testing",
247
+ validated: true,
248
+ };
249
+ const mockTools = [
250
+ {
251
+ name: "test_tool",
252
+ description: "A test tool",
253
+ inputSchema: {
254
+ type: "object",
255
+ properties: {},
256
+ },
257
+ },
258
+ ];
259
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
260
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({
261
+ [packageName]: mockPackageInfo,
262
+ });
263
+ vi.spyOn(mockExecutor, "listTools").mockResolvedValue(mockTools);
264
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
265
+ // Act
266
+ const detail = await packageSO.getDetailWithTools();
267
+ // Assert
268
+ expect(detail).toEqual({
269
+ name: "Test Package",
270
+ packageName: "@test/package",
271
+ description: "A test package for demonstration",
272
+ category: "testing",
273
+ validated: true,
274
+ tools: mockTools,
275
+ });
276
+ });
277
+ it("should return undefined tools when getting tools fails", async () => {
278
+ // Arrange
279
+ const packageName = "@test/package";
280
+ const mockConfig = {
281
+ type: "mcp-server",
282
+ runtime: "node",
283
+ packageName,
284
+ name: "Test Package",
285
+ description: "Test description",
286
+ };
287
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
288
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
289
+ vi.spyOn(mockExecutor, "listTools").mockRejectedValue(new Error("Failed to get tools"));
290
+ const consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
291
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
292
+ // Act
293
+ const detail = await packageSO.getDetailWithTools();
294
+ // Assert
295
+ expect(detail.tools).toBeUndefined();
296
+ expect(detail.name).toBe("Test Package");
297
+ expect(detail.packageName).toBe(packageName);
298
+ expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining(`[PackageSO] Failed to get tools for ${packageName}`), expect.any(Error));
299
+ consoleWarnSpy.mockRestore();
300
+ });
301
+ it("should correctly handle packages without category and validated", async () => {
302
+ // Arrange
303
+ const packageName = "@test/minimal-package";
304
+ const mockConfig = {
305
+ type: "mcp-server",
306
+ runtime: "node",
307
+ packageName,
308
+ name: "Minimal Package",
309
+ description: "A minimal package",
310
+ };
311
+ const mockTools = [];
312
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
313
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
314
+ vi.spyOn(mockExecutor, "listTools").mockResolvedValue(mockTools);
315
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
316
+ // Act
317
+ const detail = await packageSO.getDetailWithTools();
318
+ // Assert
319
+ expect(detail).toEqual({
320
+ name: "Minimal Package",
321
+ packageName: "@test/minimal-package",
322
+ description: "A minimal package",
323
+ category: undefined,
324
+ validated: undefined,
325
+ tools: mockTools,
326
+ });
327
+ });
328
+ });
329
+ describe("Getters", () => {
330
+ it("should correctly access all properties through getters", async () => {
331
+ // Arrange
332
+ const packageName = "@test/package";
333
+ const mockConfig = {
334
+ type: "mcp-server",
335
+ runtime: "node",
336
+ packageName,
337
+ name: "Test Package",
338
+ description: "Test description",
339
+ };
340
+ const mockPackageInfo = {
341
+ path: "path/to/package",
342
+ category: "test-category",
343
+ validated: false,
344
+ };
345
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
346
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({
347
+ [packageName]: mockPackageInfo,
348
+ });
349
+ // Act
350
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
351
+ // Assert
352
+ expect(packageSO.packageName).toBe(packageName);
353
+ expect(packageSO.name).toBe("Test Package");
354
+ expect(packageSO.description).toBe("Test description");
355
+ expect(packageSO.category).toBe("test-category");
356
+ expect(packageSO.validated).toBe(false);
357
+ expect(packageSO.config).toEqual(mockConfig);
358
+ });
359
+ it("should return complete config object through config getter", async () => {
360
+ // Arrange
361
+ const packageName = "@test/package";
362
+ const mockConfig = {
363
+ type: "mcp-server",
364
+ runtime: "node",
365
+ packageName,
366
+ name: "Test Package",
367
+ description: "Test description",
368
+ };
369
+ vi.spyOn(mockRepository, "getPackageConfig").mockReturnValue(mockConfig);
370
+ vi.spyOn(mockRepository, "getAllPackages").mockReturnValue({});
371
+ // Act
372
+ const packageSO = await PackageSO.init(packageName, mockRepository, mockExecutor);
373
+ // Assert
374
+ expect(packageSO.config).toBe(mockConfig);
375
+ expect(packageSO.config).toEqual(mockConfig);
376
+ });
377
+ });
378
+ });
@@ -0,0 +1,9 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { z } from "zod";
3
+ import type { MCPServerPackageConfigSchema, PackageConfigSchema, PackagesListSchema } from "../../shared/schemas";
4
+ export type MCPServerPackageConfig = z.infer<typeof MCPServerPackageConfigSchema>;
5
+ export type PackageConfig = z.infer<typeof PackageConfigSchema>;
6
+ export type PackagesList = z.infer<typeof PackagesListSchema>;
7
+ export interface MCPServerPackageConfigWithTools extends MCPServerPackageConfig {
8
+ tools?: Tool[];
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { SandboxClient } from "../sandbox-types";
3
+ /**
4
+ * Daytona Sandbox Client
5
+ * Implements SandboxClient interface for Daytona provider
6
+ */
7
+ export declare class DaytonaSandboxClient implements SandboxClient {
8
+ private sandbox;
9
+ private initializing;
10
+ private readonly packageRepository;
11
+ constructor(_runtime?: "node" | "python" | "java" | "go");
12
+ initialize(): Promise<void>;
13
+ private executeCode;
14
+ listTools(packageKey: string): Promise<Tool[]>;
15
+ executeTool(packageKey: string, toolName: string, argumentsObj: Record<string, unknown>, envs?: Record<string, string>): Promise<unknown>;
16
+ destroy(): Promise<void>;
17
+ }
@@ -0,0 +1,112 @@
1
+ import path from "node:path";
2
+ import { Daytona, Image } from "@daytonaio/sdk";
3
+ import { getDaytonaConfig } from "../../../shared/config/environment";
4
+ import { getDirname } from "../../../shared/utils/file-util";
5
+ import { extractLastOuterJSON } from "../../../shared/utils/string-util";
6
+ import { PackageRepository } from "../../package/package-repository";
7
+ import { generateMCPTestCode } from "../sandbox-utils";
8
+ /**
9
+ * Daytona Sandbox Client
10
+ * Implements SandboxClient interface for Daytona provider
11
+ */
12
+ export class DaytonaSandboxClient {
13
+ constructor(_runtime = "node") {
14
+ this.sandbox = null;
15
+ this.initializing = null;
16
+ const __dirname = getDirname(import.meta.url);
17
+ const packagesDir = path.join(__dirname, "../../../../packages");
18
+ this.packageRepository = new PackageRepository(packagesDir);
19
+ }
20
+ async initialize() {
21
+ if (this.sandbox) {
22
+ return;
23
+ }
24
+ if (this.initializing) {
25
+ await this.initializing;
26
+ return;
27
+ }
28
+ this.initializing = (async () => {
29
+ try {
30
+ const config = getDaytonaConfig();
31
+ const daytonaConfig = {
32
+ apiKey: config.apiKey,
33
+ };
34
+ if (config.apiUrl) {
35
+ daytonaConfig.apiUrl = config.apiUrl;
36
+ }
37
+ const daytona = new Daytona(daytonaConfig);
38
+ const declarativeImage = Image.base("node:20")
39
+ .runCommands("npm install -g pnpm", "mkdir -p /workspace", "cd /workspace && npm init -y", "cd /workspace && pnpm add @modelcontextprotocol/sdk")
40
+ .workdir("/workspace");
41
+ this.sandbox = await daytona.create({
42
+ language: "javascript",
43
+ image: declarativeImage,
44
+ autoDeleteInterval: 0,
45
+ });
46
+ console.log("[DaytonaSandboxClient] Sandbox created successfully");
47
+ }
48
+ finally {
49
+ this.initializing = null;
50
+ }
51
+ })();
52
+ await this.initializing;
53
+ }
54
+ async executeCode(code) {
55
+ if (!this.sandbox) {
56
+ throw new Error("Sandbox not initialized. Call initialize() first.");
57
+ }
58
+ const response = await this.sandbox.process.codeRun(code);
59
+ return {
60
+ exitCode: response.exitCode,
61
+ result: response.result,
62
+ };
63
+ }
64
+ async listTools(packageKey) {
65
+ const mcpServerConfig = this.packageRepository.getPackageConfig(packageKey);
66
+ const testCode = generateMCPTestCode(mcpServerConfig, "listTools");
67
+ const response = await this.executeCode(testCode);
68
+ if (response.exitCode !== 0) {
69
+ throw new Error(`Failed to list tools: ${response.result}`);
70
+ }
71
+ const parsedResultStr = extractLastOuterJSON(response.result);
72
+ const result = JSON.parse(parsedResultStr);
73
+ return result.tools;
74
+ }
75
+ async executeTool(packageKey, toolName, argumentsObj, envs) {
76
+ const mcpServerConfig = this.packageRepository.getPackageConfig(packageKey);
77
+ const testCode = generateMCPTestCode(mcpServerConfig, "executeTool", toolName, argumentsObj, envs);
78
+ const response = await this.executeCode(testCode);
79
+ if (response.exitCode !== 0) {
80
+ throw new Error(`Failed to execute tool: ${response.result}`);
81
+ }
82
+ const parsedResultStr = extractLastOuterJSON(response.result);
83
+ const result = JSON.parse(parsedResultStr);
84
+ if (result.isError) {
85
+ console.error("[DaytonaSandboxClient] Tool execution error:", result.errorMessage);
86
+ throw new Error(result.errorMessage);
87
+ }
88
+ return result;
89
+ }
90
+ async destroy() {
91
+ if (!this.sandbox) {
92
+ return;
93
+ }
94
+ const sandboxToDelete = this.sandbox;
95
+ this.sandbox = null; // Clear immediately to avoid duplicate calls
96
+ // Asynchronously clean up sandbox without blocking result return
97
+ sandboxToDelete
98
+ .delete()
99
+ .then(() => {
100
+ console.log("[DaytonaSandboxClient] Sandbox destroyed successfully");
101
+ })
102
+ .catch((err) => {
103
+ const errorMessage = err.message;
104
+ if (errorMessage.includes("not found")) {
105
+ console.log("[DaytonaSandboxClient] Sandbox already destroyed (not found on platform)");
106
+ }
107
+ else {
108
+ console.warn("[DaytonaSandboxClient] Warning: Could not destroy sandbox:", errorMessage);
109
+ }
110
+ });
111
+ }
112
+ }
@@ -0,0 +1,19 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { SandboxClient } from "../sandbox-types";
3
+ /**
4
+ * Sandock Sandbox Client
5
+ * Implements SandboxClient interface for Sandock provider
6
+ */
7
+ export declare class SandockSandboxClient implements SandboxClient {
8
+ private sandboxId;
9
+ private initializing;
10
+ private readonly packageRepository;
11
+ private readonly client;
12
+ constructor(_runtime?: "node" | "python" | "java" | "go");
13
+ initialize(): Promise<void>;
14
+ private executeShellCommand;
15
+ private executeCode;
16
+ listTools(packageKey: string): Promise<Tool[]>;
17
+ executeTool(packageKey: string, toolName: string, argumentsObj: Record<string, unknown>, envs?: Record<string, string>): Promise<unknown>;
18
+ destroy(): Promise<void>;
19
+ }