/** * V3 CLI MCP Server Management * * Provides server lifecycle management for MCP integration: * - Start/stop/status methods with process management * - Health check endpoint integration * - Graceful shutdown handling * - PID file management for daemon detection * - Event-based status monitoring * * Performance Targets: * - Server startup: <400ms * - Health check: <10ms * - Graceful shutdown: <5s * * @module @claude-flow/cli/mcp-server * @version 3.0.0 */ import { EventEmitter } from 'events'; /** * MCP Server configuration */ export interface MCPServerOptions { transport?: 'stdio' | 'http' | 'websocket'; host?: string; port?: number; pidFile?: string; logFile?: string; tools?: string[] | 'all'; daemonize?: boolean; timeout?: number; requestTimeoutMs?: number; } /** * MCP Server status */ export interface MCPServerStatus { running: boolean; pid?: number; transport?: string; host?: string; port?: number; uptime?: number; tools?: number; startedAt?: string; health?: { healthy: boolean; error?: string; metrics?: Record; }; } export declare function parseMcpToolSelection(value: string | undefined): string[] | 'all'; /** * Apply the existing `--tools` contract to advertised schemas. A selector can * be an exact tool name, a category, or a namespace prefix (`memory` matches * `memory_store`). Execution remains registered internally; only the fixed * per-request schema catalogue is reduced. */ export declare function filterAdvertisedMcpTools(tools: T[], selection: string[] | 'all'): T[]; export interface McpSchemaOverhead { toolCount: number; bytes: number; estimatedTokens: number; contextWindowTokens?: number; ratio?: number; risk: 'normal' | 'high'; } /** Conservative JSON-size estimate for the fixed tools/list catalogue. */ export declare function assessMcpSchemaOverhead(tools: Array<{ name: string; description?: string; inputSchema?: unknown; }>, contextWindowTokens?: number): McpSchemaOverhead; /** * MCP Server Manager * * Manages the lifecycle of the MCP server process */ export declare class MCPServerManager extends EventEmitter { private options; private process?; private server?; private startTime?; private healthCheckInterval?; private mcpServers; /** * This manager's own lifecycle (#3364). A stdio server keeps no PID record, * so nothing on disk can answer "is this manager running?" — only the * manager can. `idle` is a manager that has never started, and only there * does the #2934 fallback in getStatus() ("assume a client-launched stdio * server") apply; `stopped` is a handle on a server that is gone, and it * says so rather than reporting whatever PID the shared file happens to hold. */ private lifecycle; /** * The exact bytes this manager wrote to the PID file, while they are still * there (#3364). stop() retracts the record only while it is byte for byte * the one we wrote: the slot may have changed hands in between. */ private ownedRecord; constructor(options?: MCPServerOptions); /** * Start the MCP server */ start(): Promise; /** * Stop the MCP server */ stop(force?: boolean): Promise; /** * Get server status */ getStatus(): Promise; /** * Check server health */ checkHealth(): Promise<{ healthy: boolean; error?: string; metrics?: Record; }>; /** * Restart the server */ restart(): Promise; /** * Start stdio server in-process * Handles stdin/stdout directly like V2 implementation */ private startStdioServer; /** * Handle incoming MCP message */ private handleMCPMessage; /** * Start HTTP server in-process */ private startHttpServer; /** * Wait for server to be ready */ private waitForReady; /** * Wait for process to exit */ private waitForExit; /** * Start health monitoring */ private startHealthMonitoring; /** * Write the PID record. * * Line 1 is the bare PID, byte for byte what this file has always held, so * every existing reader keeps working: an older ruflo's * `parseInt(content.trim(), 10)` stops at the newline, and * `v3/scripts/start-mcp.sh` reads the first line. Line 2 is the durable * identity of the instance that wrote it (#3364). Returns the bytes written, * which stop() uses to retract only its own record. */ private writePidFile; /** * Read the PID record. * * A bare-integer file — an older ruflo, `start-mcp.sh --daemon`, or a * hand-written one — parses to a record with no identity, which keeps * exactly the old behaviour: the PID is checked for liveness and nothing * more. An identity line is only believed for the PID it names. */ private readPidRecord; /** * Is the recorded server still the instance the record names? (#3364) * * `kill -0`, and isProcessRunning()'s process-name check on top of it, only * answer "something with this number is alive". Durable identity answers * "it is still the one we wrote down": * - another host, OS, kernel boot or PID namespace issues its own PIDs, so * the number says nothing here. On Linux this is the ordinary stale case, * because /tmp commonly survives a reboot; * - within one boot the OS reuses a PID once the process is reaped, and the * owner's start time is what tells the two apart. * Where the start time cannot be read — Windows — the answer falls back to * isProcessRunning(), i.e. exactly the evidence used today. */ private recordedServerIsLive; /** * Remove PID file. With `ownedRecord`, only while the file still holds * exactly those bytes: the slot may have changed hands (#3364). */ private removePidFile; /** * Check if process is running AND is a node/claude-flow process. * Plain `kill -0` returns true for any process with the same owner, * which causes false positives when the OS recycles the PID. */ private isProcessRunning; /** * Make HTTP request */ private httpRequest; /** * Sleep utility */ private sleep; } /** * Create MCP server manager */ export declare function createMCPServerManager(options?: MCPServerOptions): MCPServerManager; /** * Get or create server manager singleton * * FIX for issue #942: Recreate singleton if transport type changes * Previously, once created with stdio (default), HTTP options were ignored */ export declare function getServerManager(options?: MCPServerOptions): MCPServerManager; /** * Quick start MCP server */ export declare function startMCPServer(options?: MCPServerOptions): Promise; /** * Quick stop MCP server */ export declare function stopMCPServer(force?: boolean): Promise; /** * Get MCP server status */ export declare function getMCPServerStatus(): Promise; export default MCPServerManager; //# sourceMappingURL=mcp-server.d.ts.map