Skip to main content
Glama
CodeSandbox.ts5.67 kB
/** * Code Sandbox - Secure execution of TypeScript code * * Uses Node.js built-in VM module for isolation. * Note: This is less secure than isolated-vm but doesn't require native compilation. * For production, consider using Deno or isolated-vm with an older Node version. */ import vm from "vm"; import ts from "typescript"; import type { ExecutionOptions, ExecutionResult } from "../types/index.js"; import type { MCPOrchestrator } from "../orchestrator/MCPOrchestrator.js"; import { logDebug, logError } from "../utils/logger.js"; export class CodeSandbox { constructor(private orchestrator: MCPOrchestrator) {} /** * Execute TypeScript code in a sandbox */ async execute( code: string, options: ExecutionOptions = {}, ): Promise<ExecutionResult> { const startTime = Date.now(); const timeout = options.timeout || 30000; // 30 seconds default const logs: string[] = []; let result: any = undefined; let error: string | undefined = undefined; try { // Compile TypeScript to JavaScript const jsCode = this.compileTypeScript(code); // Create sandbox context const sandbox = this.createSandbox(logs); // Create VM context const context = vm.createContext(sandbox); // Execute code (Note: timeout not directly supported in runInContext) const script = new vm.Script(jsCode, { filename: "sandbox.js", }); // Wrap in promise for timeout result = await Promise.race([ script.runInContext(context, { breakOnSigint: true, }), new Promise((_, reject) => setTimeout(() => reject(new Error("Execution timeout")), timeout), ), ]); logDebug("Code execution successful", { executionTime: Date.now() - startTime, logCount: logs.length, }); } catch (err) { error = err instanceof Error ? err.message : String(err); logError("Code execution failed", { error }); } return { logs, result, error, executionTime: Date.now() - startTime, }; } /** * Compile TypeScript to JavaScript */ private compileTypeScript(code: string): string { try { // Use TypeScript's transpileModule for simple compilation const result = ts.transpileModule(code, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, removeComments: false, }, }); return result.outputText; } catch (error) { throw new Error( `TypeScript compilation failed: ${ error instanceof Error ? error.message : String(error) }`, ); } } /** * Create sandbox environment */ private createSandbox(logs: string[]): any { // Captured console const capturedConsole = { log: (...args: any[]) => { const message = args .map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg), ) .join(" "); logs.push(message); }, error: (...args: any[]) => { const message = "[ERROR] " + args .map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg), ) .join(" "); logs.push(message); }, warn: (...args: any[]) => { const message = "[WARN] " + args .map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg), ) .join(" "); logs.push(message); }, info: (...args: any[]) => { const message = "[INFO] " + args .map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg), ) .join(" "); logs.push(message); }, debug: (...args: any[]) => { const message = "[DEBUG] " + args .map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg), ) .join(" "); logs.push(message); }, }; // MCP call binding const __mcp_call = async (toolName: string, args: any): Promise<any> => { logDebug("Sandbox calling MCP tool", { toolName, args }); return this.orchestrator.callTool(toolName, args); }; // Sandbox environment // IMPORTANT: This is minimal isolation. For production, use isolated-vm or Deno. const sandbox = { console: capturedConsole, __mcp_call, // Provide minimal globals Promise, Object, Array, String, Number, Boolean, Date, JSON, Math, parseInt, parseFloat, isNaN, isFinite, // Block dangerous globals require: undefined, process: undefined, global: undefined, globalThis: undefined, Buffer: undefined, setTimeout: undefined, setInterval: undefined, setImmediate: undefined, clearTimeout: undefined, clearInterval: undefined, clearImmediate: undefined, // NO network access fetch: undefined, XMLHttpRequest: undefined, WebSocket: undefined, // NO filesystem access fs: undefined, path: undefined, }; return sandbox; } /** * Reset sandbox state */ reset(): void { // Node.js VM doesn't need explicit reset logDebug("Sandbox reset"); } /** * Destroy sandbox */ destroy(): void { // Node.js VM doesn't need explicit cleanup logDebug("Sandbox destroyed"); } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/blas0/code2mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server