/** * Advanced MCP Toolkit Example - Multiple Servers * * This example demonstrates advanced usage of the MCP Toolkit including: * 1. Connecting to multiple servers * 2. Configuring the toolkit with detailed options * 3. Executing parallel tool calls * 4. Handling errors with custom recovery strategies * 5. Event handling for server and resource changes */ import { container, registerServices } from '../../src/container.js'; import { IMCPToolkit } from '../../src/interfaces/toolkit/toolkit.interface.js'; import { ToolCall } from '../../src/interfaces/tool.interface.js'; // Register services with configuration for multiple servers registerServices({ servers: { 'echo-server': { command: 'node', args: ['../../src/tools/echo-server.js'], env: { NODE_ENV: 'production' }, autoRestart: true, maxRestarts: 3, restartDelay: 1000 }, 'another-server': { command: 'node', args: ['../../src/tools/echo-server.js'], // Using echo-server as placeholder env: { NODE_ENV: 'production', SERVER_NAME: 'another-server' }, autoRestart: true, maxRestarts: 3, restartDelay: 1000 } }, connections: { defaults: { transportType: 'stdio', requestTimeout: 5000, autoReconnect: true, maxReconnects: 3, reconnectDelay: 1000 }, overrides: { 'another-server': { requestTimeout: 10000 // Longer timeout for this server } } }, toolExecutor: { maxRetries: 2, retryDelay: 500, useExponentialBackoff: true, executionTimeout: 10000, cacheResults: true, cacheTtl: 60000 // 1 minute }, resourceManager: { maxCacheSize: 5 * 1024 * 1024, // 5MB cache size cacheTtl: 300000 // 5 minutes }, logger: { level: 'info', console: true } }); // Get the toolkit instance const toolkit = container.resolve('IMCPToolkit'); // Set up event listeners toolkit.on('serverStatus', (event) => { console.log(`Server ${event.serverName} status changed to ${event.status}`); }); toolkit.on('toolsChanged', (event) => { console.log(`Available tools changed: ${event.tools.length} tools available`); }); toolkit.on('resourceUpdated', (event) => { console.log(`Resource updated: ${event.uri}`); }); toolkit.on('error', (event) => { console.error(`Error occurred: ${event.error.message}`); }); // Main function async function main() { try { console.log('Starting MCP Toolkit...'); // Start the toolkit (starts all servers and establishes connections) await toolkit.start(); console.log('MCP Toolkit started successfully'); // Get server statuses const servers = toolkit.getServerStatuses(); console.log('Server statuses:'); Object.entries(servers).forEach(([name, status]) => { console.log(`- ${name}: ${status}`); }); // Get available tools const tools = await toolkit.getAvailableTools(); console.log(`\nDiscovered ${tools.length} tools:`); tools.forEach(tool => { console.log(`- ${tool.name} (from ${tool.serverName}): ${tool.description || 'No description'}`); }); // Execute a tool call if (tools.some(tool => tool.name === 'echo')) { console.log('\nExecuting echo tool call...'); const echoCall: ToolCall = { function_name: 'echo', parameters: { message: 'Hello from advanced example!' } }; const echoResult = await toolkit.executeToolCall(echoCall); console.log('Echo result:', echoResult.result); } // Execute multiple tool calls in parallel console.log('\nExecuting multiple tool calls in parallel...'); const parallelCalls: ToolCall[] = [ { function_name: 'echo', parameters: { message: 'Parallel call 1' } }, { function_name: 'echo', parameters: { message: 'Parallel call 2' } } ]; const parallelResults = await toolkit.executeToolCalls(parallelCalls); console.log('Parallel results:'); parallelResults.forEach((result, index) => { console.log(`- Result ${index + 1}:`, result.result); }); // List resources console.log('\nListing available resources...'); const resources = await toolkit.listResources(); console.log(`Discovered ${resources.length} resources:`); resources.forEach(resource => { console.log(`- ${resource.uri} (from ${resource.serverName}): ${resource.description || 'No description'}`); }); // Read a resource if available if (resources.length > 0) { console.log('\nReading first resource...'); const resourceContent = await toolkit.readResource(resources[0].uri); console.log('Resource content:', resourceContent); } // Subscribe to resource updates if available if (resources.length > 0) { console.log('\nSubscribing to resource updates...'); await toolkit.subscribeToResource(resources[0].uri); console.log('Subscribed to resource updates'); } // Simulate a server restart console.log('\nRestarting echo-server...'); await toolkit.restartServer('echo-server'); console.log('Server restarted'); // Wait for user input before shutting down console.log('\nPress Enter to shut down...'); process.stdin.once('data', async () => { console.log('\nShutting down MCP Toolkit...'); await toolkit.stop(); console.log('MCP Toolkit shut down successfully'); process.exit(0); }); } catch (error) { console.error('Error in MCP Toolkit example:', error); try { // Try to clean up await toolkit.stop(); } catch (cleanupError) { console.error('Error during cleanup:', cleanupError); } process.exit(1); } } // Run the main function main().catch(error => { console.error('Unhandled error:', error); process.exit(1); });