@toolsdk.ai/registry 1.0.114 → 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/sandbox/clients/daytona-client.d.ts +17 -0
  29. package/dist/domains/sandbox/clients/daytona-client.js +112 -0
  30. package/dist/domains/sandbox/clients/sandock-client.d.ts +19 -0
  31. package/dist/domains/sandbox/clients/sandock-client.js +178 -0
  32. package/dist/domains/sandbox/sandbox-factory.d.ts +8 -0
  33. package/dist/domains/sandbox/sandbox-factory.js +23 -0
  34. package/dist/domains/sandbox/sandbox-pool-so.d.ts +25 -0
  35. package/dist/domains/sandbox/sandbox-pool-so.js +123 -0
  36. package/dist/domains/sandbox/sandbox-types.d.ts +25 -0
  37. package/dist/domains/sandbox/sandbox-types.js +1 -0
  38. package/dist/domains/sandbox/sandbox-utils.d.ts +3 -0
  39. package/dist/domains/sandbox/sandbox-utils.js +109 -0
  40. package/dist/domains/search/search-handler.d.ts +47 -0
  41. package/dist/domains/search/search-handler.js +113 -0
  42. package/dist/domains/search/search-route.d.ts +2 -0
  43. package/dist/domains/search/search-route.js +101 -0
  44. package/dist/domains/search/search-schema.d.ts +384 -0
  45. package/dist/domains/search/search-schema.js +99 -0
  46. package/dist/domains/search/search-so.d.ts +55 -0
  47. package/dist/{search/search-service.js → domains/search/search-so.js} +200 -297
  48. package/dist/shared/config/environment.d.ts +16 -0
  49. package/dist/shared/config/environment.js +41 -0
  50. package/dist/shared/schemas/common-schema.d.ts +249 -0
  51. package/dist/{schema.js → shared/schemas/common-schema.js} +37 -80
  52. package/dist/shared/schemas/index.d.ts +1 -0
  53. package/dist/shared/schemas/index.js +1 -0
  54. package/dist/shared/scripts-helpers/index.d.ts +60 -0
  55. package/dist/shared/scripts-helpers/index.js +61 -0
  56. package/dist/shared/utils/file-util.d.ts +1 -0
  57. package/dist/shared/utils/file-util.js +5 -0
  58. package/dist/shared/utils/index.d.ts +5 -0
  59. package/dist/shared/utils/index.js +5 -0
  60. package/dist/shared/utils/mcp-client-util.d.ts +31 -0
  61. package/dist/shared/utils/mcp-client-util.js +79 -0
  62. package/dist/shared/utils/package-util.d.ts +6 -0
  63. package/dist/shared/utils/package-util.js +53 -0
  64. package/dist/shared/utils/promise-util.d.ts +1 -0
  65. package/dist/shared/utils/promise-util.js +14 -0
  66. package/dist/{utils.d.ts → shared/utils/response-util.d.ts} +6 -2
  67. package/dist/{utils.js → shared/utils/response-util.js} +1 -6
  68. package/dist/shared/utils/string-util.d.ts +1 -0
  69. package/dist/shared/utils/string-util.js +25 -0
  70. package/dist/shared/utils/validation-util.d.ts +12 -0
  71. package/dist/shared/utils/validation-util.js +99 -0
  72. package/indexes/categories-list.json +1 -0
  73. package/indexes/packages-list.json +6 -0
  74. package/package.json +8 -2
  75. package/packages/developer-tools/neurolink.json +23 -0
  76. package/README.dev.md +0 -195
  77. package/dist/api/package-handler.d.ts +0 -18
  78. package/dist/api/package-handler.js +0 -73
  79. package/dist/api/package-route.d.ts +0 -2
  80. package/dist/api/package-so.d.ts +0 -19
  81. package/dist/api/package-so.js +0 -223
  82. package/dist/api/package.test.js +0 -19
  83. package/dist/helper.d.ts +0 -74
  84. package/dist/helper.js +0 -312
  85. package/dist/sandbox/mcp-sandbox-client.d.ts +0 -16
  86. package/dist/sandbox/mcp-sandbox-client.js +0 -229
  87. package/dist/sandbox/mcp-sandbox-client.test.js +0 -491
  88. package/dist/schema.d.ts +0 -806
  89. package/dist/search/search-route.d.ts +0 -3
  90. package/dist/search/search-route.js +0 -305
  91. package/dist/search/search-service.d.ts +0 -120
  92. package/dist/search/search.test.js +0 -100
  93. package/dist/types.d.ts +0 -28
  94. /package/dist/{api/package.test.d.ts → domains/config/config-types.js} +0 -0
  95. /package/dist/{sandbox/mcp-sandbox-client.test.d.ts → domains/executor/executor-types.js} +0 -0
  96. /package/dist/{search/search.test.d.ts → domains/package/package-so.test.d.ts} +0 -0
  97. /package/dist/{types.js → domains/package/package-types.js} +0 -0
package/README.md CHANGED
@@ -6,10 +6,10 @@
6
6
 
7
7
  [![Product Hunt](https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=997428&theme=light&period=daily)](https://www.producthunt.com/products/toolsdk-ai)
8
8
 
9
- ![How many MCP Servers in Awesome MCP Registry](https://img.shields.io/badge/MCP_Servers-4107-blue)
9
+ ![How many MCP Servers in Awesome MCP Registry](https://img.shields.io/badge/MCP_Servers-4108-blue)
10
10
  ![awesome-mcp-registry License](https://img.shields.io/badge/LICENSE-MIT-ff69b4)
11
11
 
12
- An open, high-quality, well-structured and developer-friendly list of 4107+ MCP servers.
12
+ An open, high-quality, well-structured and developer-friendly list of 4108+ MCP servers.
13
13
 
14
14
  ---
15
15
 
@@ -21,7 +21,7 @@ You can use it to:
21
21
 
22
22
  - ⚡ Build and host your own MCP projects with ease
23
23
  - 🔒 Deploy a fully **private registry** for your team or organization
24
- - 🛠️ Maintain complete control of your MCP tools in a secure environment
24
+ - 🚀 **Execute MCP tools remotely** in a secure sandbox environment
25
25
 
26
26
  This registry leverages structured JSON configs to generate:
27
27
 
@@ -31,10 +31,17 @@ This registry leverages structured JSON configs to generate:
31
31
 
32
32
  ---
33
33
 
34
- - [Video: How to submit a MCP server in JSON file?](https://www.youtube.com/watch?v=J_oaDtCoVVo)
35
- - [Quick Start](#quick-start)
36
- - [Contributing Guide](./docs/guide.md)
37
- - [Awesome MCP Servers](#mcp-servers)
34
+ ## 📚 Table of Contents
35
+
36
+ - [🎥 Video: How to submit a MCP server in JSON file?](https://www.youtube.com/watch?v=J_oaDtCoVVo)
37
+ - [🚀 Quick Start](#quick-start)
38
+ - [🐳 Docker Self-Hosting](#-docker-self-hosting)
39
+ - [📦 Install via Package Manager](#install-via-package-manager)
40
+ - [📄 Submit New MCP Servers](#submit-new-mcp-servers)
41
+ - [📖 Development Guide](./docs/DEVELOPMENT.md)
42
+ - [🤝 Contributing Guide](./docs/guide.md)
43
+ - [⭐ Awesome MCP Servers](#mcp-servers)
44
+
38
45
  - [Uncategorized](#uncategorized)
39
46
  - [Aggregators](#aggregators)
40
47
  - [Art & Culture](#art-and-culture)
@@ -71,19 +78,62 @@ This registry leverages structured JSON configs to generate:
71
78
 
72
79
  ## 🚀 Quick Start
73
80
 
74
- #### Install via package manager:
81
+ ### 🐳 Docker Self-Hosting
82
+
83
+ Deploy your **private MCP Registry** in 5 minutes with Docker! Take full control of your MCP servers with search functionality and secure sandbox execution.
84
+
85
+ #### Quick Deploy (2 Steps)
86
+
87
+ **Step 1: Get and Set API Key**
88
+
89
+ - Get your Sandock API Key from https://sandock.ai
90
+ - Edit `.env` and set: `SANDOCK_API_KEY=your-api-key-here`
91
+
92
+ **Step 2: Start services**
93
+
94
+ ```bash
95
+ docker compose up -d
96
+ ```
97
+
98
+ #### 🎉 Access Your Private Registry
99
+
100
+ - 🌐 **Web Interface**: http://localhost:3003
101
+ - 📚 **API Documentation**: http://localhost:3003/swagger
102
+ - 🔍 **Search & Execute** MCP tools remotely
103
+
104
+ #### Usage Example
105
+
106
+ ```bash
107
+ # Execute a tool remotely
108
+ curl -X POST http://localhost:3003/api/v1/packages/run \
109
+ -H "Content-Type: application/json" \
110
+ -d '{
111
+ "packageName": "@modelcontextprotocol/server-everything",
112
+ "toolKey": "echo",
113
+ "inputData": {
114
+ "message": "Hello, ToolSDK MCP Registry"
115
+ },
116
+ "envs": {}
117
+ }'
118
+ ```
119
+
120
+ > For more details about Docker Self-Hosting, see the [DEVELOPMENT documentation](./docs/DEVELOPMENT.md#4--quick-start-with-docker).
121
+
122
+ <a id="install-via-package-manager"></a>
123
+
124
+ ### Install via package manager:
75
125
 
76
126
  ```bash
77
127
  npm install @toolsdk.ai/registry
78
128
  ```
79
129
 
80
- #### Use it on your JavaScript / Typescript project:
130
+ ### Use it on your JavaScript / Typescript project:
81
131
 
82
132
  ```ts
83
133
  import mcpServerLists from '@toolsdk.ai/registry/indexes/packages-lists.json';
84
134
  ```
85
135
 
86
- #### Fetch all MCP Servers lists via cURL:
136
+ ### Fetch all MCP Servers lists via cURL:
87
137
 
88
138
  ```bash
89
139
  curl https://toolsdk-ai.github.io/awesome-mcp-registry/indexes/packages-list.json
@@ -94,6 +144,8 @@ curl https://toolsdk-ai.github.io/awesome-mcp-registry/indexes/packages-list.jso
94
144
  console.log(await(await fetch('https://toolsdk-ai.github.io/awesome-mcp-registry/indexes/packages-list.json')).json());
95
145
  ```
96
146
 
147
+ <a id="submit-new-mcp-servers"></a>
148
+
97
149
  ## 📦 Submit new MCP servers:
98
150
 
99
151
  ```json
@@ -118,11 +170,13 @@ console.log(await(await fetch('https://toolsdk-ai.github.io/awesome-mcp-registry
118
170
 
119
171
  For more detail please see [the guide](./docs/guide.md).
120
172
 
173
+ <a id="mcp-servers"></a>
174
+
121
175
  ## MCP Servers
122
176
 
123
177
  ✅: Validated and runnable tools (709)
124
178
 
125
- ❌: Cannot be run by the MCP client (with mock environments variables (3398))
179
+ ❌: Cannot be run by the MCP client (with mock environments variables (3399))
126
180
 
127
181
 
128
182
 
@@ -1786,6 +1840,7 @@ Enhance your development workflow with tools for coding and environment manageme
1786
1840
  - [❌ @fiveohhwon/workflows-mcp](https://github.com/fiveohhwon/workflows-mcp): Provides workflow management and automation through step-by-step execution with branching logic, conditional operations, template variables, and state persistence for complex multi-step processes like code reviews and data pipelines. (node)
1787
1841
  - [❌ autodocument](https://github.com/pars-doe/autodocument): Automatically generates documentation, test plans, and code reviews for software repositories through a bottom-up analysis approach that respects .gitignore rules and handles existing file updates. (node)
1788
1842
  - [❌ gdb-debugger](https://github.com/yywz1999/gdb-mcp-server): Integrates GDB with AI capabilities to provide interactive debugging assistance for C/C++ applications, enabling breakpoint management, memory examination, and execution flow analysis during debugging sessions. (python)
1843
+ - [❌ @juspay/neurolink](https://github.com/juspay/neurolink): Universal AI development platform unifying 12+ providers (OpenAI, Anthropic, Google, Bedrock, Azure) with built-in MCP support, multi-provider failover, and production-ready enterprise features (node)
1789
1844
  - [❌ clojars-dependency-versions](https://github.com/bigsy/clojars-mcp-server): Retrieves information related to Clojure dependency management. (node)
1790
1845
  - [❌ react-analyzer](https://github.com/azer/react-analyzer-mcp): Enables parsing and analysis of React component structures, props, and state management patterns for code review, debugging, and understanding complex React codebases (node)
1791
1846
  - [❌ ansible](https://github.com/tarnover/mcp-sysoperator): Integrates with Ansible to enable infrastructure automation through direct execution of playbooks, ad-hoc commands, inventory management, and AWS resource operations for DevOps workflows (node)
@@ -1,3 +1,3 @@
1
1
  import { OpenAPIHono } from "@hono/zod-openapi";
2
- declare const app: OpenAPIHono;
2
+ declare const app: OpenAPIHono<import("hono").Env, {}, "/">;
3
3
  export default app;
package/dist/api/index.js CHANGED
@@ -1,19 +1,17 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
3
  import { serve } from "@hono/node-server";
4
4
  import { swaggerUI } from "@hono/swagger-ui";
5
5
  import { OpenAPIHono } from "@hono/zod-openapi";
6
- import dotenv from "dotenv";
7
- import { searchRoutes } from "../search/search-route";
8
- import searchService from "../search/search-service";
9
- import { getDirname } from "../utils";
10
- import { packageRoutes } from "./package-route";
11
- const __dirname = getDirname(import.meta.url);
12
- dotenv.config({ path: path.resolve(process.cwd(), ".env.local") });
13
- dotenv.config({ path: path.resolve(process.cwd(), ".env") });
6
+ import { configRoutes } from "../domains/config/config-route";
7
+ import { packageRoutes } from "../domains/package/package-route";
8
+ import { searchRoutes } from "../domains/search/search-route";
9
+ import { SearchSO } from "../domains/search/search-so";
10
+ import { getServerPort, isSearchEnabled } from "../shared/config/environment";
11
+ import { getDirname } from "../shared/utils";
14
12
  const initializeSearchService = async () => {
15
13
  try {
16
- await searchService.initialize();
14
+ await SearchSO.getInstance();
17
15
  console.log("🔍 Search service initialized");
18
16
  }
19
17
  catch (error) {
@@ -21,22 +19,20 @@ const initializeSearchService = async () => {
21
19
  console.log("💡 Install and start MeiliSearch to enable enhanced search features");
22
20
  }
23
21
  };
22
+ // Load search.html content
23
+ const __dirname = getDirname(import.meta.url);
24
+ const searchHtmlPath = join(__dirname, "../domains/search/search.html");
25
+ const searchHtmlContent = readFileSync(searchHtmlPath, "utf-8");
24
26
  const app = new OpenAPIHono();
27
+ // Domain routes
25
28
  app.route("/api/v1", packageRoutes);
26
- if (process.env.ENABLE_SEARCH === "true") {
29
+ app.route("/api/v1/config", configRoutes);
30
+ if (isSearchEnabled()) {
27
31
  initializeSearchService().catch(console.error);
28
- app.route("/api/v1", searchRoutes);
32
+ app.route("/api/v1/search", searchRoutes);
29
33
  }
30
- app.get("/", async (c) => {
31
- try {
32
- const htmlPath = path.join(__dirname, "..", "search", "search.html");
33
- const html = await fs.readFile(htmlPath, "utf8");
34
- return c.html(html);
35
- }
36
- catch (error) {
37
- console.error("Failed to load home page:", error);
38
- return c.text("MCP Registry API Server is running!");
39
- }
34
+ app.get("/", (c) => {
35
+ return c.html(searchHtmlContent);
40
36
  });
41
37
  app.get("/api/meta", async (c) => {
42
38
  try {
@@ -50,6 +46,7 @@ app.get("/api/meta", async (c) => {
50
46
  return c.json({ version: "unknown" });
51
47
  }
52
48
  });
49
+ // OpenAPI documentation
53
50
  app.doc("/api/v1/doc", {
54
51
  openapi: "3.0.0",
55
52
  info: {
@@ -57,6 +54,7 @@ app.doc("/api/v1/doc", {
57
54
  title: "MCP Registry API",
58
55
  },
59
56
  });
57
+ // Swagger UI
60
58
  app.get("/swagger", swaggerUI({ url: "/api/v1/doc" }));
61
59
  app.notFound((c) => {
62
60
  return c.json({ success: false, code: 404, message: "[Registry API] Route not found" }, 404);
@@ -69,10 +67,10 @@ app.onError((err, c) => {
69
67
  message: `[Registry API] Internal server error, errMsg: ${err.message}`,
70
68
  }, 500);
71
69
  });
72
- const port = process.env.MCP_SERVER_PORT ? parseInt(process.env.MCP_SERVER_PORT, 10) : 3003;
73
- console.log(`Server is running on: http://localhost:${port}`);
70
+ const port = getServerPort();
74
71
  serve({
75
72
  fetch: app.fetch,
76
73
  port,
77
74
  });
75
+ console.log(`🚀 Server is running on http://localhost:${port}`);
78
76
  export default app;
@@ -0,0 +1,2 @@
1
+ import { OpenAPIHono } from "@hono/zod-openapi";
2
+ export declare const configRoutes: OpenAPIHono<import("hono").Env, {}, "/">;
@@ -0,0 +1,31 @@
1
+ import path from "node:path";
2
+ import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
3
+ import { getDirname } from "../../shared/utils/file-util";
4
+ import { createResponse, createRouteResponses } from "../../shared/utils/response-util";
5
+ import { configSchemas } from "./config-schema";
6
+ const __dirname = getDirname(import.meta.url);
7
+ export const configRoutes = new OpenAPIHono();
8
+ const featuredRoute = createRoute({
9
+ method: "get",
10
+ path: "/featured",
11
+ responses: createRouteResponses(configSchemas.FeaturedResponseSchema),
12
+ });
13
+ configRoutes.openapi(featuredRoute, async (c) => {
14
+ const featuredPath = path.join(__dirname, "../../../config/featured.mjs");
15
+ const featuredModule = await import(`file://${featuredPath}`);
16
+ const featured = featuredModule.default;
17
+ const response = createResponse(featured);
18
+ return c.json(response, 200);
19
+ });
20
+ const categoriesRoute = createRoute({
21
+ method: "get",
22
+ path: "/categories",
23
+ responses: createRouteResponses(configSchemas.CategoriesResponseSchema),
24
+ });
25
+ configRoutes.openapi(categoriesRoute, async (c) => {
26
+ const categoriesPath = path.join(__dirname, "../../../config/categories.mjs");
27
+ const categoriesModule = await import(`file://${categoriesPath}`);
28
+ const categories = categoriesModule.default;
29
+ const response = createResponse(categories);
30
+ return c.json(response, 200);
31
+ });
@@ -0,0 +1,57 @@
1
+ import { z } from "@hono/zod-openapi";
2
+ export declare const configSchemas: {
3
+ FeaturedResponseSchema: z.ZodObject<{
4
+ success: z.ZodBoolean;
5
+ code: z.ZodNumber;
6
+ message: z.ZodString;
7
+ } & {
8
+ data: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ success: boolean;
11
+ code: number;
12
+ message: string;
13
+ data?: string[] | undefined;
14
+ }, {
15
+ success: boolean;
16
+ code: number;
17
+ message: string;
18
+ data?: string[] | undefined;
19
+ }>;
20
+ CategoriesResponseSchema: z.ZodObject<{
21
+ success: z.ZodBoolean;
22
+ code: z.ZodNumber;
23
+ message: z.ZodString;
24
+ } & {
25
+ data: z.ZodOptional<z.ZodArray<z.ZodObject<{
26
+ key: z.ZodString;
27
+ name: z.ZodString;
28
+ description: z.ZodOptional<z.ZodString>;
29
+ }, "strip", z.ZodTypeAny, {
30
+ name: string;
31
+ key: string;
32
+ description?: string | undefined;
33
+ }, {
34
+ name: string;
35
+ key: string;
36
+ description?: string | undefined;
37
+ }>, "many">>;
38
+ }, "strip", z.ZodTypeAny, {
39
+ success: boolean;
40
+ code: number;
41
+ message: string;
42
+ data?: {
43
+ name: string;
44
+ key: string;
45
+ description?: string | undefined;
46
+ }[] | undefined;
47
+ }, {
48
+ success: boolean;
49
+ code: number;
50
+ message: string;
51
+ data?: {
52
+ name: string;
53
+ key: string;
54
+ description?: string | undefined;
55
+ }[] | undefined;
56
+ }>;
57
+ };
@@ -0,0 +1,10 @@
1
+ import { z } from "@hono/zod-openapi";
2
+ import { BaseResponseSchema, CategoryConfigSchema } from "../../shared/schemas/common-schema";
3
+ export const configSchemas = {
4
+ FeaturedResponseSchema: BaseResponseSchema.extend({
5
+ data: z.array(z.string()).optional(),
6
+ }).openapi("FeaturedResponse"),
7
+ CategoriesResponseSchema: BaseResponseSchema.extend({
8
+ data: z.array(CategoryConfigSchema).optional(),
9
+ }).openapi("CategoriesResponse"),
10
+ };
@@ -0,0 +1,3 @@
1
+ import type { z } from "zod";
2
+ import type { CategoryConfigSchema } from "../../shared/schemas";
3
+ export type CategoryConfig = z.infer<typeof CategoryConfigSchema>;
@@ -0,0 +1,9 @@
1
+ import type { MCPSandboxProvider } from "../sandbox/sandbox-types";
2
+ import type { ToolExecutor } from "./executor-types";
3
+ /**
4
+ * Executor Factory
5
+ * Creates appropriate executor based on sandbox provider configuration
6
+ */
7
+ export declare class ExecutorFactory {
8
+ static create(provider: MCPSandboxProvider): ToolExecutor;
9
+ }
@@ -0,0 +1,17 @@
1
+ import { LocalExecutor } from "./local-executor";
2
+ import { SandboxExecutor } from "./sandbox-executor";
3
+ /**
4
+ * Executor Factory
5
+ * Creates appropriate executor based on sandbox provider configuration
6
+ */
7
+ // biome-ignore lint/complexity/noStaticOnlyClass: Factory pattern
8
+ export class ExecutorFactory {
9
+ static create(provider) {
10
+ if (provider === "LOCAL") {
11
+ console.log("[ExecutorFactory] Creating LocalExecutor");
12
+ return new LocalExecutor();
13
+ }
14
+ console.log(`[ExecutorFactory] Creating SandboxExecutor with provider: ${provider}`);
15
+ return new SandboxExecutor(provider);
16
+ }
17
+ }
@@ -0,0 +1,15 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ export interface ToolExecuteRequest {
3
+ packageName: string;
4
+ toolKey: string;
5
+ inputData: Record<string, unknown>;
6
+ envs?: Record<string, string>;
7
+ }
8
+ /**
9
+ * Tool Executor Interface
10
+ * Unified abstraction for local and sandbox execution
11
+ */
12
+ export interface ToolExecutor {
13
+ executeTool(request: ToolExecuteRequest): Promise<unknown>;
14
+ listTools(packageName: string): Promise<Tool[]>;
15
+ }
@@ -0,0 +1,12 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { ToolExecuteRequest, ToolExecutor } from "./executor-types";
3
+ /**
4
+ * Local Executor
5
+ * Executes MCP tools in local environment
6
+ */
7
+ export declare class LocalExecutor implements ToolExecutor {
8
+ private readonly packageRepository;
9
+ constructor();
10
+ executeTool(request: ToolExecuteRequest): Promise<unknown>;
11
+ listTools(packageName: string): Promise<Tool[]>;
12
+ }
@@ -0,0 +1,48 @@
1
+ import path from "node:path";
2
+ import { getDirname } from "../../shared/utils/file-util";
3
+ import { getMcpClient } from "../../shared/utils/mcp-client-util";
4
+ import { PackageRepository } from "../package/package-repository";
5
+ /**
6
+ * Local Executor
7
+ * Executes MCP tools in local environment
8
+ */
9
+ export class LocalExecutor {
10
+ constructor() {
11
+ const __dirname = getDirname(import.meta.url);
12
+ const packagesDir = path.join(__dirname, "../../../packages");
13
+ this.packageRepository = new PackageRepository(packagesDir);
14
+ }
15
+ async executeTool(request) {
16
+ const mcpServerConfig = this.packageRepository.getPackageConfig(request.packageName);
17
+ const { client, closeConnection } = await getMcpClient(mcpServerConfig, request.envs || {});
18
+ try {
19
+ const result = await client.callTool({
20
+ name: request.toolKey,
21
+ arguments: request.inputData,
22
+ });
23
+ console.log(`[LocalExecutor] Tool ${request.toolKey} executed successfully`);
24
+ return result;
25
+ }
26
+ finally {
27
+ await closeConnection();
28
+ }
29
+ }
30
+ async listTools(packageName) {
31
+ const mcpServerConfig = this.packageRepository.getPackageConfig(packageName);
32
+ const mockEnvs = {};
33
+ if (mcpServerConfig.env) {
34
+ Object.keys(mcpServerConfig.env).forEach((key) => {
35
+ mockEnvs[key] = "mock_value";
36
+ });
37
+ }
38
+ const { client, closeConnection } = await getMcpClient(mcpServerConfig, mockEnvs);
39
+ try {
40
+ const { tools } = await client.listTools();
41
+ console.log(`[LocalExecutor] Tools list retrieved successfully for package ${packageName}`);
42
+ return tools;
43
+ }
44
+ finally {
45
+ await closeConnection();
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,16 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { MCPSandboxProvider } from "../sandbox/sandbox-types";
3
+ import type { ToolExecuteRequest, ToolExecutor } from "./executor-types";
4
+ /**
5
+ * Sandbox Executor
6
+ * Executes MCP tools in sandbox environment
7
+ */
8
+ export declare class SandboxExecutor implements ToolExecutor {
9
+ private readonly provider;
10
+ private readonly sandboxPool;
11
+ private readonly packageRepository;
12
+ private readonly localExecutor;
13
+ constructor(provider: MCPSandboxProvider);
14
+ executeTool(request: ToolExecuteRequest): Promise<unknown>;
15
+ listTools(packageName: string): Promise<Tool[]>;
16
+ }
@@ -0,0 +1,83 @@
1
+ import path from "node:path";
2
+ import { getDirname } from "../../shared/utils/file-util";
3
+ import { PackageRepository } from "../package/package-repository";
4
+ import { SandboxPoolSO } from "../sandbox/sandbox-pool-so";
5
+ import { LocalExecutor } from "./local-executor";
6
+ /**
7
+ * Sandbox Executor
8
+ * Executes MCP tools in sandbox environment
9
+ */
10
+ export class SandboxExecutor {
11
+ constructor(provider) {
12
+ this.provider = provider;
13
+ this.sandboxPool = SandboxPoolSO.getInstance();
14
+ const __dirname = getDirname(import.meta.url);
15
+ const packagesDir = path.join(__dirname, "../../../packages");
16
+ this.packageRepository = new PackageRepository(packagesDir);
17
+ this.localExecutor = new LocalExecutor();
18
+ }
19
+ async executeTool(request) {
20
+ const mcpServerConfig = this.packageRepository.getPackageConfig(request.packageName);
21
+ const runtime = mcpServerConfig.runtime || "python";
22
+ // Sandbox only supports node runtime, fallback to LOCAL for other runtimes
23
+ if (runtime !== "node") {
24
+ console.log(`[SandboxExecutor] Runtime '${runtime}' is not supported in sandbox, using LOCAL execution`);
25
+ return await this.localExecutor.executeTool(request);
26
+ }
27
+ const sandboxClient = await this.sandboxPool.acquire(runtime, this.provider);
28
+ try {
29
+ await sandboxClient.initialize();
30
+ const result = await sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
31
+ console.log(`[SandboxExecutor] Tool ${request.toolKey} executed successfully in sandbox`);
32
+ return result;
33
+ }
34
+ catch (error) {
35
+ console.warn(`[SandboxExecutor] sandbox execution failed, falling back to LOCAL execution`);
36
+ console.warn(`[SandboxExecutor] Error: ${error instanceof Error ? error.message : String(error)}`);
37
+ try {
38
+ const result = await this.localExecutor.executeTool(request);
39
+ console.log(`[SandboxExecutor] Tool ${request.toolKey} executed successfully with LOCAL fallback`);
40
+ return result;
41
+ }
42
+ catch (localError) {
43
+ console.error("[SandboxExecutor] LOCAL fallback execution also failed");
44
+ throw localError;
45
+ }
46
+ }
47
+ finally {
48
+ await this.sandboxPool.release(runtime, this.provider);
49
+ }
50
+ }
51
+ async listTools(packageName) {
52
+ const mcpServerConfig = this.packageRepository.getPackageConfig(packageName);
53
+ const runtime = mcpServerConfig.runtime || "python";
54
+ // Sandbox only supports node runtime, fallback to LOCAL for other runtimes
55
+ if (runtime !== "node") {
56
+ console.log(`[SandboxExecutor] Runtime '${runtime}' is not supported in sandbox, using LOCAL execution`);
57
+ return await this.localExecutor.listTools(packageName);
58
+ }
59
+ const sandboxClient = await this.sandboxPool.acquire(runtime, this.provider);
60
+ try {
61
+ await sandboxClient.initialize();
62
+ const tools = await sandboxClient.listTools(packageName);
63
+ console.log(`[SandboxExecutor] Tools list retrieved successfully for package ${packageName}`);
64
+ return tools;
65
+ }
66
+ catch (error) {
67
+ console.warn(`[SandboxExecutor] sandbox list tools failed, falling back to LOCAL execution`);
68
+ console.warn(`[SandboxExecutor] Error: ${error instanceof Error ? error.message : String(error)}`);
69
+ try {
70
+ const tools = await this.localExecutor.listTools(packageName);
71
+ console.log(`[SandboxExecutor] Tools list retrieved successfully with LOCAL fallback`);
72
+ return tools;
73
+ }
74
+ catch (localError) {
75
+ console.error("[SandboxExecutor] LOCAL fallback list tools also failed");
76
+ throw localError;
77
+ }
78
+ }
79
+ finally {
80
+ await this.sandboxPool.release(runtime, this.provider);
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,17 @@
1
+ export declare const packageHandler: {
2
+ getPackageDetail: (packageName: string) => Promise<{
3
+ success: boolean;
4
+ code: number;
5
+ message: string;
6
+ }>;
7
+ executeTool: (packageName: string, toolKey: string, inputData: Record<string, unknown>, envs?: Record<string, string>) => Promise<{
8
+ success: boolean;
9
+ code: number;
10
+ message: string;
11
+ }>;
12
+ listTools: (packageName: string) => Promise<{
13
+ success: boolean;
14
+ code: number;
15
+ message: string;
16
+ }>;
17
+ };
@@ -0,0 +1,58 @@
1
+ import path from "node:path";
2
+ import { getSandboxProvider } from "../../shared/config/environment";
3
+ import { getDirname } from "../../shared/utils/file-util";
4
+ import { createErrorResponse, createResponse } from "../../shared/utils/response-util";
5
+ import { ExecutorFactory } from "../executor/executor-factory";
6
+ import { PackageRepository } from "./package-repository";
7
+ import { PackageSO } from "./package-so";
8
+ const __dirname = getDirname(import.meta.url);
9
+ const packagesDir = path.join(__dirname, "../../../packages");
10
+ const repository = new PackageRepository(packagesDir);
11
+ const executor = ExecutorFactory.create(getSandboxProvider());
12
+ export const packageHandler = {
13
+ getPackageDetail: async (packageName) => {
14
+ try {
15
+ const packageSO = await PackageSO.init(packageName, repository, executor);
16
+ const result = await packageSO.getDetailWithTools();
17
+ return createResponse(result);
18
+ }
19
+ catch (error) {
20
+ if (error instanceof Error && error.message.includes("not found")) {
21
+ return createErrorResponse(`Package '${packageName}' not found`, 404);
22
+ }
23
+ throw error;
24
+ }
25
+ },
26
+ executeTool: async (packageName, toolKey, inputData, envs) => {
27
+ try {
28
+ const packageSO = await PackageSO.init(packageName, repository, executor);
29
+ const result = await packageSO.executeTool(toolKey, inputData, envs);
30
+ return createResponse(result);
31
+ }
32
+ catch (error) {
33
+ if (error instanceof Error) {
34
+ if (error.message.includes("not found")) {
35
+ return createErrorResponse(`Package '${packageName}' not found`, 404);
36
+ }
37
+ if (error.message.includes("Unknown tool")) {
38
+ return createErrorResponse(`Tool '${toolKey}' not found in package '${packageName}'`, 404);
39
+ }
40
+ return createErrorResponse(`Error: ${error.message}`, 500);
41
+ }
42
+ throw error;
43
+ }
44
+ },
45
+ listTools: async (packageName) => {
46
+ try {
47
+ const packageSO = await PackageSO.init(packageName, repository, executor);
48
+ const tools = await packageSO.getTools();
49
+ return createResponse(tools);
50
+ }
51
+ catch (error) {
52
+ if (error instanceof Error && error.message.includes("not found")) {
53
+ return createErrorResponse(`Package '${packageName}' not found`, 404);
54
+ }
55
+ throw error;
56
+ }
57
+ },
58
+ };
@@ -0,0 +1,9 @@
1
+ import type { MCPServerPackageConfig, PackagesList } from "./package-types";
2
+ export declare class PackageRepository {
3
+ private readonly packagesList;
4
+ private readonly packagesDir;
5
+ constructor(packagesDir: string);
6
+ getPackageConfig(packageName: string): MCPServerPackageConfig;
7
+ getAllPackages(): PackagesList;
8
+ exists(packageName: string): boolean;
9
+ }