@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.
- package/README.md +66 -11
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +23 -25
- package/dist/domains/config/config-route.d.ts +2 -0
- package/dist/domains/config/config-route.js +31 -0
- package/dist/domains/config/config-schema.d.ts +57 -0
- package/dist/domains/config/config-schema.js +10 -0
- package/dist/domains/config/config-types.d.ts +3 -0
- package/dist/domains/executor/executor-factory.d.ts +9 -0
- package/dist/domains/executor/executor-factory.js +17 -0
- package/dist/domains/executor/executor-types.d.ts +15 -0
- package/dist/domains/executor/local-executor.d.ts +12 -0
- package/dist/domains/executor/local-executor.js +48 -0
- package/dist/domains/executor/sandbox-executor.d.ts +16 -0
- package/dist/domains/executor/sandbox-executor.js +83 -0
- package/dist/domains/package/package-handler.d.ts +17 -0
- package/dist/domains/package/package-handler.js +58 -0
- package/dist/domains/package/package-repository.d.ts +9 -0
- package/dist/domains/package/package-repository.js +26 -0
- package/dist/domains/package/package-route.d.ts +2 -0
- package/dist/{api → domains/package}/package-route.js +38 -52
- package/dist/domains/package/package-schema.d.ts +244 -0
- package/dist/domains/package/package-schema.js +52 -0
- package/dist/domains/package/package-so.d.ts +78 -0
- package/dist/domains/package/package-so.js +61 -0
- package/dist/domains/package/package-so.test.js +378 -0
- package/dist/domains/package/package-types.d.ts +9 -0
- package/dist/domains/package/package-types.js +1 -0
- package/dist/domains/sandbox/clients/daytona-client.d.ts +17 -0
- package/dist/domains/sandbox/clients/daytona-client.js +112 -0
- package/dist/domains/sandbox/clients/sandock-client.d.ts +19 -0
- package/dist/domains/sandbox/clients/sandock-client.js +178 -0
- package/dist/domains/sandbox/sandbox-factory.d.ts +8 -0
- package/dist/domains/sandbox/sandbox-factory.js +23 -0
- package/dist/domains/sandbox/sandbox-pool-so.d.ts +25 -0
- package/dist/domains/sandbox/sandbox-pool-so.js +123 -0
- package/dist/domains/sandbox/sandbox-types.d.ts +25 -0
- package/dist/domains/sandbox/sandbox-types.js +1 -0
- package/dist/domains/sandbox/sandbox-utils.d.ts +3 -0
- package/dist/domains/sandbox/sandbox-utils.js +109 -0
- package/dist/domains/search/search-handler.d.ts +47 -0
- package/dist/domains/search/search-handler.js +113 -0
- package/dist/domains/search/search-route.d.ts +2 -0
- package/dist/domains/search/search-route.js +101 -0
- package/dist/domains/search/search-schema.d.ts +384 -0
- package/dist/domains/search/search-schema.js +99 -0
- package/dist/domains/search/search-so.d.ts +55 -0
- package/dist/{search/search-service.js → domains/search/search-so.js} +200 -297
- package/dist/shared/config/environment.d.ts +16 -0
- package/dist/shared/config/environment.js +41 -0
- package/dist/shared/schemas/common-schema.d.ts +249 -0
- package/dist/{schema.js → shared/schemas/common-schema.js} +37 -80
- package/dist/shared/schemas/index.d.ts +1 -0
- package/dist/shared/schemas/index.js +1 -0
- package/dist/shared/scripts-helpers/index.d.ts +60 -0
- package/dist/shared/scripts-helpers/index.js +61 -0
- package/dist/shared/utils/file-util.d.ts +1 -0
- package/dist/shared/utils/file-util.js +5 -0
- package/dist/shared/utils/index.d.ts +5 -0
- package/dist/shared/utils/index.js +5 -0
- package/dist/shared/utils/mcp-client-util.d.ts +31 -0
- package/dist/shared/utils/mcp-client-util.js +79 -0
- package/dist/shared/utils/package-util.d.ts +6 -0
- package/dist/shared/utils/package-util.js +53 -0
- package/dist/shared/utils/promise-util.d.ts +1 -0
- package/dist/shared/utils/promise-util.js +14 -0
- package/dist/{utils.d.ts → shared/utils/response-util.d.ts} +6 -2
- package/dist/{utils.js → shared/utils/response-util.js} +1 -6
- package/dist/shared/utils/string-util.d.ts +1 -0
- package/dist/shared/utils/string-util.js +25 -0
- package/dist/shared/utils/validation-util.d.ts +12 -0
- package/dist/shared/utils/validation-util.js +99 -0
- package/indexes/categories-list.json +1 -0
- package/indexes/packages-list.json +6 -0
- package/package.json +9 -2
- package/packages/developer-tools/neurolink.json +23 -0
- package/packages/search-data-extraction/ref-tools-mcp.json +7 -2
- package/README.dev.md +0 -195
- package/dist/api/package-handler.d.ts +0 -18
- package/dist/api/package-handler.js +0 -72
- package/dist/api/package-route.d.ts +0 -2
- package/dist/api/package-so.d.ts +0 -19
- package/dist/api/package-so.js +0 -263
- package/dist/api/package.test.js +0 -19
- package/dist/helper.d.ts +0 -72
- package/dist/helper.js +0 -278
- package/dist/sandbox/mcp-sandbox-client.d.ts +0 -37
- package/dist/sandbox/mcp-sandbox-client.js +0 -428
- package/dist/schema.d.ts +0 -806
- package/dist/search/search-route.d.ts +0 -3
- package/dist/search/search-route.js +0 -305
- package/dist/search/search-service.d.ts +0 -120
- package/dist/search/search.test.js +0 -100
- package/dist/types.d.ts +0 -27
- /package/dist/{api/package.test.d.ts → domains/config/config-types.js} +0 -0
- /package/dist/{search/search.test.d.ts → domains/executor/executor-types.js} +0 -0
- /package/dist/{types.js → domains/package/package-so.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://www.producthunt.com/products/toolsdk-ai)
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|

|
|
11
11
|
|
|
12
|
-
An open, high-quality, well-structured and developer-friendly list of
|
|
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
|
-
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
- [
|
|
37
|
-
- [
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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)
|
package/dist/api/index.d.ts
CHANGED
package/dist/api/index.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
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
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
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
|
|
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
|
-
|
|
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("/",
|
|
31
|
-
|
|
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 =
|
|
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,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,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
|
+
}
|