UNPKG

claude-flow

Version:

Enterprise-grade AI agent orchestration with WASM-powered ReasoningBank memory and AgentDB vector database (always uses latest agentic-flow)

313 lines (265 loc) 7.89 kB
/** * SDK Integration Layer for In-Process MCP Server * * Provides seamless integration between Claude Code SDK and Claude-Flow's * in-process MCP server for 10-100x performance improvement. */ import { query, type Query, type Options } from '@anthropic-ai/claude-code/sdk'; import { createClaudeFlowSdkServer, ClaudeFlowToolRegistry } from './tool-registry.js'; import type { McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-code/sdk.d.ts'; import { logger } from '../core/logger.js'; export interface SDKIntegrationConfig { enableInProcess: boolean; enableMetrics: boolean; enableCaching: boolean; orchestratorContext?: any; fallbackToStdio?: boolean; } /** * SDK Integration Manager * Manages in-process MCP server and SDK query integration */ export class SDKIntegration { private sdkServer?: McpSdkServerConfigWithInstance; private registry?: ClaudeFlowToolRegistry; private config: SDKIntegrationConfig; constructor(config: SDKIntegrationConfig) { this.config = { fallbackToStdio: true, ...config, }; logger.info('SDKIntegration initialized', { enableInProcess: config.enableInProcess, enableMetrics: config.enableMetrics, }); } /** * Initialize SDK integration with in-process server */ async initialize(): Promise<void> { if (!this.config.enableInProcess) { logger.info('In-process MCP server disabled, using stdio fallback'); return; } logger.info('Initializing in-process MCP server...'); try { // Create SDK server with all Claude-Flow tools this.sdkServer = await createClaudeFlowSdkServer(this.config.orchestratorContext); logger.info('In-process MCP server initialized successfully', { serverName: this.sdkServer.name, transport: 'in-process', }); } catch (error) { logger.error('Failed to initialize in-process MCP server', { error }); if (!this.config.fallbackToStdio) { throw error; } logger.warn('Falling back to stdio transport'); } } /** * Create SDK query with in-process MCP server */ query(prompt: string, options?: Partial<Options>): Query { const queryOptions: Options = { ...options, }; // Add in-process MCP server if available if (this.sdkServer) { queryOptions.mcpServers = { ...queryOptions.mcpServers, 'claude-flow': this.sdkServer, }; logger.debug('Query created with in-process MCP server', { mcpServers: Object.keys(queryOptions.mcpServers || {}), }); } else { logger.debug('Query created without in-process server (fallback mode)'); } return query({ prompt, options: queryOptions }); } /** * Create SDK query for agent with in-process tools */ async queryAgent( agentId: string, prompt: string, options?: Partial<Options> ): Promise<Query> { const queryOptions: Options = { ...options, mcpServers: { ...options?.mcpServers, }, }; // Add in-process server if (this.sdkServer) { queryOptions.mcpServers!['claude-flow'] = this.sdkServer; } // Create agent-specific context if (this.config.orchestratorContext) { logger.debug('Creating agent query with orchestrator context', { agentId }); } return query({ prompt, options: queryOptions }); } /** * Get SDK server config for direct use */ getSdkServer(): McpSdkServerConfigWithInstance | undefined { return this.sdkServer; } /** * Check if in-process server is available */ isInProcessAvailable(): boolean { return this.sdkServer !== undefined; } /** * Get performance metrics */ getMetrics() { if (!this.registry) { return { error: 'Tool registry not available' }; } return this.registry.getMetrics(); } /** * Get performance comparison */ getPerformanceComparison() { if (!this.registry) { return { error: 'Tool registry not available' }; } return this.registry.getPerformanceComparison(); } /** * Cleanup resources */ async cleanup(): Promise<void> { if (this.registry) { await this.registry.cleanup(); } this.sdkServer = undefined; logger.info('SDK integration cleaned up'); } } /** * Global SDK integration instance */ let globalIntegration: SDKIntegration | undefined; /** * Initialize global SDK integration */ export async function initializeSDKIntegration( config: SDKIntegrationConfig ): Promise<SDKIntegration> { if (globalIntegration) { logger.warn('SDK integration already initialized, returning existing instance'); return globalIntegration; } globalIntegration = new SDKIntegration(config); await globalIntegration.initialize(); return globalIntegration; } /** * Get global SDK integration instance */ export function getSDKIntegration(): SDKIntegration | undefined { return globalIntegration; } /** * Create a query with in-process MCP server * Convenience function for direct use */ export async function createInProcessQuery( prompt: string, options?: Partial<Options>, orchestratorContext?: any ): Promise<Query> { // Initialize if not already done if (!globalIntegration) { await initializeSDKIntegration({ enableInProcess: true, enableMetrics: true, enableCaching: true, orchestratorContext, }); } return globalIntegration!.query(prompt, options); } /** * Get in-process MCP server config for use in SDK queries */ export async function getInProcessServerConfig( orchestratorContext?: any ): Promise<McpSdkServerConfigWithInstance> { // Initialize if needed if (!globalIntegration) { await initializeSDKIntegration({ enableInProcess: true, enableMetrics: true, enableCaching: true, orchestratorContext, }); } const server = globalIntegration?.getSdkServer(); if (!server) { throw new Error('In-process MCP server not available'); } return server; } /** * Measure performance difference between in-process and IPC */ export async function measurePerformance( toolName: string, args: Record<string, unknown>, iterations: number = 10 ): Promise<{ inProcessAvg: number; inProcessMin: number; inProcessMax: number; estimatedIPCAvg: number; speedupFactor: number; }> { if (!globalIntegration || !globalIntegration.isInProcessAvailable()) { throw new Error('In-process server not available for performance testing'); } const durations: number[] = []; logger.info('Starting performance measurement', { toolName, iterations }); for (let i = 0; i < iterations; i++) { const start = performance.now(); // Execute via in-process (through SDK integration) const query = globalIntegration.query(`Execute tool: ${toolName}`, { allowedTools: [toolName], }); // Wait for completion for await (const message of query) { if (message.type === 'result') { break; } } const duration = performance.now() - start; durations.push(duration); } const inProcessAvg = durations.reduce((a, b) => a + b, 0) / durations.length; const inProcessMin = Math.min(...durations); const inProcessMax = Math.max(...durations); // Estimate IPC overhead (based on typical stdio/SSE latency) // Conservative estimate: 50x slower for IPC due to serialization, process spawning, etc. const estimatedIPCAvg = inProcessAvg * 50; const speedupFactor = estimatedIPCAvg / inProcessAvg; logger.info('Performance measurement complete', { toolName, inProcessAvg: `${inProcessAvg.toFixed(2)}ms`, estimatedIPCAvg: `${estimatedIPCAvg.toFixed(2)}ms`, speedupFactor: `${speedupFactor.toFixed(1)}x`, }); return { inProcessAvg, inProcessMin, inProcessMax, estimatedIPCAvg, speedupFactor, }; }