/** * Child MCP Manager * * Spawns child MCP processes, connects via stdio transport, * discovers their tools, and manages their full lifecycle. * * This is the core engine for the Evolving Hub — it bridges * between the Bhived MCP server and any number of child * MCP servers running as subprocesses. */ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { type ChildMcpTool } from "../registries/childMcpRegistry.js"; import type { McpConfig, McpPayload } from "../client/types.js"; export interface SpawnResult { /** Name of the spawned MCP */ name: string; /** Tools discovered from the child */ tools: ChildMcpTool[]; /** The MCP Client instance */ client: Client; } export interface SpawnOptions { /** Where this child came from: "standalone" or "skill:{name}" */ source: `skill:${string}` | "standalone"; /** Memory ID from the backend (for tracking) */ memory_id: string; /** Connection timeout in milliseconds (default: 15000) */ connectTimeout?: number; } export declare class ChildMcpManager { private healthInterval; private healthCheckRunning; private readonly stopping; /** * Spawn a child MCP process, connect to it, and discover its tools. * * Flow: * 1. Create StdioClientTransport (which spawns the child process) * 2. Create MCP Client and connect via the transport * 3. client.listTools() to discover available tools * 4. Register in ChildMcpRegistry * 5. Set up crash handler * 6. Return discovered tools */ spawn(mcpConfig: McpConfig | McpPayload, options: SpawnOptions): Promise; /** * Stop a child MCP process gracefully. * * Flow: * 1. Close the MCP client (sends SIGTERM via transport) * 2. Force kill only if close fails or times out * 3. Remove from registry */ stop(mcpName: string): Promise; /** * Forward a tool call to a child MCP. */ callTool(mcpName: string, toolName: string, params?: Record): Promise; /** * Start a periodic health monitor that pings each child MCP. * On failure, marks the child as crashed and clears its tools. */ startHealthMonitor(): void; /** * Run a one-time health check for all registered child MCPs. */ checkHealthNow(): Promise; /** * Stop the health monitor. */ stopHealthMonitor(): void; /** * Gracefully cleanup all child MCP processes. * Called during process exit / SIGINT / SIGTERM. */ cleanupAll(): Promise; /** * Stop all child MCPs that belong to a specific skill. */ stopBySkill(skillName: string): Promise; private stopUnhealthy; /** * Extract the child process from the StdioClientTransport. * * The SDK stores the child process as `_process` (private). After * connection succeeds, the process is alive. On close/crash, the * SDK sets `_process = undefined`, so we must extract it while * the transport is connected. * * We also check for the `pid` getter (public API since SDK v1.x) * to avoid relying solely on private internals. */ private extractChildProcess; /** * Set up a crash handler on the child process. * When the process exits unexpectedly, mark it as crashed. */ private setupCrashHandler; /** * Validate that the command binary exists on the system. * Throws with an actionable error message if not found. */ private validateCommand; /** * Build contextual error hints based on stderr output and the MCP config. * Helps agents understand what went wrong and what to try. */ private buildErrorHints; private normalizeTools; private killProcess; /** * Race a promise against a timeout, properly cleaning up the timer. * Unlike bare Promise.race with setTimeout, this avoids timer leaks. */ private raceWithTimeout; } /** Singleton ChildMcpManager instance */ export declare const childMcpManager: ChildMcpManager; //# sourceMappingURL=manager.d.ts.map