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
text/typescript
/**
* 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,
};
}