@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/dist/api/package-so.js
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { getMcpClient, getPackageConfigByKey, typedAllPackagesList } from "../helper.js";
|
|
4
|
-
import { MCPSandboxClient } from "../sandbox/mcp-sandbox-client.js";
|
|
5
|
-
import { getDirname } from "../utils";
|
|
6
|
-
const __dirname = getDirname(import.meta.url);
|
|
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
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// Acquire / Release explicit APIs (for external or future use)
|
|
62
|
-
static async acquireSandbox(key = "default") {
|
|
63
|
-
const record = PackageSO.sandboxInstances.get(key);
|
|
64
|
-
if (record) {
|
|
65
|
-
record.refCount++;
|
|
66
|
-
record.lastUsedAt = Date.now();
|
|
67
|
-
record.client.touch();
|
|
68
|
-
return record.client;
|
|
69
|
-
}
|
|
70
|
-
// Create new instance (note MAX_SANDBOXES check, consistent with constructor logic)
|
|
71
|
-
if (PackageSO.sandboxInstances.size >= PackageSO.MAX_SANDBOXES) {
|
|
72
|
-
// Try to evict LRU idle instance
|
|
73
|
-
let lruKey = null;
|
|
74
|
-
let lruTime = Infinity;
|
|
75
|
-
for (const [k, r] of PackageSO.sandboxInstances) {
|
|
76
|
-
if (r.refCount === 0 && r.lastUsedAt < lruTime) {
|
|
77
|
-
lruKey = k;
|
|
78
|
-
lruTime = r.lastUsedAt;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (lruKey) {
|
|
82
|
-
const evict = PackageSO.sandboxInstances.get(lruKey);
|
|
83
|
-
if (evict) {
|
|
84
|
-
await evict.client
|
|
85
|
-
.kill()
|
|
86
|
-
.catch((e) => console.error("[PackageSO] Error killing evicted sandbox:", e));
|
|
87
|
-
PackageSO.sandboxInstances.delete(lruKey);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
throw new Error("Cannot create new sandbox: max sandboxes reached and none are idle");
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const client = new MCPSandboxClient();
|
|
95
|
-
const newRecord = {
|
|
96
|
-
client,
|
|
97
|
-
refCount: 1,
|
|
98
|
-
lastUsedAt: Date.now(),
|
|
99
|
-
idleCloseMs: PackageSO.IDLE_CLOSE_MS,
|
|
100
|
-
};
|
|
101
|
-
PackageSO.sandboxInstances.set(key, newRecord);
|
|
102
|
-
return client;
|
|
103
|
-
}
|
|
104
|
-
static async releaseSandbox(key = "default") {
|
|
105
|
-
const record = PackageSO.sandboxInstances.get(key);
|
|
106
|
-
if (!record)
|
|
107
|
-
return;
|
|
108
|
-
record.refCount = Math.max(0, record.refCount - 1);
|
|
109
|
-
record.lastUsedAt = Date.now();
|
|
110
|
-
if (record.refCount === 0) {
|
|
111
|
-
// schedule idle close after IDLE_CLOSE_MS
|
|
112
|
-
record.client.scheduleIdleClose(record.idleCloseMs || PackageSO.IDLE_CLOSE_MS);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// Cleanup all static sandbox instances safely
|
|
116
|
-
static async cleanupSandboxInstances() {
|
|
117
|
-
const killers = [];
|
|
118
|
-
for (const [key, record] of PackageSO.sandboxInstances) {
|
|
119
|
-
killers.push((async () => {
|
|
120
|
-
try {
|
|
121
|
-
await record.client.kill();
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
console.error("[PackageSO] cleanup error for sandbox", key, err);
|
|
125
|
-
}
|
|
126
|
-
})());
|
|
127
|
-
PackageSO.sandboxInstances.delete(key);
|
|
128
|
-
}
|
|
129
|
-
await Promise.all(killers);
|
|
130
|
-
}
|
|
131
|
-
async executeTool(request) {
|
|
132
|
-
const mcpServerConfig = getPackageConfigByKey(request.packageName);
|
|
133
|
-
if (this.useSandbox && mcpServerConfig.runtime === "node") {
|
|
134
|
-
try {
|
|
135
|
-
const result = await this.executeToolInSandbox(request);
|
|
136
|
-
return result;
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
console.warn(`[executeTool] Sandbox mode failed for tool ${request.toolKey} in package ${request.packageName}, falling back to local mode:`, error);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const { client, closeConnection } = await getMcpClient(mcpServerConfig, request.envs || {});
|
|
143
|
-
try {
|
|
144
|
-
const result = await client.callTool({
|
|
145
|
-
name: request.toolKey,
|
|
146
|
-
arguments: request.inputData,
|
|
147
|
-
});
|
|
148
|
-
console.log(`Tool ${request.toolKey} executed successfully`);
|
|
149
|
-
return result;
|
|
150
|
-
}
|
|
151
|
-
finally {
|
|
152
|
-
await closeConnection();
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
async executeToolInSandbox(request) {
|
|
156
|
-
if (!this.sandboxClient) {
|
|
157
|
-
throw new Error("Sandbox client not initialized");
|
|
158
|
-
}
|
|
159
|
-
// Initialize if not already initialized (concurrency protection via MCPSandboxClient.initialize)
|
|
160
|
-
await this.sandboxClient.initialize();
|
|
161
|
-
// Mark usage
|
|
162
|
-
this.sandboxClient.touch();
|
|
163
|
-
try {
|
|
164
|
-
const result = await this.sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
|
|
165
|
-
console.log(`Tool ${request.toolKey} executed successfully in sandbox`);
|
|
166
|
-
return result;
|
|
167
|
-
}
|
|
168
|
-
catch (error) {
|
|
169
|
-
// If it's a sandbox not found error, try reinitializing and retrying once
|
|
170
|
-
if (error instanceof Error && error.message.includes("sandbox was not found")) {
|
|
171
|
-
console.log("[PackageSO] Retrying tool execution after sandbox failure");
|
|
172
|
-
await this.sandboxClient.initialize();
|
|
173
|
-
// Retry tool execution
|
|
174
|
-
const result = await this.sandboxClient.executeTool(request.packageName, request.toolKey, request.inputData || {}, request.envs);
|
|
175
|
-
console.log(`Tool ${request.toolKey} executed successfully in sandbox (retry)`);
|
|
176
|
-
return result;
|
|
177
|
-
}
|
|
178
|
-
throw error;
|
|
179
|
-
}
|
|
180
|
-
finally {
|
|
181
|
-
// Release reference count
|
|
182
|
-
await PackageSO.releaseSandbox("default");
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
async listTools(packageName) {
|
|
186
|
-
const mcpServerConfig = getPackageConfigByKey(packageName);
|
|
187
|
-
if (this.useSandbox && mcpServerConfig.runtime === "node") {
|
|
188
|
-
try {
|
|
189
|
-
const tools = await this.listToolsInSandbox(packageName);
|
|
190
|
-
return tools;
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
console.warn(`[listTools] Sandbox mode failed for package ${packageName}, falling back to local mode:`, error);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
const mockEnvs = {};
|
|
197
|
-
if (mcpServerConfig.env) {
|
|
198
|
-
Object.keys(mcpServerConfig.env).forEach((key) => {
|
|
199
|
-
mockEnvs[key] = "mock_value";
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
const { client, closeConnection } = await getMcpClient(mcpServerConfig, mockEnvs);
|
|
203
|
-
try {
|
|
204
|
-
const { tools } = await client.listTools();
|
|
205
|
-
console.log(`Tools list retrieved successfully for package ${packageName}`);
|
|
206
|
-
return tools;
|
|
207
|
-
}
|
|
208
|
-
finally {
|
|
209
|
-
await closeConnection();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
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();
|
|
219
|
-
try {
|
|
220
|
-
const tools = await this.sandboxClient.listTools(packageName);
|
|
221
|
-
console.log(`Tools list retrieved successfully for package ${packageName} in sandbox`);
|
|
222
|
-
return tools;
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
// If it's a sandbox not found error, try reinitializing and retrying once
|
|
226
|
-
if (error instanceof Error && error.message.includes("sandbox was not found")) {
|
|
227
|
-
console.log("[PackageSO] Retrying tools listing after sandbox failure");
|
|
228
|
-
await this.sandboxClient.initialize();
|
|
229
|
-
// Retry listing tools
|
|
230
|
-
const tools = await this.sandboxClient.listTools(packageName);
|
|
231
|
-
console.log(`Tools list retrieved successfully for package ${packageName} in sandbox (retry)`);
|
|
232
|
-
return tools;
|
|
233
|
-
}
|
|
234
|
-
throw error;
|
|
235
|
-
}
|
|
236
|
-
finally {
|
|
237
|
-
await PackageSO.releaseSandbox("default");
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
async getPackageDetail(packageName) {
|
|
241
|
-
const packageInfo = typedAllPackagesList[packageName];
|
|
242
|
-
if (!packageInfo) {
|
|
243
|
-
throw new Error(`Package ${packageName} not found`);
|
|
244
|
-
}
|
|
245
|
-
const jsonFilePath = path.join(__dirname, "../../packages/", packageInfo.path);
|
|
246
|
-
const jsonStr = fs.readFileSync(jsonFilePath, "utf-8");
|
|
247
|
-
const packageConfig = JSON.parse(jsonStr);
|
|
248
|
-
let tools;
|
|
249
|
-
try {
|
|
250
|
-
tools = await this.listTools(packageName);
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
console.warn(`Warn retrieving tools for package ${packageName}:`, error.message);
|
|
254
|
-
// if tools cannot be retrieved, set tools to undefined
|
|
255
|
-
tools = undefined;
|
|
256
|
-
}
|
|
257
|
-
const packageConfigWithTools = Object.assign(Object.assign({}, packageConfig), { tools });
|
|
258
|
-
return packageConfigWithTools;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
PackageSO.sandboxInstances = new Map();
|
|
262
|
-
PackageSO.MAX_SANDBOXES = 10;
|
|
263
|
-
PackageSO.IDLE_CLOSE_MS = 5 * 60 * 1000;
|
package/dist/api/package.test.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// npx vitest run src/api/package.test.ts
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { PackageSO } from "./package-so";
|
|
4
|
-
describe("PackageSO - MCP Tool Execution Service Test", () => {
|
|
5
|
-
it("should execute tool successfully", async () => {
|
|
6
|
-
const toolSO = new PackageSO();
|
|
7
|
-
const request = {
|
|
8
|
-
packageName: "mcp-starter",
|
|
9
|
-
toolKey: "hello_tool",
|
|
10
|
-
inputData: { name: "Mike" },
|
|
11
|
-
envs: {},
|
|
12
|
-
};
|
|
13
|
-
const result = await toolSO.executeTool(request);
|
|
14
|
-
expect(result).toEqual({
|
|
15
|
-
content: [],
|
|
16
|
-
message: "Hello, Mike!",
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
});
|
package/dist/helper.d.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
-
import type { MCPServerPackageConfig } from "./types";
|
|
4
|
-
export declare const typedAllPackagesList: Record<string, {
|
|
5
|
-
path: string;
|
|
6
|
-
category?: string | undefined;
|
|
7
|
-
validated?: boolean | undefined;
|
|
8
|
-
tools?: Record<string, {
|
|
9
|
-
description?: string | undefined;
|
|
10
|
-
name?: string | undefined;
|
|
11
|
-
}> | undefined;
|
|
12
|
-
}>;
|
|
13
|
-
export declare function getPackageConfigByKey(packageKey: string): MCPServerPackageConfig;
|
|
14
|
-
export declare function getPackageJSON(packageName: string): any;
|
|
15
|
-
export declare function getMcpClient(mcpServerConfig: MCPServerPackageConfig, env?: Record<string, string>): Promise<{
|
|
16
|
-
client: Client<{
|
|
17
|
-
method: string;
|
|
18
|
-
params?: {
|
|
19
|
-
[x: string]: unknown;
|
|
20
|
-
_meta?: {
|
|
21
|
-
[x: string]: unknown;
|
|
22
|
-
progressToken?: string | number | undefined;
|
|
23
|
-
} | undefined;
|
|
24
|
-
} | undefined;
|
|
25
|
-
}, {
|
|
26
|
-
method: string;
|
|
27
|
-
params?: {
|
|
28
|
-
[x: string]: unknown;
|
|
29
|
-
_meta?: {
|
|
30
|
-
[x: string]: unknown;
|
|
31
|
-
} | undefined;
|
|
32
|
-
} | undefined;
|
|
33
|
-
}, {
|
|
34
|
-
[x: string]: unknown;
|
|
35
|
-
_meta?: {
|
|
36
|
-
[x: string]: unknown;
|
|
37
|
-
} | undefined;
|
|
38
|
-
}>;
|
|
39
|
-
transport: StdioClientTransport;
|
|
40
|
-
closeConnection: () => Promise<void>;
|
|
41
|
-
}>;
|
|
42
|
-
export declare function updatePackageJsonDependencies({ packageDeps, enableValidation, }: {
|
|
43
|
-
packageDeps: Record<string, string>;
|
|
44
|
-
enableValidation?: boolean;
|
|
45
|
-
}): void;
|
|
46
|
-
export declare function getActualVersion(packageName: string, configuredVersion?: string): string;
|
|
47
|
-
export declare function withTimeout<T>(ms: number, promise: Promise<T>): Promise<T>;
|
|
48
|
-
export declare function isValidNpmPackage(packageName: string): Promise<boolean>;
|
|
49
|
-
interface PyProjectToml {
|
|
50
|
-
project?: {
|
|
51
|
-
dependencies?: string[];
|
|
52
|
-
[key: string]: unknown;
|
|
53
|
-
};
|
|
54
|
-
[key: string]: unknown;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Parses the pyproject.toml file and returns its content
|
|
58
|
-
* @returns Parsed pyproject.toml content
|
|
59
|
-
*/
|
|
60
|
-
export declare function parsePyprojectToml(): PyProjectToml;
|
|
61
|
-
/**
|
|
62
|
-
* Extracts package name from a dependency string
|
|
63
|
-
* @param dep - Dependency string (e.g., "package>=1.0.0")
|
|
64
|
-
* @returns Package name without version constraints
|
|
65
|
-
*/
|
|
66
|
-
export declare function extractPackageName(dep: string): string;
|
|
67
|
-
/**
|
|
68
|
-
* Gets Python dependencies from pyproject.toml
|
|
69
|
-
* @returns Array of Python dependency names
|
|
70
|
-
*/
|
|
71
|
-
export declare function getPythonDependencies(): string[];
|
|
72
|
-
export {};
|
package/dist/helper.js
DELETED
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import toml from "@iarna/toml";
|
|
5
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
6
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
7
|
-
import axios from "axios";
|
|
8
|
-
import semver from "semver";
|
|
9
|
-
import allPackagesList from "../indexes/packages-list.json";
|
|
10
|
-
import { getDirname } from "../src/utils";
|
|
11
|
-
import { MCPServerPackageConfigSchema, PackagesListSchema } from "./schema";
|
|
12
|
-
const __dirname = getDirname(import.meta.url);
|
|
13
|
-
export const typedAllPackagesList = PackagesListSchema.parse(allPackagesList);
|
|
14
|
-
export function getPackageConfigByKey(packageKey) {
|
|
15
|
-
const value = typedAllPackagesList[packageKey];
|
|
16
|
-
if (!value) {
|
|
17
|
-
throw new Error(`Package '${packageKey}' not found in packages list.`);
|
|
18
|
-
}
|
|
19
|
-
const jsonFile = value.path;
|
|
20
|
-
// read the JSON file and convert it to MCPServerPackageConfig
|
|
21
|
-
const jsonStr = fs.readFileSync(`${__dirname}/../packages/${jsonFile}`, "utf-8");
|
|
22
|
-
const mcpServerConfig = MCPServerPackageConfigSchema.parse(JSON.parse(jsonStr));
|
|
23
|
-
return mcpServerConfig;
|
|
24
|
-
}
|
|
25
|
-
export function getPackageJSON(packageName) {
|
|
26
|
-
const packageJSONFilePath = `${__dirname}/../node_modules/${packageName}/package.json`;
|
|
27
|
-
// Check if the package exists in node_modules
|
|
28
|
-
if (!fs.existsSync(packageJSONFilePath)) {
|
|
29
|
-
throw new Error(`Package '${packageName}' not found in node_modules. Install it first with: pnpm add ${packageName}`);
|
|
30
|
-
}
|
|
31
|
-
const packageJSONStr = fs.readFileSync(packageJSONFilePath, "utf8");
|
|
32
|
-
const packageJSON = JSON.parse(packageJSONStr);
|
|
33
|
-
return packageJSON;
|
|
34
|
-
}
|
|
35
|
-
async function createMcpClient(mcpServerConfig, transport) {
|
|
36
|
-
const { packageName, name } = mcpServerConfig;
|
|
37
|
-
const client = new Client({
|
|
38
|
-
name: `mcp-server-${name}-client`,
|
|
39
|
-
version: "1.0.0",
|
|
40
|
-
}, {
|
|
41
|
-
capabilities: {
|
|
42
|
-
tools: {},
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
await client.connect(transport);
|
|
46
|
-
const closeConnection = async () => {
|
|
47
|
-
try {
|
|
48
|
-
await client.close();
|
|
49
|
-
}
|
|
50
|
-
catch (e) {
|
|
51
|
-
console.warn(`${packageName} mcp client close failure.`, e);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
return { client, transport, closeConnection };
|
|
55
|
-
}
|
|
56
|
-
async function getNodeMcpClient(mcpServerConfig, env) {
|
|
57
|
-
const { packageName } = mcpServerConfig;
|
|
58
|
-
const packageJSON = getPackageJSON(packageName);
|
|
59
|
-
let binFilePath = "";
|
|
60
|
-
let binPath;
|
|
61
|
-
if (typeof packageJSON.bin === "string") {
|
|
62
|
-
binPath = packageJSON.bin;
|
|
63
|
-
}
|
|
64
|
-
else if (typeof packageJSON.bin === "object") {
|
|
65
|
-
binPath = Object.values(packageJSON.bin)[0];
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
binPath = packageJSON.main;
|
|
69
|
-
}
|
|
70
|
-
assert(binPath, `Package ${packageName} does not have a valid bin path in package.json.`);
|
|
71
|
-
binFilePath = `${__dirname}/../node_modules/${packageName}/${binPath}`;
|
|
72
|
-
const mcpServerBinPath = mcpServerConfig.bin || binFilePath;
|
|
73
|
-
const binArgs = mcpServerConfig.binArgs || [];
|
|
74
|
-
const transport = new StdioClientTransport({
|
|
75
|
-
args: [mcpServerBinPath, ...binArgs],
|
|
76
|
-
command: process.execPath,
|
|
77
|
-
env: env || {},
|
|
78
|
-
});
|
|
79
|
-
return createMcpClient(mcpServerConfig, transport);
|
|
80
|
-
}
|
|
81
|
-
async function getPyMcpClient(mcpServerConfig, env) {
|
|
82
|
-
const { packageName } = mcpServerConfig;
|
|
83
|
-
const pythonModuleName = packageName;
|
|
84
|
-
const transport = new StdioClientTransport({
|
|
85
|
-
command: "uv",
|
|
86
|
-
args: ["run", "--directory", "./python-mcp", pythonModuleName],
|
|
87
|
-
env: Object.assign(Object.assign({}, Object.fromEntries(Object.entries(process.env).filter(([_, v]) => v !== undefined))), env),
|
|
88
|
-
});
|
|
89
|
-
return createMcpClient(mcpServerConfig, transport);
|
|
90
|
-
}
|
|
91
|
-
export async function getMcpClient(mcpServerConfig, env) {
|
|
92
|
-
const { runtime } = mcpServerConfig;
|
|
93
|
-
if (runtime === "python") {
|
|
94
|
-
return getPyMcpClient(mcpServerConfig, env);
|
|
95
|
-
}
|
|
96
|
-
return getNodeMcpClient(mcpServerConfig, env);
|
|
97
|
-
}
|
|
98
|
-
export function updatePackageJsonDependencies({ packageDeps, enableValidation = false, }) {
|
|
99
|
-
var _a;
|
|
100
|
-
// Write package.json dependencies
|
|
101
|
-
const packageJsonFile = "./package.json";
|
|
102
|
-
const packageJSONStr = fs.readFileSync(packageJsonFile, "utf-8");
|
|
103
|
-
const newDeps = {
|
|
104
|
-
"@e2b/code-interpreter": "^2.0.0",
|
|
105
|
-
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
106
|
-
"@hono/node-server": "1.15.0",
|
|
107
|
-
"@hono/swagger-ui": "^0.5.2",
|
|
108
|
-
"@hono/zod-openapi": "^0.16.4",
|
|
109
|
-
"@iarna/toml": "^2.2.5",
|
|
110
|
-
meilisearch: "^0.33.0",
|
|
111
|
-
lodash: "^4.17.21",
|
|
112
|
-
zod: "^3.23.30",
|
|
113
|
-
axios: "^1.9.0",
|
|
114
|
-
hono: "4.8.3",
|
|
115
|
-
semver: "^7.5.4",
|
|
116
|
-
};
|
|
117
|
-
for (const [depName, depVer] of Object.entries(packageDeps)) {
|
|
118
|
-
if (!enableValidation || ((_a = typedAllPackagesList[depName]) === null || _a === void 0 ? void 0 : _a.validated)) {
|
|
119
|
-
newDeps[depName] = depVer || "latest";
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// const blacklistDeps = new Set([
|
|
123
|
-
// "@mcp-server/google-search-mcp",
|
|
124
|
-
// "@executeautomation/playwright-mcp-server",
|
|
125
|
-
// ]);
|
|
126
|
-
// for (const dep of blacklistDeps) {
|
|
127
|
-
// if (newDeps[dep]) {
|
|
128
|
-
// delete newDeps[dep];
|
|
129
|
-
// }
|
|
130
|
-
// }
|
|
131
|
-
const packageJSON = JSON.parse(packageJSONStr);
|
|
132
|
-
packageJSON.dependencies = newDeps;
|
|
133
|
-
fs.writeFileSync(packageJsonFile, JSON.stringify(packageJSON, null, 2), "utf-8");
|
|
134
|
-
console.log(`Generated new package.json file at ${packageJsonFile}`);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
export function getActualVersion(packageName, configuredVersion) {
|
|
138
|
-
if (configuredVersion && configuredVersion !== "latest") {
|
|
139
|
-
return configuredVersion;
|
|
140
|
-
}
|
|
141
|
-
try {
|
|
142
|
-
const packageJsonPath = path.join(__dirname, "../node_modules", packageName, "package.json");
|
|
143
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
144
|
-
return packageJson.version;
|
|
145
|
-
}
|
|
146
|
-
catch (e) {
|
|
147
|
-
console.warn(`Failed to read version for ${packageName}, using 'latest' by default`, e.message);
|
|
148
|
-
return "latest";
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
export function withTimeout(ms, promise) {
|
|
152
|
-
return new Promise((resolve, reject) => {
|
|
153
|
-
const timer = setTimeout(() => {
|
|
154
|
-
reject(new Error(`Operation timed out after ${ms}ms`));
|
|
155
|
-
}, ms);
|
|
156
|
-
promise.then((res) => {
|
|
157
|
-
clearTimeout(timer);
|
|
158
|
-
resolve(res);
|
|
159
|
-
}, (err) => {
|
|
160
|
-
clearTimeout(timer);
|
|
161
|
-
reject(err);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
function checkDependencyValidity(dependencyData, versionRange) {
|
|
166
|
-
// 兼容 "latest" 的情况
|
|
167
|
-
if (versionRange === "latest") {
|
|
168
|
-
return Object.keys(dependencyData.versions).length > 0;
|
|
169
|
-
}
|
|
170
|
-
// 使用 semver 检查是否有满足版本范围的有效版本
|
|
171
|
-
const versions = Object.keys(dependencyData.versions);
|
|
172
|
-
for (const version of versions) {
|
|
173
|
-
if (semver.satisfies(version, versionRange)) {
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
async function checkDependencies(dependencies) {
|
|
180
|
-
const dependencyCache = {};
|
|
181
|
-
const checkSingleDependency = async (depName, depVersionRange) => {
|
|
182
|
-
const cacheKey = `${depName}@${depVersionRange}`;
|
|
183
|
-
if (dependencyCache[cacheKey] !== undefined) {
|
|
184
|
-
return dependencyCache[cacheKey];
|
|
185
|
-
}
|
|
186
|
-
try {
|
|
187
|
-
const depResponse = await axios.get(`https://registry.npmjs.org/${depName}`, {
|
|
188
|
-
timeout: 5000,
|
|
189
|
-
headers: {
|
|
190
|
-
"User-Agent": "MyToolManager/1.0",
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
if (depResponse.status !== 200 || !depResponse.data.versions) {
|
|
194
|
-
console.error(`Failed to fetch ${depName}`);
|
|
195
|
-
dependencyCache[cacheKey] = false;
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
const isValid = checkDependencyValidity(depResponse.data, depVersionRange);
|
|
199
|
-
dependencyCache[cacheKey] = isValid;
|
|
200
|
-
if (!isValid) {
|
|
201
|
-
console.error(`Invalid or missing: ${depName}`);
|
|
202
|
-
}
|
|
203
|
-
return isValid;
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
console.error(`Error fetching ${depName}: ${error.message}`);
|
|
207
|
-
dependencyCache[cacheKey] = false;
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
const promises = Object.entries(dependencies).map(([depName, depVersionRange]) => checkSingleDependency(depName, depVersionRange));
|
|
212
|
-
const results = await Promise.all(promises);
|
|
213
|
-
return results.every((result) => result);
|
|
214
|
-
}
|
|
215
|
-
export async function isValidNpmPackage(packageName) {
|
|
216
|
-
var _a, _b, _c, _d;
|
|
217
|
-
try {
|
|
218
|
-
// 检查主包是否存在
|
|
219
|
-
console.log("checking package:", packageName);
|
|
220
|
-
const response = await axios.get(`https://registry.npmjs.org/${packageName}`, {
|
|
221
|
-
timeout: 5000,
|
|
222
|
-
headers: {
|
|
223
|
-
"User-Agent": "MyToolManager/1.0",
|
|
224
|
-
},
|
|
225
|
-
});
|
|
226
|
-
// 检查主包是否被标记为 unpublished
|
|
227
|
-
if (response.status !== 200 || !((_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a["dist-tags"]) === null || _b === void 0 ? void 0 : _b.latest)) {
|
|
228
|
-
console.error(`Package marked as unpublished: ${packageName}`);
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
// 获取主包的最新版本信息
|
|
232
|
-
const latestVersion = response.data["dist-tags"].latest;
|
|
233
|
-
const versionData = (_d = (_c = response.data) === null || _c === void 0 ? void 0 : _c.versions) === null || _d === void 0 ? void 0 : _d[latestVersion];
|
|
234
|
-
if (!versionData) {
|
|
235
|
-
console.error(`Invalid package: ${packageName} - No version data found`);
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
// 检查 dependencies 和 devDependencies
|
|
239
|
-
console.log(`Checking dependencies for ${packageName}`);
|
|
240
|
-
const dependencies = Object.assign(Object.assign({}, versionData.dependencies), versionData.devDependencies);
|
|
241
|
-
if (!(await checkDependencies(dependencies))) {
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
console.log(`Valid package: ${packageName}`);
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
catch (error) {
|
|
248
|
-
console.error(`Error validating package ${packageName}:`, error.message);
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Parses the pyproject.toml file and returns its content
|
|
254
|
-
* @returns Parsed pyproject.toml content
|
|
255
|
-
*/
|
|
256
|
-
export function parsePyprojectToml() {
|
|
257
|
-
const pyprojectPath = "./python-mcp/pyproject.toml";
|
|
258
|
-
const content = fs.readFileSync(pyprojectPath, "utf-8");
|
|
259
|
-
return toml.parse(content);
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Extracts package name from a dependency string
|
|
263
|
-
* @param dep - Dependency string (e.g., "package>=1.0.0")
|
|
264
|
-
* @returns Package name without version constraints
|
|
265
|
-
*/
|
|
266
|
-
export function extractPackageName(dep) {
|
|
267
|
-
return dep.split(/[=<>!]/)[0].trim();
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Gets Python dependencies from pyproject.toml
|
|
271
|
-
* @returns Array of Python dependency names
|
|
272
|
-
*/
|
|
273
|
-
export function getPythonDependencies() {
|
|
274
|
-
var _a;
|
|
275
|
-
const data = parsePyprojectToml();
|
|
276
|
-
const deps = ((_a = data.project) === null || _a === void 0 ? void 0 : _a.dependencies) || [];
|
|
277
|
-
return deps.map(extractPackageName);
|
|
278
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
export declare class MCPSandboxClient {
|
|
3
|
-
private sandbox;
|
|
4
|
-
private initializing;
|
|
5
|
-
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);
|
|
18
|
-
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
|
-
kill(): Promise<void>;
|
|
30
|
-
clearPackageCache(packageKey: string): void;
|
|
31
|
-
clearAllCache(): void;
|
|
32
|
-
listTools(packageKey: string): Promise<Tool[]>;
|
|
33
|
-
executeTool(packageKey: string, toolName: string, argumentsObj: Record<string, unknown>, envs?: Record<string, string>): Promise<unknown>;
|
|
34
|
-
private runCodeWithTimeout;
|
|
35
|
-
private generateMCPTestCode;
|
|
36
|
-
private generateEnvVariables;
|
|
37
|
-
}
|