Skip to main content
Glama

MCPMan

by semistrict
runtime.ts4.17 kB
import vm from "node:vm"; import type { UpstreamServerManager } from "../mcp/upstream-server-manager.js"; import type { MacroManager } from "../mcp/macros.js"; import { createGlobalContext, createServerProxies, type ServerProxies } from "./proxy.js"; export class EvalRuntime { private vmContext: vm.Context | null = null; private macroManager: MacroManager | null = null; private serverProxies: ServerProxies = {}; constructor(private upstreamServerManager: UpstreamServerManager) {} setMacroManager(macroManager: MacroManager): void { this.macroManager = macroManager; } getServerProxy(serverName: string): unknown { return this.serverProxies[serverName]; } async eval(code: string, arg: unknown = {}): Promise<{ result: unknown; output: string }> { // Initialize VM context if not already created if (!this.vmContext) { await this.initializeContext(); } // Create output buffer for this eval call const output: string[] = []; // Update console methods to use this call's output buffer if (!this.vmContext) { throw new Error("VM context not initialized"); } this.vmContext.console = { log: (...args: unknown[]) => { output.push(`[LOG] ${args.map((arg) => String(arg)).join(" ")}`); }, error: (...args: unknown[]) => { output.push(`[ERROR] ${args.map((arg) => String(arg)).join(" ")}`); }, warn: (...args: unknown[]) => { output.push(`[WARN] ${args.map((arg) => String(arg)).join(" ")}`); }, info: (...args: unknown[]) => { output.push(`[INFO] ${args.map((arg) => String(arg)).join(" ")}`); }, }; // Run the code and capture the result // Treat code as a function expression and call it with the arg this.vmContext.__evalArg = arg; let result = await vm.runInContext( `(async () => { const fn = ${code}; return await fn(__evalArg); })()`, this.vmContext, { timeout: 30000, } ); // Clean up delete this.vmContext.__evalArg; // Auto-await if result is a promise if (result && typeof result === "object" && result !== null && "then" in result) { result = await (result as Promise<unknown>); } return { result, output: output.join("\n"), }; } async appendResult(result: unknown): Promise<number> { // Initialize VM context if not already created if (!this.vmContext) { await this.initializeContext(); } if (!this.vmContext) { throw new Error("VM context not initialized"); } // Access $results from vmContext and push the new result const results = this.vmContext.$results as unknown[]; results.push(result); return results.length - 1; } private async initializeContext(): Promise<void> { // Create proxies for all connected servers this.serverProxies = await createServerProxies(this.upstreamServerManager); const context = createGlobalContext( this.serverProxies, this.upstreamServerManager, this.macroManager, this ); // Create VM context with initial setup const vmContextData = { ...context, console: { // These will be overridden per eval call log: () => { // Placeholder - overridden per eval call }, error: () => { // Placeholder - overridden per eval call }, warn: () => { // Placeholder - overridden per eval call }, info: () => { // Placeholder - overridden per eval call }, }, // Add other globals that might be needed setTimeout, clearTimeout, setInterval, clearInterval, Promise, process: { env: process.env }, // Results array for invoke tool $results: [], }; this.vmContext = vm.createContext(vmContextData); } } // AsyncFunction constructor (available in modern JS environments) const _AsyncFunction = (async () => { // Intentionally empty async function for constructor access }).constructor as new ( ...args: string[] ) => (...args: unknown[]) => Promise<unknown>;

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/semistrict/mcpman'

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