UNPKG

jay-code

Version:

Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability

877 lines (771 loc) 26.3 kB
/** * MCP Integration with Jay-Code Orchestration System * Provides seamless integration between MCP servers and the broader orchestration components */ import { EventEmitter } from 'node:events'; import type { ILogger } from '../core/logger.js'; import { MCPConfig, MCPSession, MCPTool, SystemEvents } from '../utils/types.js'; import { MCPError } from '../utils/errors.js'; import { MCPServer, IMCPServer } from './server.js'; import { MCPLifecycleManager, LifecycleState } from './lifecycle-manager.js'; import { MCPPerformanceMonitor } from './performance-monitor.js'; import { MCPProtocolManager } from './protocol-manager.js'; export interface OrchestrationComponents { orchestrator?: any; swarmCoordinator?: any; agentManager?: any; resourceManager?: any; memoryManager?: any; messageBus?: any; monitor?: any; eventBus?: any; terminalManager?: any; } export interface MCPOrchestrationConfig { enabledIntegrations: { orchestrator: boolean; swarm: boolean; agents: boolean; resources: boolean; memory: boolean; monitoring: boolean; terminals: boolean; }; autoStart: boolean; healthCheckInterval: number; reconnectAttempts: number; reconnectDelay: number; enableMetrics: boolean; enableAlerts: boolean; } export interface IntegrationStatus { component: string; enabled: boolean; connected: boolean; healthy: boolean; lastCheck: Date; error?: string; metrics?: Record<string, number>; } /** * MCP Orchestration Integration Manager * Manages the integration between MCP servers and orchestration components */ export class MCPOrchestrationIntegration extends EventEmitter { private server?: IMCPServer; private lifecycleManager?: MCPLifecycleManager; private performanceMonitor?: MCPPerformanceMonitor; private protocolManager?: MCPProtocolManager; private integrationStatus = new Map<string, IntegrationStatus>(); private healthCheckTimer?: NodeJS.Timeout; private reconnectTimers = new Map<string, NodeJS.Timeout>(); private readonly defaultConfig: MCPOrchestrationConfig = { enabledIntegrations: { orchestrator: true, swarm: true, agents: true, resources: true, memory: true, monitoring: true, terminals: true, }, autoStart: true, healthCheckInterval: 30000, // 30 seconds reconnectAttempts: 3, reconnectDelay: 5000, // 5 seconds enableMetrics: true, enableAlerts: true, }; constructor( private mcpConfig: MCPConfig, private orchestrationConfig: MCPOrchestrationConfig, private components: OrchestrationComponents, private logger: ILogger, ) { super(); this.orchestrationConfig = { ...this.defaultConfig, ...orchestrationConfig }; this.initializeIntegration(); } /** * Start the MCP orchestration integration */ async start(): Promise<void> { this.logger.info('Starting MCP orchestration integration'); try { // Initialize protocol manager this.protocolManager = new MCPProtocolManager(this.logger); // Initialize performance monitor if (this.orchestrationConfig.enableMetrics) { this.performanceMonitor = new MCPPerformanceMonitor(this.logger); this.setupPerformanceMonitoring(); } // Create MCP server this.server = new MCPServer( this.mcpConfig, this.components.eventBus || new EventEmitter(), this.logger, this.components.orchestrator, this.components.swarmCoordinator, this.components.agentManager, this.components.resourceManager, this.components.messageBus, this.components.monitor, ); // Initialize lifecycle manager this.lifecycleManager = new MCPLifecycleManager( this.mcpConfig, this.logger, () => this.server!, ); // Setup lifecycle event handlers this.setupLifecycleHandlers(); // Register orchestration tools this.registerOrchestrationTools(); // Start the server if (this.orchestrationConfig.autoStart) { await this.lifecycleManager.start(); } // Start health monitoring this.startHealthMonitoring(); // Setup component integrations await this.setupComponentIntegrations(); this.logger.info('MCP orchestration integration started successfully'); this.emit('integrationStarted'); } catch (error) { this.logger.error('Failed to start MCP orchestration integration', error); throw error; } } /** * Stop the MCP orchestration integration */ async stop(): Promise<void> { this.logger.info('Stopping MCP orchestration integration'); try { // Stop health monitoring this.stopHealthMonitoring(); // Stop lifecycle manager if (this.lifecycleManager) { await this.lifecycleManager.stop(); } // Stop performance monitor if (this.performanceMonitor) { this.performanceMonitor.stop(); } // Clear reconnect timers for (const timer of this.reconnectTimers.values()) { clearTimeout(timer); } this.reconnectTimers.clear(); this.logger.info('MCP orchestration integration stopped'); this.emit('integrationStopped'); } catch (error) { this.logger.error('Error stopping MCP orchestration integration', error); throw error; } } /** * Get integration status for all components */ getIntegrationStatus(): IntegrationStatus[] { return Array.from(this.integrationStatus.values()); } /** * Get status for a specific component */ getComponentStatus(component: string): IntegrationStatus | undefined { return this.integrationStatus.get(component); } /** * Get MCP server instance */ getServer(): IMCPServer | undefined { return this.server; } /** * Get lifecycle manager */ getLifecycleManager(): MCPLifecycleManager | undefined { return this.lifecycleManager; } /** * Get performance monitor */ getPerformanceMonitor(): MCPPerformanceMonitor | undefined { return this.performanceMonitor; } /** * Get protocol manager */ getProtocolManager(): MCPProtocolManager | undefined { return this.protocolManager; } /** * Force reconnection to a component */ async reconnectComponent(component: string): Promise<void> { const status = this.integrationStatus.get(component); if (!status || !status.enabled) { throw new MCPError(`Component ${component} is not enabled`); } this.logger.info('Reconnecting to component', { component }); try { await this.connectComponent(component); this.logger.info('Successfully reconnected to component', { component }); } catch (error) { this.logger.error('Failed to reconnect to component', { component, error }); throw error; } } /** * Enable/disable component integration */ async setComponentEnabled(component: string, enabled: boolean): Promise<void> { const status = this.integrationStatus.get(component); if (!status) { throw new MCPError(`Unknown component: ${component}`); } status.enabled = enabled; if (enabled) { await this.connectComponent(component); } else { await this.disconnectComponent(component); } this.logger.info('Component integration updated', { component, enabled }); this.emit('componentToggled', { component, enabled }); } private initializeIntegration(): void { const components = [ 'orchestrator', 'swarm', 'agents', 'resources', 'memory', 'monitoring', 'terminals', ]; for (const component of components) { this.integrationStatus.set(component, { component, enabled: this.orchestrationConfig.enabledIntegrations[ component as keyof typeof this.orchestrationConfig.enabledIntegrations ], connected: false, healthy: false, lastCheck: new Date(), }); } } private setupLifecycleHandlers(): void { if (!this.lifecycleManager) return; this.lifecycleManager.on('stateChange', (event) => { this.logger.info('MCP server state changed', { from: event.previousState, to: event.state, error: event.error?.message, }); // Emit to orchestration event bus if (this.components.eventBus) { this.components.eventBus.emit(SystemEvents.SYSTEM_HEALTHCHECK, { status: event.state === LifecycleState.RUNNING ? 'healthy' : 'unhealthy', component: 'mcp-server', timestamp: event.timestamp, }); } this.emit('lifecycleStateChanged', event); }); } private setupPerformanceMonitoring(): void { if (!this.performanceMonitor) return; this.performanceMonitor.on('metricsCollected', (metrics) => { // Forward metrics to orchestration monitor if (this.components.monitor && typeof this.components.monitor.recordMetrics === 'function') { this.components.monitor.recordMetrics('mcp', metrics); } this.emit('metricsCollected', metrics); }); this.performanceMonitor.on('alertTriggered', (alert) => { this.logger.warn('MCP performance alert triggered', { alertId: alert.id, ruleName: alert.ruleName, severity: alert.severity, message: alert.message, }); // Forward to orchestration alert system if (this.orchestrationConfig.enableAlerts && this.components.monitor) { if (typeof this.components.monitor.sendAlert === 'function') { this.components.monitor.sendAlert({ source: 'mcp', severity: alert.severity, message: alert.message, metadata: alert, }); } } this.emit('performanceAlert', alert); }); this.performanceMonitor.on('optimizationSuggestion', (suggestion) => { this.logger.info('MCP optimization suggestion', { type: suggestion.type, priority: suggestion.priority, title: suggestion.title, }); this.emit('optimizationSuggestion', suggestion); }); } private registerOrchestrationTools(): void { if (!this.server) return; // Register orchestrator tools if (this.orchestrationConfig.enabledIntegrations.orchestrator && this.components.orchestrator) { this.registerOrchestratorTools(); } // Register swarm tools if (this.orchestrationConfig.enabledIntegrations.swarm && this.components.swarmCoordinator) { this.registerSwarmTools(); } // Register agent tools if (this.orchestrationConfig.enabledIntegrations.agents && this.components.agentManager) { this.registerAgentTools(); } // Register resource tools if (this.orchestrationConfig.enabledIntegrations.resources && this.components.resourceManager) { this.registerResourceTools(); } // Register memory tools if (this.orchestrationConfig.enabledIntegrations.memory && this.components.memoryManager) { this.registerMemoryTools(); } // Register monitoring tools if (this.orchestrationConfig.enabledIntegrations.monitoring && this.components.monitor) { this.registerMonitoringTools(); } // Register terminal tools if (this.orchestrationConfig.enabledIntegrations.terminals && this.components.terminalManager) { this.registerTerminalTools(); } } private registerOrchestratorTools(): void { const tools: MCPTool[] = [ { name: 'orchestrator/status', description: 'Get orchestrator status and metrics', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.orchestrator?.getStatus === 'function') { return await this.components.orchestrator.getStatus(); } throw new MCPError('Orchestrator status not available'); }, }, { name: 'orchestrator/tasks', description: 'List all tasks in the orchestrator', inputSchema: { type: 'object', properties: { status: { type: 'string', enum: ['pending', 'running', 'completed', 'failed'] }, limit: { type: 'number', minimum: 1, maximum: 100 }, }, }, handler: async (input: any) => { if (typeof this.components.orchestrator?.listTasks === 'function') { return await this.components.orchestrator.listTasks(input); } throw new MCPError('Orchestrator task listing not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private registerSwarmTools(): void { const tools: MCPTool[] = [ { name: 'swarm/status', description: 'Get swarm coordinator status', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.swarmCoordinator?.getStatus === 'function') { return await this.components.swarmCoordinator.getStatus(); } throw new MCPError('Swarm coordinator status not available'); }, }, { name: 'swarm/agents', description: 'List active swarm agents', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.swarmCoordinator?.listAgents === 'function') { return await this.components.swarmCoordinator.listAgents(); } throw new MCPError('Swarm agent listing not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private registerAgentTools(): void { const tools: MCPTool[] = [ { name: 'agents/list', description: 'List all managed agents', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.agentManager?.listAgents === 'function') { return await this.components.agentManager.listAgents(); } throw new MCPError('Agent listing not available'); }, }, { name: 'agents/spawn', description: 'Spawn a new agent', inputSchema: { type: 'object', properties: { profile: { type: 'object' }, config: { type: 'object' }, }, required: ['profile'], }, handler: async (input: any) => { if (typeof this.components.agentManager?.spawnAgent === 'function') { return await this.components.agentManager.spawnAgent(input.profile, input.config); } throw new MCPError('Agent spawning not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private registerResourceTools(): void { const tools: MCPTool[] = [ { name: 'resources/list', description: 'List available resources', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.resourceManager?.listResources === 'function') { return await this.components.resourceManager.listResources(); } throw new MCPError('Resource listing not available'); }, }, { name: 'resources/status', description: 'Get resource manager status', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.resourceManager?.getStatus === 'function') { return await this.components.resourceManager.getStatus(); } throw new MCPError('Resource manager status not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private registerMemoryTools(): void { const tools: MCPTool[] = [ { name: 'memory/query', description: 'Query memory bank', inputSchema: { type: 'object', properties: { query: { type: 'string' }, namespace: { type: 'string' }, limit: { type: 'number' }, }, required: ['query'], }, handler: async (input: any) => { if (typeof this.components.memoryManager?.query === 'function') { return await this.components.memoryManager.query(input); } throw new MCPError('Memory query not available'); }, }, { name: 'memory/store', description: 'Store data in memory bank', inputSchema: { type: 'object', properties: { data: { type: 'object' }, namespace: { type: 'string' }, tags: { type: 'array', items: { type: 'string' } }, }, required: ['data'], }, handler: async (input: any) => { if (typeof this.components.memoryManager?.store === 'function') { return await this.components.memoryManager.store(input); } throw new MCPError('Memory storage not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private registerMonitoringTools(): void { const tools: MCPTool[] = [ { name: 'monitoring/metrics', description: 'Get system monitoring metrics', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.monitor?.getMetrics === 'function') { return await this.components.monitor.getMetrics(); } throw new MCPError('Monitoring metrics not available'); }, }, { name: 'monitoring/alerts', description: 'List active alerts', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.monitor?.getAlerts === 'function') { return await this.components.monitor.getAlerts(); } throw new MCPError('Alert listing not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private registerTerminalTools(): void { const tools: MCPTool[] = [ { name: 'terminals/list', description: 'List active terminal sessions', inputSchema: { type: 'object', properties: {} }, handler: async () => { if (typeof this.components.terminalManager?.listSessions === 'function') { return await this.components.terminalManager.listSessions(); } throw new MCPError('Terminal session listing not available'); }, }, { name: 'terminals/execute', description: 'Execute command in terminal', inputSchema: { type: 'object', properties: { command: { type: 'string' }, sessionId: { type: 'string' }, }, required: ['command'], }, handler: async (input: any) => { if (typeof this.components.terminalManager?.execute === 'function') { return await this.components.terminalManager.execute(input.command, input.sessionId); } throw new MCPError('Terminal execution not available'); }, }, ]; for (const tool of tools) { this.server!.registerTool(tool); } } private async setupComponentIntegrations(): Promise<void> { const promises = []; for (const [component, status] of this.integrationStatus.entries()) { if (status.enabled) { promises.push(this.connectComponent(component)); } } await Promise.allSettled(promises); } private async connectComponent(component: string): Promise<void> { const status = this.integrationStatus.get(component); if (!status) return; try { // Component-specific connection logic switch (component) { case 'orchestrator': await this.connectOrchestrator(); break; case 'swarm': await this.connectSwarmCoordinator(); break; case 'agents': await this.connectAgentManager(); break; case 'resources': await this.connectResourceManager(); break; case 'memory': await this.connectMemoryManager(); break; case 'monitoring': await this.connectMonitor(); break; case 'terminals': await this.connectTerminalManager(); break; } status.connected = true; status.healthy = true; status.lastCheck = new Date(); status.error = undefined; this.logger.info('Component connected', { component }); this.emit('componentConnected', { component }); } catch (error) { status.connected = false; status.healthy = false; status.error = error instanceof Error ? error.message : 'Unknown error'; this.logger.error('Failed to connect component', { component, error }); this.scheduleReconnect(component); } } private async disconnectComponent(component: string): Promise<void> { const status = this.integrationStatus.get(component); if (!status) return; status.connected = false; status.healthy = false; status.lastCheck = new Date(); // Clear any reconnect timers const timer = this.reconnectTimers.get(component); if (timer) { clearTimeout(timer); this.reconnectTimers.delete(component); } this.logger.info('Component disconnected', { component }); this.emit('componentDisconnected', { component }); } private scheduleReconnect(component: string): void { const timer = this.reconnectTimers.get(component); if (timer) return; // Already scheduled const reconnectTimer = setTimeout(async () => { this.reconnectTimers.delete(component); try { await this.connectComponent(component); } catch (error) { // Will be handled by connectComponent } }, this.orchestrationConfig.reconnectDelay); this.reconnectTimers.set(component, reconnectTimer); } private startHealthMonitoring(): void { this.healthCheckTimer = setInterval(async () => { await this.performHealthChecks(); }, this.orchestrationConfig.healthCheckInterval); } private stopHealthMonitoring(): void { if (this.healthCheckTimer) { clearInterval(this.healthCheckTimer); this.healthCheckTimer = undefined; } } private async performHealthChecks(): Promise<void> { for (const [component, status] of this.integrationStatus.entries()) { if (!status.enabled || !status.connected) continue; try { const healthy = await this.checkComponentHealth(component); status.healthy = healthy; status.lastCheck = new Date(); status.error = undefined; } catch (error) { status.healthy = false; status.error = error instanceof Error ? error instanceof Error ? error.message : String(error) : 'Health check failed'; this.logger.warn('Component health check failed', { component, error }); } } } private async checkComponentHealth(component: string): Promise<boolean> { const componentInstance = this.getComponentInstance(component); if (!componentInstance) return false; // Check if component has health check method if (typeof componentInstance.healthCheck === 'function') { const result = await componentInstance.healthCheck(); return result === true || (typeof result === 'object' && result.healthy === true); } // Basic check - component exists and is not null return true; } private getComponentInstance(component: string): any { switch (component) { case 'orchestrator': return this.components.orchestrator; case 'swarm': return this.components.swarmCoordinator; case 'agents': return this.components.agentManager; case 'resources': return this.components.resourceManager; case 'memory': return this.components.memoryManager; case 'monitoring': return this.components.monitor; case 'terminals': return this.components.terminalManager; default: return null; } } // Component-specific connection methods private async connectOrchestrator(): Promise<void> { if (!this.components.orchestrator) { throw new MCPError('Orchestrator component not available'); } // Add orchestrator-specific connection logic here } private async connectSwarmCoordinator(): Promise<void> { if (!this.components.swarmCoordinator) { throw new MCPError('Swarm coordinator component not available'); } // Add swarm coordinator-specific connection logic here } private async connectAgentManager(): Promise<void> { if (!this.components.agentManager) { throw new MCPError('Agent manager component not available'); } // Add agent manager-specific connection logic here } private async connectResourceManager(): Promise<void> { if (!this.components.resourceManager) { throw new MCPError('Resource manager component not available'); } // Add resource manager-specific connection logic here } private async connectMemoryManager(): Promise<void> { if (!this.components.memoryManager) { throw new MCPError('Memory manager component not available'); } // Add memory manager-specific connection logic here } private async connectMonitor(): Promise<void> { if (!this.components.monitor) { throw new MCPError('Monitor component not available'); } // Add monitor-specific connection logic here } private async connectTerminalManager(): Promise<void> { if (!this.components.terminalManager) { throw new MCPError('Terminal manager component not available'); } // Add terminal manager-specific connection logic here } }