UNPKG

@mrtkrcm/acp-claude-code

Version:

ACP (Agent Client Protocol) bridge for Claude Code

138 lines 5.74 kB
import { createLogger } from './logger.js'; export class McpConnectionManager { connections = new Map(); connectionStats = new Map(); connectionConfigs = new Map(); healthCheckInterval; logger; constructor() { this.logger = createLogger('MCP-Manager'); this.startHealthChecking(); } /** * Register an MCP server configuration for connection pooling */ async registerServer(config) { this.connectionConfigs.set(config.name, config); this.connectionStats.set(config.name, { totalCalls: 0, failedCalls: 0, avgResponseTime: 0, lastUsed: 0, isHealthy: true, }); // Initialize connection pool const poolSize = config.maxConnections || 3; const connections = []; for (let i = 0; i < poolSize; i++) { try { // Note: This would need to be implemented based on actual MCP SDK interfaces // const connection = await this.createConnection(config); // connections.push(connection); } catch (error) { this.logger.warn(`Failed to create MCP connection for ${config.name}: ${error}`); } } this.connections.set(config.name, connections); this.logger.info(`Registered MCP server: ${config.name} with ${connections.length} connections`); } /** * Execute MCP tool with connection pooling and retry logic */ async executeToolWithPooling(serverName, toolName, args, options = {}) { const connections = this.connections.get(serverName); const stats = this.connectionStats.get(serverName); if (!connections || connections.length === 0) { throw new Error(`No available connections for MCP server: ${serverName}`); } const startTime = Date.now(); const { timeout = 30000, retries = 2 } = options; let lastError = null; for (let attempt = 0; attempt <= retries; attempt++) { // Round-robin connection selection const connectionIndex = stats.totalCalls % connections.length; const connection = connections[connectionIndex]; try { stats.totalCalls++; stats.lastUsed = Date.now(); // Execute with timeout const result = await Promise.race([ this.executeWithConnection(connection, toolName, args), new Promise((_, reject) => setTimeout(() => reject(new Error('Tool execution timeout')), timeout)) ]); // Update performance stats const duration = Date.now() - startTime; stats.avgResponseTime = (stats.avgResponseTime + duration) / 2; return result; } catch (error) { lastError = error; stats.failedCalls++; if (attempt === retries) { this.logger.error(`MCP tool execution failed after ${retries + 1} attempts: ${lastError.message}`); } else { this.logger.warn(`MCP tool attempt ${attempt + 1} failed, retrying: ${lastError.message}`); await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1))); } } } throw lastError || new Error('Tool execution failed'); } async executeWithConnection(connection, toolName, args) { // This would need to be implemented based on actual MCP SDK interfaces // return await connection.callTool({ name: toolName, arguments: args }); throw new Error('Not implemented - requires actual MCP SDK integration'); } /** * Get connection statistics for monitoring */ getStats() { return Object.fromEntries(this.connectionStats.entries()); } /** * Health check all connections */ startHealthChecking() { this.healthCheckInterval = setInterval(async () => { for (const [serverName, connections] of this.connections.entries()) { const stats = this.connectionStats.get(serverName); if (!stats) continue; let healthyConnections = 0; for (const connection of connections) { try { // Implement health check based on actual MCP SDK // const isHealthy = await this.checkConnectionHealth(connection); const isHealthy = true; // Placeholder if (isHealthy) healthyConnections++; } catch (error) { this.logger.warn(`Health check failed for ${serverName}: ${error}`); } } stats.isHealthy = healthyConnections > 0; if (!stats.isHealthy) { this.logger.error(`MCP server ${serverName} is unhealthy`); } } }, 30000); // Check every 30 seconds } destroy() { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); } for (const connections of this.connections.values()) { for (const connection of connections) { // Close connections // await connection.close(); } } this.connections.clear(); this.connectionStats.clear(); } } export const globalMcpManager = new McpConnectionManager(); //# sourceMappingURL=mcp-connection-manager.js.map