diff --git a/Chat/backend/benchmarks/benchmark_mcp.js b/Chat/backend/benchmarks/benchmark_mcp.js new file mode 100644 index 00000000..1cf5c572 --- /dev/null +++ b/Chat/backend/benchmarks/benchmark_mcp.js @@ -0,0 +1,93 @@ + +// Mocking MCPService for benchmarking +class MockMCPService { + constructor() { + this.servers = new Map(); + this.tools = []; + } + + _refreshToolListOriginal() { + const allTools = []; + for (const server of this.servers.values()) { + allTools.push(...server.tools.map(t => ({ + ...t, + _server: server.name // internal tracking + }))); + } + this.tools = allTools; + } + + _refreshToolListOptimized() { + this.tools = Array.from(this.servers.values()).flatMap(server => + server.tools.map(t => ({ + ...t, + _server: server.name + })) + ); + } + + _refreshToolListFaster() { + const allTools = []; + for (const server of this.servers.values()) { + const serverName = server.name; + const tools = server.tools; + for (let i = 0; i < tools.length; i++) { + const t = tools[i]; + allTools.push({ + ...t, + _server: serverName + }); + } + } + this.tools = allTools; + } +} + +const service = new MockMCPService(); + +// Populate with dummy data +const NUM_SERVERS = 100; +const TOOLS_PER_SERVER = 50; + +for (let i = 0; i < NUM_SERVERS; i++) { + const serverName = `server_${i}`; + const tools = []; + for (let j = 0; j < TOOLS_PER_SERVER; j++) { + tools.push({ + name: `tool_${i}_${j}`, + description: `Description for tool ${j} on server ${i}`, + inputSchema: { type: 'object', properties: {} } + }); + } + service.servers.set(serverName, { name: serverName, tools }); +} + +console.log(`Benchmarking with ${NUM_SERVERS} servers and ${TOOLS_PER_SERVER} tools per server (Total: ${NUM_SERVERS * TOOLS_PER_SERVER} tools)`); + +const ITERATIONS = 2000; +const WARMUP = 500; + +// Warmup +for (let i = 0; i < WARMUP; i++) { + service._refreshToolListOriginal(); + service._refreshToolListOptimized(); + service._refreshToolListFaster(); +} + +function runBench(name, fn) { + let total = 0; + for (let i = 0; i < ITERATIONS; i++) { + let start = performance.now(); + fn(); + total += (performance.now() - start); + } + console.log(`${name}: ${total.toFixed(4)}ms (average: ${(total / ITERATIONS).toFixed(4)}ms per call)`); + return total; +} + +const originalTime = runBench('Original', () => service._refreshToolListOriginal()); +const optimizedTime = runBench('Optimized (flatMap)', () => service._refreshToolListOptimized()); +const fasterTime = runBench('Faster (nested loops)', () => service._refreshToolListFaster()); + +console.log(`Improvement (flatMap): ${((originalTime - optimizedTime) / originalTime * 100).toFixed(2)}%`); +console.log(`Improvement (nested loops): ${((originalTime - fasterTime) / originalTime * 100).toFixed(2)}%`); diff --git a/Chat/backend/services/mcpService.js b/Chat/backend/services/mcpService.js index cb12f763..b9ae024d 100644 --- a/Chat/backend/services/mcpService.js +++ b/Chat/backend/services/mcpService.js @@ -141,10 +141,13 @@ class MCPService { _refreshToolList() { const allTools = []; for (const server of this.servers.values()) { - allTools.push(...server.tools.map(t => ({ - ...t, - _server: server.name // internal tracking - }))); + const serverName = server.name; + for (const tool of server.tools) { + allTools.push({ + ...tool, + _server: serverName // internal tracking + }); + } } this.tools = allTools; } diff --git a/Chat/backend/tests/mcp_verify.js b/Chat/backend/tests/mcp_verify.js new file mode 100644 index 00000000..a294c55d --- /dev/null +++ b/Chat/backend/tests/mcp_verify.js @@ -0,0 +1,47 @@ + +import { mcpService } from './services/mcpService.js'; +import assert from 'assert'; + +async function verify() { + console.log('Verifying MCPService._refreshToolList correctness...'); + + const server1 = { + name: 'server1', + tools: [ + { name: 'tool1', description: 'desc1' }, + { name: 'tool2', description: 'desc2' } + ] + }; + + const server2 = { + name: 'server2', + tools: [ + { name: 'tool3', description: 'desc3' } + ] + }; + + mcpService.servers.set('server1', server1); + mcpService.servers.set('server2', server2); + + // Trigger refresh + mcpService._refreshToolList(); + + console.log(`Total tools found: ${mcpService.tools.length}`); + + assert.strictEqual(mcpService.tools.length, 3, 'Should have 3 tools'); + + const tool1 = mcpService.tools.find(t => t.name === 'tool1'); + assert.ok(tool1, 'tool1 should exist'); + assert.strictEqual(tool1._server, 'server1', 'tool1 should belong to server1'); + + const tool3 = mcpService.tools.find(t => t.name === 'tool3'); + assert.ok(tool3, 'tool3 should exist'); + assert.strictEqual(tool3._server, 'server2', 'tool3 should belong to server2'); + + console.log('✅ Correctness verified!'); +} + +verify().catch(err => { + console.error('❌ Verification failed:', err); + process.exit(1); +});