@justanothermldude/mcp-exec 0.1.0

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 (78) hide show
  1. package/README.md +344 -0
  2. package/dist/bridge/index.d.ts +3 -0
  3. package/dist/bridge/index.d.ts.map +1 -0
  4. package/dist/bridge/index.js +3 -0
  5. package/dist/bridge/index.js.map +1 -0
  6. package/dist/bridge/server.d.ts +84 -0
  7. package/dist/bridge/server.d.ts.map +1 -0
  8. package/dist/bridge/server.js +352 -0
  9. package/dist/bridge/server.js.map +1 -0
  10. package/dist/codegen/index.d.ts +6 -0
  11. package/dist/codegen/index.d.ts.map +1 -0
  12. package/dist/codegen/index.js +6 -0
  13. package/dist/codegen/index.js.map +1 -0
  14. package/dist/codegen/module-resolver.d.ts +95 -0
  15. package/dist/codegen/module-resolver.d.ts.map +1 -0
  16. package/dist/codegen/module-resolver.js +152 -0
  17. package/dist/codegen/module-resolver.js.map +1 -0
  18. package/dist/codegen/wrapper-generator.d.ts +22 -0
  19. package/dist/codegen/wrapper-generator.d.ts.map +1 -0
  20. package/dist/codegen/wrapper-generator.js +282 -0
  21. package/dist/codegen/wrapper-generator.js.map +1 -0
  22. package/dist/index.d.ts +27 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +123 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/sandbox/config.d.ts +37 -0
  27. package/dist/sandbox/config.d.ts.map +1 -0
  28. package/dist/sandbox/config.js +36 -0
  29. package/dist/sandbox/config.js.map +1 -0
  30. package/dist/sandbox/executor.d.ts +63 -0
  31. package/dist/sandbox/executor.d.ts.map +1 -0
  32. package/dist/sandbox/executor.js +240 -0
  33. package/dist/sandbox/executor.js.map +1 -0
  34. package/dist/sandbox/index.d.ts +8 -0
  35. package/dist/sandbox/index.d.ts.map +1 -0
  36. package/dist/sandbox/index.js +9 -0
  37. package/dist/sandbox/index.js.map +1 -0
  38. package/dist/server.d.ts +110 -0
  39. package/dist/server.d.ts.map +1 -0
  40. package/dist/server.js +150 -0
  41. package/dist/server.js.map +1 -0
  42. package/dist/tools/execute-batch.d.ts +111 -0
  43. package/dist/tools/execute-batch.d.ts.map +1 -0
  44. package/dist/tools/execute-batch.js +325 -0
  45. package/dist/tools/execute-batch.js.map +1 -0
  46. package/dist/tools/execute-code.d.ts +65 -0
  47. package/dist/tools/execute-code.d.ts.map +1 -0
  48. package/dist/tools/execute-code.js +141 -0
  49. package/dist/tools/execute-code.js.map +1 -0
  50. package/dist/tools/execute-with-context.d.ts +80 -0
  51. package/dist/tools/execute-with-context.d.ts.map +1 -0
  52. package/dist/tools/execute-with-context.js +223 -0
  53. package/dist/tools/execute-with-context.js.map +1 -0
  54. package/dist/tools/execute-with-wrappers.d.ts +69 -0
  55. package/dist/tools/execute-with-wrappers.d.ts.map +1 -0
  56. package/dist/tools/execute-with-wrappers.js +219 -0
  57. package/dist/tools/execute-with-wrappers.js.map +1 -0
  58. package/dist/tools/get-tool-schema.d.ts +59 -0
  59. package/dist/tools/get-tool-schema.d.ts.map +1 -0
  60. package/dist/tools/get-tool-schema.js +101 -0
  61. package/dist/tools/get-tool-schema.js.map +1 -0
  62. package/dist/tools/index.d.ts +10 -0
  63. package/dist/tools/index.d.ts.map +1 -0
  64. package/dist/tools/index.js +16 -0
  65. package/dist/tools/index.js.map +1 -0
  66. package/dist/tools/list-servers.d.ts +48 -0
  67. package/dist/tools/list-servers.d.ts.map +1 -0
  68. package/dist/tools/list-servers.js +85 -0
  69. package/dist/tools/list-servers.js.map +1 -0
  70. package/dist/types/execution.d.ts +25 -0
  71. package/dist/types/execution.d.ts.map +1 -0
  72. package/dist/types/execution.js +5 -0
  73. package/dist/types/execution.js.map +1 -0
  74. package/dist/types/index.d.ts +2 -0
  75. package/dist/types/index.d.ts.map +1 -0
  76. package/dist/types/index.js +3 -0
  77. package/dist/types/index.js.map +1 -0
  78. package/package.json +32 -0
package/README.md ADDED
@@ -0,0 +1,344 @@
1
+ # @meta-mcp/exec
2
+
3
+ MCP execution utilities for sandboxed TypeScript/JavaScript code execution with OS-level isolation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @meta-mcp/exec
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ This package provides secure code execution capabilities with:
14
+
15
+ - **Sandbox Isolation**: OS-level sandboxing via `@anthropic-ai/sandbox-runtime` (sandbox-exec on macOS, bubblewrap on Linux)
16
+ - **MCP Bridge**: HTTP bridge allowing sandboxed code to call MCP tools
17
+ - **Wrapper Generation**: Auto-generate type-safe TypeScript wrappers for MCP tools
18
+
19
+ ## Quick Start
20
+
21
+ ### Basic Code Execution
22
+
23
+ ```typescript
24
+ import { executeCode } from '@meta-mcp/exec';
25
+
26
+ const result = await executeCode({
27
+ code: 'console.log("Hello from sandbox!")',
28
+ timeout_ms: 5000,
29
+ });
30
+
31
+ console.log(result.output); // ['Hello from sandbox!']
32
+ console.log(result.durationMs); // execution time in ms
33
+ ```
34
+
35
+ ### Using as MCP Server
36
+
37
+ ```bash
38
+ # Start the mcp-exec server
39
+ npx @meta-mcp/exec
40
+
41
+ # Or with specific config
42
+ SERVERS_CONFIG=~/.meta-mcp/servers.json npx @meta-mcp/exec
43
+ ```
44
+
45
+ ## API Reference
46
+
47
+ ### executeCode
48
+
49
+ Execute code in a sandboxed environment.
50
+
51
+ ```typescript
52
+ import { executeCode } from '@meta-mcp/exec';
53
+
54
+ const result = await executeCode({
55
+ code: string; // TypeScript/JavaScript code to execute
56
+ timeout_ms?: number; // Max execution time (default: 30000)
57
+ });
58
+
59
+ // Result type
60
+ interface ExecutionResult {
61
+ output: string[]; // stdout lines
62
+ error?: string; // stderr content
63
+ durationMs: number; // execution time
64
+ }
65
+ ```
66
+
67
+ ### SandboxExecutor
68
+
69
+ Create a custom executor with specific configuration:
70
+
71
+ ```typescript
72
+ import { SandboxExecutor, createExecutor } from '@meta-mcp/exec';
73
+
74
+ // Using factory function
75
+ const executor = createExecutor({
76
+ mcpBridgePort: 4000,
77
+ additionalWritePaths: ['/tmp/my-app'],
78
+ enableLogMonitor: true,
79
+ });
80
+
81
+ // Using class directly
82
+ const executor = new SandboxExecutor({
83
+ mcpBridgePort: 4000,
84
+ additionalWritePaths: ['/tmp/my-app'],
85
+ });
86
+
87
+ // Execute code
88
+ const result = await executor.execute('console.log(1 + 1)', 5000);
89
+
90
+ // Check status
91
+ executor.checkDependencies(); // true if sandbox-runtime available
92
+ executor.isSandboxingEnabled(); // true if OS sandboxing active
93
+
94
+ // Update config
95
+ executor.updateConfig({ mcpBridgePort: 5000 });
96
+
97
+ // Clean up
98
+ await executor.reset();
99
+ ```
100
+
101
+ ### MCPBridge
102
+
103
+ HTTP bridge for MCP tool access from sandboxed code:
104
+
105
+ ```typescript
106
+ import { MCPBridge } from '@meta-mcp/exec';
107
+ import { ServerPool, createConnection, getServerConfig } from '@meta-mcp/core';
108
+
109
+ // Create server pool
110
+ const connectionFactory = async (serverId: string) => {
111
+ const config = getServerConfig(serverId);
112
+ if (!config) throw new Error(`Server not found: ${serverId}`);
113
+ return createConnection(config);
114
+ };
115
+ const pool = new ServerPool(connectionFactory);
116
+
117
+ // Create and start bridge
118
+ const bridge = new MCPBridge(pool, {
119
+ port: 3000,
120
+ host: '127.0.0.1',
121
+ });
122
+
123
+ await bridge.start();
124
+
125
+ // Bridge endpoints:
126
+ // GET /health - Health check
127
+ // POST /call - Execute MCP tool call
128
+
129
+ // Check status
130
+ bridge.isRunning(); // true
131
+ bridge.getPort(); // 3000
132
+ bridge.getHost(); // '127.0.0.1'
133
+
134
+ // Stop bridge
135
+ await bridge.stop();
136
+ ```
137
+
138
+ ### Wrapper Generator
139
+
140
+ Generate type-safe TypeScript wrappers for MCP tools:
141
+
142
+ ```typescript
143
+ import { generateToolWrapper, generateServerModule } from '@meta-mcp/exec';
144
+ import type { ToolDefinition } from '@meta-mcp/core';
145
+
146
+ // Generate wrapper for single tool
147
+ const tool: ToolDefinition = {
148
+ name: 'read_file',
149
+ description: 'Read contents of a file',
150
+ inputSchema: {
151
+ type: 'object',
152
+ properties: {
153
+ path: { type: 'string', description: 'File path to read' },
154
+ },
155
+ required: ['path'],
156
+ },
157
+ };
158
+
159
+ const wrapper = generateToolWrapper(tool, 'filesystem');
160
+ // Generates TypeScript function that calls bridge endpoint
161
+
162
+ // Generate module for all server tools
163
+ const tools: ToolDefinition[] = [/* ... */];
164
+ const module = generateServerModule(tools, 'filesystem');
165
+ // Generates complete TypeScript module with all tool wrappers
166
+ ```
167
+
168
+ **Generated wrapper example:**
169
+
170
+ ```typescript
171
+ export interface ReadFileInput {
172
+ /** File path to read */
173
+ path: string;
174
+ }
175
+
176
+ /**
177
+ * Read contents of a file
178
+ * @param input.path - File path to read
179
+ * @returns Promise resolving to tool result
180
+ */
181
+ export async function read_file(input: ReadFileInput): Promise<unknown> {
182
+ const response = await fetch('http://localhost:3000/call', {
183
+ method: 'POST',
184
+ headers: { 'Content-Type': 'application/json' },
185
+ body: JSON.stringify({
186
+ server_name: 'filesystem',
187
+ tool_name: 'read_file',
188
+ arguments: input,
189
+ }),
190
+ });
191
+
192
+ if (!response.ok) {
193
+ throw new Error(`Tool call failed: ${response.statusText}`);
194
+ }
195
+
196
+ return response.json();
197
+ }
198
+ ```
199
+
200
+ ### MCP Server
201
+
202
+ Create the mcp-exec MCP server programmatically:
203
+
204
+ ```typescript
205
+ import { createMcpExecServer } from '@meta-mcp/exec';
206
+ import { ServerPool, createConnection, getServerConfig } from '@meta-mcp/core';
207
+
208
+ // Create pool
209
+ const connectionFactory = async (serverId: string) => {
210
+ const config = getServerConfig(serverId);
211
+ if (!config) throw new Error(`Server not found: ${serverId}`);
212
+ return createConnection(config);
213
+ };
214
+ const pool = new ServerPool(connectionFactory);
215
+
216
+ // Create server
217
+ const { server, listToolsHandler, callToolHandler, shutdown } = createMcpExecServer(pool);
218
+
219
+ // List available tools
220
+ const tools = await listToolsHandler();
221
+ // => { tools: [{ name: 'execute_code', inputSchema: {...} }] }
222
+
223
+ // Call execute_code tool
224
+ const result = await callToolHandler({
225
+ name: 'execute_code',
226
+ arguments: {
227
+ code: 'console.log("Hello!")',
228
+ timeout_ms: 5000,
229
+ },
230
+ });
231
+
232
+ // Graceful shutdown
233
+ await shutdown();
234
+ ```
235
+
236
+ ## Types
237
+
238
+ ```typescript
239
+ import type {
240
+ ExecuteCodeInput,
241
+ ExecutionResult,
242
+ SandboxExecutorConfig,
243
+ MCPBridgeConfig,
244
+ CallRequest,
245
+ CallResponse,
246
+ } from '@meta-mcp/exec';
247
+
248
+ interface ExecuteCodeInput {
249
+ code: string;
250
+ timeout_ms?: number;
251
+ }
252
+
253
+ interface ExecutionResult {
254
+ output: string[];
255
+ error?: string;
256
+ durationMs: number;
257
+ }
258
+
259
+ interface SandboxExecutorConfig {
260
+ mcpBridgePort?: number;
261
+ additionalWritePaths?: string[];
262
+ enableLogMonitor?: boolean;
263
+ }
264
+
265
+ interface MCPBridgeConfig {
266
+ port?: number;
267
+ host?: string;
268
+ }
269
+
270
+ interface CallRequest {
271
+ server: string;
272
+ tool: string;
273
+ args?: Record<string, unknown>;
274
+ }
275
+
276
+ interface CallResponse {
277
+ success: boolean;
278
+ content?: unknown[];
279
+ isError?: boolean;
280
+ error?: string;
281
+ }
282
+ ```
283
+
284
+ ## CLI Usage
285
+
286
+ ```bash
287
+ # Start the MCP server
288
+ mcp-exec
289
+
290
+ # Show version
291
+ mcp-exec --version
292
+
293
+ # Show help
294
+ mcp-exec --help
295
+ ```
296
+
297
+ ## Using Wrappers in Sandboxed Code
298
+
299
+ When code runs in the sandbox, it can call MCP tools via the HTTP bridge:
300
+
301
+ ```typescript
302
+ // Code running inside sandbox
303
+ const result = await fetch('http://localhost:3000/call', {
304
+ method: 'POST',
305
+ headers: { 'Content-Type': 'application/json' },
306
+ body: JSON.stringify({
307
+ server: 'filesystem',
308
+ tool: 'read_file',
309
+ args: { path: '/tmp/test.txt' },
310
+ }),
311
+ });
312
+
313
+ const data = await result.json();
314
+ console.log(data.content[0].text);
315
+ ```
316
+
317
+ Or use generated wrappers:
318
+
319
+ ```typescript
320
+ // Import generated wrappers
321
+ import { read_file, write_file } from './filesystem-wrappers';
322
+
323
+ // Type-safe tool calls
324
+ const content = await read_file({ path: '/tmp/test.txt' });
325
+ await write_file({ path: '/tmp/output.txt', content: 'Hello!' });
326
+ ```
327
+
328
+ ## Security
329
+
330
+ - **Network Isolation**: Sandbox only allows connections to the local bridge (e.g., `localhost:3000`)
331
+ - **Filesystem Isolation**: Write access restricted to configured paths
332
+ - **Timeout Enforcement**: Code execution automatically terminated after timeout
333
+ - **OS-Level Sandboxing**: Uses `sandbox-exec` (macOS) or `bubblewrap` (Linux)
334
+
335
+ ## Environment Variables
336
+
337
+ | Variable | Default | Description |
338
+ |----------|---------|-------------|
339
+ | `SERVERS_CONFIG` | `~/.meta-mcp/servers.json` | Path to servers configuration |
340
+ | `MCP_DEFAULT_TIMEOUT` | none | Global timeout for MCP tool calls (ms) |
341
+
342
+ ## License
343
+
344
+ MIT
@@ -0,0 +1,3 @@
1
+ export { MCPBridge } from './server.js';
2
+ export type { CallRequest, CallResponse, MCPBridgeConfig } from './server.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ // MCP Bridge HTTP server exports
2
+ export { MCPBridge } from './server.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,84 @@
1
+ import type { ServerPool } from '@justanothermldude/meta-mcp-core';
2
+ /**
3
+ * Request body for the /call endpoint
4
+ */
5
+ export interface CallRequest {
6
+ /** Name of the MCP server to call */
7
+ server: string;
8
+ /** Name of the tool to invoke */
9
+ tool: string;
10
+ /** Arguments to pass to the tool */
11
+ args?: Record<string, unknown>;
12
+ }
13
+ /**
14
+ * Response from the /call endpoint
15
+ */
16
+ export interface CallResponse {
17
+ /** Whether the call was successful */
18
+ success: boolean;
19
+ /** Tool result content (when success is true) */
20
+ content?: unknown[];
21
+ /** Error message (when success is false) */
22
+ error?: string;
23
+ /** Whether the result indicates an error from the tool */
24
+ isError?: boolean;
25
+ }
26
+ /**
27
+ * Configuration options for MCPBridge
28
+ */
29
+ export interface MCPBridgeConfig {
30
+ /** Port to listen on (default: 3000) */
31
+ port?: number;
32
+ /** Host to bind to (default: '127.0.0.1') */
33
+ host?: string;
34
+ }
35
+ /**
36
+ * MCP Bridge HTTP server that allows sandboxed code to call
37
+ * MCP tools via HTTP requests to localhost.
38
+ */
39
+ export declare class MCPBridge {
40
+ private readonly pool;
41
+ private readonly port;
42
+ private readonly host;
43
+ private server;
44
+ constructor(pool: ServerPool, config?: MCPBridgeConfig);
45
+ /**
46
+ * Start the HTTP bridge server
47
+ * @returns Promise that resolves when server is listening
48
+ */
49
+ start(): Promise<void>;
50
+ /**
51
+ * Stop the HTTP bridge server
52
+ * @returns Promise that resolves when server is closed
53
+ */
54
+ stop(): Promise<void>;
55
+ /**
56
+ * Get the port the server is listening on
57
+ */
58
+ getPort(): number;
59
+ /**
60
+ * Get the host the server is bound to
61
+ */
62
+ getHost(): string;
63
+ /**
64
+ * Check if the server is running
65
+ */
66
+ isRunning(): boolean;
67
+ /**
68
+ * Handle incoming HTTP requests
69
+ */
70
+ private handleRequest;
71
+ /**
72
+ * Handle POST /call endpoint for tool invocation
73
+ */
74
+ private handleCallRequest;
75
+ /**
76
+ * Handle GET /health endpoint
77
+ */
78
+ private handleHealthRequest;
79
+ /**
80
+ * Send an error response
81
+ */
82
+ private sendError;
83
+ }
84
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,kCAAkC,CAAC;AAGlF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAwKD;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,MAAM,CAAuB;gBAEzB,IAAI,EAAE,UAAU,EAAE,MAAM,GAAE,eAAoB;IAM1D;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,OAAO,CAAC,aAAa;IAwBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+GzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,SAAS;CAQlB"}