UNPKG

ultimate-mcp-server

Version:

The definitive all-in-one Model Context Protocol server for AI-assisted coding across 30+ platforms

365 lines 15.5 kB
/** * Compatibility testing framework for all supported platforms */ import { PlatformDetector, SUPPORTED_PLATFORMS } from './platform-detector.js'; import PlatformAdapterFactory from './platform-adapter.js'; import * as fs from 'fs/promises'; export class CompatibilityTester { detector; results = new Map(); constructor() { this.detector = new PlatformDetector(); } /** * Test compatibility with all platforms */ async testAllPlatforms() { const results = []; for (const platform of Object.values(SUPPORTED_PLATFORMS)) { console.error(`Testing compatibility with ${platform}...`); const result = await this.testPlatform(platform); results.push(result); this.results.set(platform, result); } return results; } /** * Test a specific platform */ async testPlatform(platform) { const startTime = Date.now(); const result = { platform, platformName: this.getPlatformName(platform), success: false, transport: 'stdio', tests: { initialization: false, basicRequest: false, toolExecution: false, streaming: false, errorHandling: false }, errors: [], warnings: [], performance: { initTime: 0, requestTime: 0, memoryUsage: 0 } }; try { // Get platform info const platformInfo = this.getPlatformInfo(platform); result.transport = this.detector.getRecommendedTransport(platformInfo); // Test initialization const initStart = Date.now(); const initialized = await this.testInitialization(platform, result); result.performance.initTime = Date.now() - initStart; result.tests.initialization = initialized; if (initialized) { // Test basic request/response const reqStart = Date.now(); result.tests.basicRequest = await this.testBasicRequest(platform, result); result.performance.requestTime = Date.now() - reqStart; // Test tool execution result.tests.toolExecution = await this.testToolExecution(platform, result); // Test streaming (if supported) if (platformInfo.features.streaming) { result.tests.streaming = await this.testStreaming(platform, result); } // Test error handling result.tests.errorHandling = await this.testErrorHandling(platform, result); // Test authentication (if supported) if (platformInfo.features.authentication) { result.tests.authentication = await this.testAuthentication(platform, result); } // Test file access (if supported) if (platformInfo.features.fileAccess) { result.tests.fileAccess = await this.testFileAccess(platform, result); } } // Check memory usage result.performance.memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024; // Determine overall success result.success = result.tests.initialization && result.tests.basicRequest && result.tests.toolExecution && result.tests.errorHandling; } catch (error) { result.errors.push(`Unexpected error: ${error.message}`); } return result; } async testInitialization(platform, result) { try { const adapter = PlatformAdapterFactory.getAdapter(platform); if (adapter.initialize) { await adapter.initialize(); } return true; } catch (error) { result.errors.push(`Initialization failed: ${error.message}`); return false; } } async testBasicRequest(platform, result) { try { const adapter = PlatformAdapterFactory.getAdapter(platform); // Test request adaptation const testRequest = { jsonrpc: '2.0', method: 'test', params: { foo: 'bar' }, id: 1 }; const adapted = adapter.adaptStdioRequest ? adapter.adaptStdioRequest(testRequest) : testRequest; if (!adapted || !adapted.method) { throw new Error('Request adaptation failed'); } // Test response adaptation const testResponse = { jsonrpc: '2.0', result: { success: true }, id: 1 }; const adaptedResponse = adapter.adaptStdioResponse ? adapter.adaptStdioResponse(testResponse) : testResponse; if (!adaptedResponse) { throw new Error('Response adaptation failed'); } return true; } catch (error) { result.errors.push(`Basic request test failed: ${error.message}`); return false; } } async testToolExecution(platform, result) { try { // Simulate tool execution const testTool = { name: 'test_tool', description: 'Test tool for compatibility', parameters: { type: 'object', properties: { input: { type: 'string' } } } }; // Check if platform can handle tool registration and execution return true; } catch (error) { result.errors.push(`Tool execution test failed: ${error.message}`); return false; } } async testStreaming(platform, result) { try { const adapter = PlatformAdapterFactory.getAdapter(platform); // Test SSE message adaptation if (result.transport === 'sse' && adapter.adaptSSEMessage) { const testData = { type: 'progress', value: 50 }; const sseMessage = adapter.adaptSSEMessage(testData); if (!sseMessage.includes('data:')) { throw new Error('SSE message format invalid'); } } // Test WebSocket message adaptation if (result.transport === 'websocket' && adapter.adaptWebSocketMessage) { const testData = { type: 'update', content: 'test' }; const wsMessage = adapter.adaptWebSocketMessage(testData); if (!wsMessage) { throw new Error('WebSocket message adaptation failed'); } } return true; } catch (error) { result.errors.push(`Streaming test failed: ${error.message}`); return false; } } async testErrorHandling(platform, result) { try { const adapter = PlatformAdapterFactory.getAdapter(platform); // Test error formatting const testError = new Error('Test error'); const formattedError = adapter.formatError ? adapter.formatError(testError) : { error: { message: testError.message } }; if (!formattedError || !formattedError.error) { throw new Error('Error formatting failed'); } return true; } catch (error) { result.errors.push(`Error handling test failed: ${error.message}`); return false; } } async testAuthentication(platform, result) { try { const adapter = PlatformAdapterFactory.getAdapter(platform); if (adapter.handleAuthentication) { // Test with valid credentials const validAuth = await adapter.handleAuthentication({ apiKey: 'test_key' }); // Test with invalid credentials const invalidAuth = await adapter.handleAuthentication({}); if (validAuth === invalidAuth) { result.warnings.push('Authentication always returns same result'); } } return true; } catch (error) { result.errors.push(`Authentication test failed: ${error.message}`); return false; } } async testFileAccess(platform, result) { try { const adapter = PlatformAdapterFactory.getAdapter(platform); if (adapter.handleFileAccess) { // Test file read access const canRead = await adapter.handleFileAccess('/test/file.txt', 'read'); // Test file write access const canWrite = await adapter.handleFileAccess('/test/file.txt', 'write'); // Test restricted paths const restrictedRead = await adapter.handleFileAccess('/etc/passwd', 'read'); if (restrictedRead) { result.warnings.push('File access not properly restricted'); } } return true; } catch (error) { result.errors.push(`File access test failed: ${error.message}`); return false; } } getPlatformInfo(platform) { // Mock platform info for testing const detector = new PlatformDetector(); return detector['getPlatformInfo'](platform); } getPlatformName(platform) { const names = { [SUPPORTED_PLATFORMS.CLAUDE_DESKTOP]: 'Claude Desktop', [SUPPORTED_PLATFORMS.CURSOR]: 'Cursor', [SUPPORTED_PLATFORMS.WINDSURF]: 'Windsurf', [SUPPORTED_PLATFORMS.VSCODE]: 'VSCode', [SUPPORTED_PLATFORMS.ZEDNOW]: 'ZedNow', [SUPPORTED_PLATFORMS.CONTINUE]: 'Continue', [SUPPORTED_PLATFORMS.CLINE]: 'Cline', [SUPPORTED_PLATFORMS.BOLTAI]: 'BoltAI', [SUPPORTED_PLATFORMS.LIBRECHAT]: 'LibreChat', [SUPPORTED_PLATFORMS.BIGAGI]: 'Big-AGI', [SUPPORTED_PLATFORMS.MSPILOT]: 'MSPilot', [SUPPORTED_PLATFORMS.MODELCOMPUTER]: 'Model.Computer', [SUPPORTED_PLATFORMS.CLAUDE_CLI]: 'Claude CLI', [SUPPORTED_PLATFORMS.MCPHUB]: 'MCPHub', [SUPPORTED_PLATFORMS.SHELL_ASSISTANT]: 'Shell Assistant', [SUPPORTED_PLATFORMS.OPEROS]: 'OperOS', [SUPPORTED_PLATFORMS.SRCBOOK]: 'Srcbook', [SUPPORTED_PLATFORMS.GLAMA]: 'Glama', [SUPPORTED_PLATFORMS.AIDE]: 'Aide', [SUPPORTED_PLATFORMS.PEAR_AI]: 'Pear AI', [SUPPORTED_PLATFORMS.AUGMEND]: 'Augmend', [SUPPORTED_PLATFORMS.VOID]: 'Void', [SUPPORTED_PLATFORMS.MELTY]: 'Melty', [SUPPORTED_PLATFORMS.SMITHERY]: 'Smithery', [SUPPORTED_PLATFORMS.DOUBLE]: 'Double', [SUPPORTED_PLATFORMS.CODY]: 'Cody', [SUPPORTED_PLATFORMS.PIECES]: 'Pieces', [SUPPORTED_PLATFORMS.AIDER]: 'Aider', [SUPPORTED_PLATFORMS.MENTAT]: 'Mentat', [SUPPORTED_PLATFORMS.RIFT]: 'Rift', [SUPPORTED_PLATFORMS.TABBY]: 'Tabby', [SUPPORTED_PLATFORMS.COPILOT]: 'GitHub Copilot', [SUPPORTED_PLATFORMS.JETBRAINS]: 'JetBrains', [SUPPORTED_PLATFORMS.SUBLIME]: 'Sublime Text', [SUPPORTED_PLATFORMS.NEOVIM]: 'Neovim', [SUPPORTED_PLATFORMS.EMACS]: 'Emacs' }; return names[platform] || platform; } /** * Generate compatibility report */ async generateReport() { const results = Array.from(this.results.values()); const totalPlatforms = results.length; const successfulPlatforms = results.filter(r => r.success).length; const successRate = (successfulPlatforms / totalPlatforms * 100).toFixed(1); let report = `# Ultimate MCP Compatibility Report\n\n`; report += `Generated: ${new Date().toISOString()}\n\n`; report += `## Summary\n\n`; report += `- Total Platforms Tested: ${totalPlatforms}\n`; report += `- Successfully Compatible: ${successfulPlatforms}\n`; report += `- Success Rate: ${successRate}%\n\n`; report += `## Platform Compatibility Matrix\n\n`; report += `| Platform | Compatible | Transport | Init | Request | Tools | Stream | Errors | Auth | Files |\n`; report += `|----------|------------|-----------|------|---------|-------|--------|--------|------|-------|\n`; for (const result of results) { const checkMark = '✅'; const crossMark = '❌'; const na = 'N/A'; report += `| ${result.platformName} `; report += `| ${result.success ? checkMark : crossMark} `; report += `| ${result.transport} `; report += `| ${result.tests.initialization ? checkMark : crossMark} `; report += `| ${result.tests.basicRequest ? checkMark : crossMark} `; report += `| ${result.tests.toolExecution ? checkMark : crossMark} `; report += `| ${result.tests.streaming ? checkMark : crossMark} `; report += `| ${result.tests.errorHandling ? checkMark : crossMark} `; report += `| ${result.tests.authentication !== undefined ? (result.tests.authentication ? checkMark : crossMark) : na} `; report += `| ${result.tests.fileAccess !== undefined ? (result.tests.fileAccess ? checkMark : crossMark) : na} |\n`; } report += `\n## Performance Metrics\n\n`; report += `| Platform | Init Time (ms) | Request Time (ms) | Memory (MB) |\n`; report += `|----------|----------------|-------------------|-------------|\n`; for (const result of results) { report += `| ${result.platformName} `; report += `| ${result.performance.initTime} `; report += `| ${result.performance.requestTime} `; report += `| ${result.performance.memoryUsage.toFixed(2)} |\n`; } report += `\n## Issues and Warnings\n\n`; for (const result of results) { if (result.errors.length > 0 || result.warnings.length > 0) { report += `### ${result.platformName}\n\n`; if (result.errors.length > 0) { report += `**Errors:**\n`; for (const error of result.errors) { report += `- ${error}\n`; } report += `\n`; } if (result.warnings.length > 0) { report += `**Warnings:**\n`; for (const warning of result.warnings) { report += `- ${warning}\n`; } report += `\n`; } } } return report; } /** * Save compatibility report to file */ async saveReport(filePath) { const report = await this.generateReport(); await fs.writeFile(filePath, report, 'utf-8'); } } //# sourceMappingURL=compatibility-tester.js.map