Spaces:
Sleeping
Sleeping
| /** | |
| * Test Protocol Version Negotiation | |
| * | |
| * This script tests the protocol version negotiation logic with different client scenarios. | |
| */ | |
| import { | |
| negotiateProtocolVersion, | |
| isN8nClient, | |
| STANDARD_PROTOCOL_VERSION, | |
| N8N_PROTOCOL_VERSION | |
| } from '../utils/protocol-version'; | |
| interface TestCase { | |
| name: string; | |
| clientVersion?: string; | |
| clientInfo?: any; | |
| userAgent?: string; | |
| headers?: Record<string, string>; | |
| expectedVersion: string; | |
| expectedIsN8nClient: boolean; | |
| } | |
| const testCases: TestCase[] = [ | |
| { | |
| name: 'Standard MCP client (Claude Desktop)', | |
| clientVersion: '2025-03-26', | |
| clientInfo: { name: 'Claude Desktop', version: '1.0.0' }, | |
| expectedVersion: '2025-03-26', | |
| expectedIsN8nClient: false | |
| }, | |
| { | |
| name: 'n8n client with specific client info', | |
| clientVersion: '2025-03-26', | |
| clientInfo: { name: 'n8n', version: '1.0.0' }, | |
| expectedVersion: N8N_PROTOCOL_VERSION, | |
| expectedIsN8nClient: true | |
| }, | |
| { | |
| name: 'LangChain client', | |
| clientVersion: '2025-03-26', | |
| clientInfo: { name: 'langchain-js', version: '0.1.0' }, | |
| expectedVersion: N8N_PROTOCOL_VERSION, | |
| expectedIsN8nClient: true | |
| }, | |
| { | |
| name: 'n8n client via user agent', | |
| clientVersion: '2025-03-26', | |
| userAgent: 'n8n/1.0.0', | |
| expectedVersion: N8N_PROTOCOL_VERSION, | |
| expectedIsN8nClient: true | |
| }, | |
| { | |
| name: 'n8n mode environment variable', | |
| clientVersion: '2025-03-26', | |
| expectedVersion: N8N_PROTOCOL_VERSION, | |
| expectedIsN8nClient: true | |
| }, | |
| { | |
| name: 'Client requesting older version', | |
| clientVersion: '2024-06-25', | |
| clientInfo: { name: 'Some Client', version: '1.0.0' }, | |
| expectedVersion: '2024-06-25', | |
| expectedIsN8nClient: false | |
| }, | |
| { | |
| name: 'Client requesting unsupported version', | |
| clientVersion: '2020-01-01', | |
| clientInfo: { name: 'Old Client', version: '1.0.0' }, | |
| expectedVersion: STANDARD_PROTOCOL_VERSION, | |
| expectedIsN8nClient: false | |
| }, | |
| { | |
| name: 'No client info provided', | |
| expectedVersion: STANDARD_PROTOCOL_VERSION, | |
| expectedIsN8nClient: false | |
| }, | |
| { | |
| name: 'n8n headers detection', | |
| clientVersion: '2025-03-26', | |
| headers: { 'x-n8n-version': '1.0.0' }, | |
| expectedVersion: N8N_PROTOCOL_VERSION, | |
| expectedIsN8nClient: true | |
| } | |
| ]; | |
| async function runTests(): Promise<void> { | |
| console.log('๐งช Testing Protocol Version Negotiation\n'); | |
| let passed = 0; | |
| let failed = 0; | |
| // Set N8N_MODE for the environment variable test | |
| const originalN8nMode = process.env.N8N_MODE; | |
| for (const testCase of testCases) { | |
| try { | |
| // Set N8N_MODE for specific test | |
| if (testCase.name.includes('environment variable')) { | |
| process.env.N8N_MODE = 'true'; | |
| } else { | |
| delete process.env.N8N_MODE; | |
| } | |
| // Test isN8nClient function | |
| const detectedAsN8n = isN8nClient(testCase.clientInfo, testCase.userAgent, testCase.headers); | |
| // Test negotiateProtocolVersion function | |
| const result = negotiateProtocolVersion( | |
| testCase.clientVersion, | |
| testCase.clientInfo, | |
| testCase.userAgent, | |
| testCase.headers | |
| ); | |
| // Check results | |
| const versionCorrect = result.version === testCase.expectedVersion; | |
| const n8nDetectionCorrect = result.isN8nClient === testCase.expectedIsN8nClient; | |
| const isN8nFunctionCorrect = detectedAsN8n === testCase.expectedIsN8nClient; | |
| if (versionCorrect && n8nDetectionCorrect && isN8nFunctionCorrect) { | |
| console.log(`โ ${testCase.name}`); | |
| console.log(` Version: ${result.version}, n8n client: ${result.isN8nClient}`); | |
| console.log(` Reasoning: ${result.reasoning}\n`); | |
| passed++; | |
| } else { | |
| console.log(`โ ${testCase.name}`); | |
| console.log(` Expected: version=${testCase.expectedVersion}, isN8n=${testCase.expectedIsN8nClient}`); | |
| console.log(` Got: version=${result.version}, isN8n=${result.isN8nClient}`); | |
| console.log(` isN8nClient function: ${detectedAsN8n} (expected: ${testCase.expectedIsN8nClient})`); | |
| console.log(` Reasoning: ${result.reasoning}\n`); | |
| failed++; | |
| } | |
| } catch (error) { | |
| console.log(`๐ฅ ${testCase.name} - ERROR`); | |
| console.log(` ${error instanceof Error ? error.message : String(error)}\n`); | |
| failed++; | |
| } | |
| } | |
| // Restore original N8N_MODE | |
| if (originalN8nMode) { | |
| process.env.N8N_MODE = originalN8nMode; | |
| } else { | |
| delete process.env.N8N_MODE; | |
| } | |
| // Summary | |
| console.log(`\n๐ Test Results:`); | |
| console.log(` โ Passed: ${passed}`); | |
| console.log(` โ Failed: ${failed}`); | |
| console.log(` Total: ${passed + failed}`); | |
| if (failed > 0) { | |
| console.log(`\nโ Some tests failed!`); | |
| process.exit(1); | |
| } else { | |
| console.log(`\n๐ All tests passed!`); | |
| } | |
| } | |
| // Additional integration test | |
| async function testIntegration(): Promise<void> { | |
| console.log('\n๐ง Integration Test - MCP Server Protocol Negotiation\n'); | |
| // This would normally test the actual MCP server, but we'll just verify | |
| // the negotiation logic works in typical scenarios | |
| const scenarios = [ | |
| { | |
| name: 'Claude Desktop connecting', | |
| clientInfo: { name: 'Claude Desktop', version: '1.0.0' }, | |
| clientVersion: '2025-03-26' | |
| }, | |
| { | |
| name: 'n8n connecting via HTTP', | |
| headers: { 'user-agent': 'n8n/1.52.0' }, | |
| clientVersion: '2025-03-26' | |
| } | |
| ]; | |
| for (const scenario of scenarios) { | |
| const result = negotiateProtocolVersion( | |
| scenario.clientVersion, | |
| scenario.clientInfo, | |
| scenario.headers?.['user-agent'], | |
| scenario.headers | |
| ); | |
| console.log(`๐ ${scenario.name}:`); | |
| console.log(` Negotiated version: ${result.version}`); | |
| console.log(` Is n8n client: ${result.isN8nClient}`); | |
| console.log(` Reasoning: ${result.reasoning}\n`); | |
| } | |
| } | |
| if (require.main === module) { | |
| runTests() | |
| .then(() => testIntegration()) | |
| .catch(error => { | |
| console.error('Test execution failed:', error); | |
| process.exit(1); | |
| }); | |
| } |