Skip to main content
Glama

n8n-MCP

by 88-888
test-essentials.tsโ€ข10.2 kB
#!/usr/bin/env ts-node /** * Test script for validating the get_node_essentials tool * * This script: * 1. Compares get_node_essentials vs get_node_info response sizes * 2. Validates that essential properties are correctly extracted * 3. Checks that examples are properly generated * 4. Tests the property search functionality */ import { N8NDocumentationMCPServer } from '../src/mcp/server'; import { readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; // Color codes for terminal output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', cyan: '\x1b[36m' }; function log(message: string, color: string = colors.reset) { console.log(`${color}${message}${colors.reset}`); } function logSection(title: string) { console.log('\n' + '='.repeat(60)); log(title, colors.bright + colors.cyan); console.log('='.repeat(60)); } function formatBytes(bytes: number): string { if (bytes < 1024) return bytes + ' B'; const kb = bytes / 1024; if (kb < 1024) return kb.toFixed(1) + ' KB'; const mb = kb / 1024; return mb.toFixed(2) + ' MB'; } async function testNodeEssentials(server: N8NDocumentationMCPServer, nodeType: string) { logSection(`Testing ${nodeType}`); try { // Get full node info const startFull = Date.now(); const fullInfo = await server.executeTool('get_node_info', { nodeType }); const fullTime = Date.now() - startFull; const fullSize = JSON.stringify(fullInfo).length; // Get essential info const startEssential = Date.now(); const essentialInfo = await server.executeTool('get_node_essentials', { nodeType }); const essentialTime = Date.now() - startEssential; const essentialSize = JSON.stringify(essentialInfo).length; // Calculate metrics const sizeReduction = ((fullSize - essentialSize) / fullSize * 100).toFixed(1); const speedImprovement = ((fullTime - essentialTime) / fullTime * 100).toFixed(1); // Display results log(`\n๐Ÿ“Š Size Comparison:`, colors.bright); log(` Full response: ${formatBytes(fullSize)}`, colors.yellow); log(` Essential response: ${formatBytes(essentialSize)}`, colors.green); log(` Size reduction: ${sizeReduction}% โœจ`, colors.bright + colors.green); log(`\nโšก Performance:`, colors.bright); log(` Full response time: ${fullTime}ms`); log(` Essential response time: ${essentialTime}ms`); log(` Speed improvement: ${speedImprovement}%`, colors.green); log(`\n๐Ÿ“‹ Property Count:`, colors.bright); const fullPropCount = fullInfo.properties?.length || 0; const essentialPropCount = (essentialInfo.requiredProperties?.length || 0) + (essentialInfo.commonProperties?.length || 0); log(` Full properties: ${fullPropCount}`); log(` Essential properties: ${essentialPropCount}`); log(` Properties removed: ${fullPropCount - essentialPropCount} (${((fullPropCount - essentialPropCount) / fullPropCount * 100).toFixed(1)}%)`, colors.green); log(`\n๐Ÿ”ง Essential Properties:`, colors.bright); log(` Required: ${essentialInfo.requiredProperties?.map((p: any) => p.name).join(', ') || 'None'}`); log(` Common: ${essentialInfo.commonProperties?.map((p: any) => p.name).join(', ') || 'None'}`); log(`\n๐Ÿ“š Examples:`, colors.bright); const examples = Object.keys(essentialInfo.examples || {}); log(` Available examples: ${examples.join(', ') || 'None'}`); if (essentialInfo.examples?.minimal) { log(` Minimal example properties: ${Object.keys(essentialInfo.examples.minimal).join(', ')}`); } log(`\n๐Ÿ“Š Metadata:`, colors.bright); log(` Total properties available: ${essentialInfo.metadata?.totalProperties || 0}`); log(` Is AI Tool: ${essentialInfo.metadata?.isAITool ? 'Yes' : 'No'}`); log(` Is Trigger: ${essentialInfo.metadata?.isTrigger ? 'Yes' : 'No'}`); log(` Has Credentials: ${essentialInfo.metadata?.hasCredentials ? 'Yes' : 'No'}`); // Test property search const searchTerms = ['auth', 'header', 'body', 'json']; log(`\n๐Ÿ” Property Search Test:`, colors.bright); for (const term of searchTerms) { try { const searchResult = await server.executeTool('search_node_properties', { nodeType, query: term, maxResults: 5 }); log(` "${term}": Found ${searchResult.totalMatches} properties`); } catch (error) { log(` "${term}": Search failed`, colors.red); } } return { nodeType, fullSize, essentialSize, sizeReduction: parseFloat(sizeReduction), fullPropCount, essentialPropCount, success: true }; } catch (error) { log(`โŒ Error testing ${nodeType}: ${error}`, colors.red); return { nodeType, fullSize: 0, essentialSize: 0, sizeReduction: 0, fullPropCount: 0, essentialPropCount: 0, success: false, error: error instanceof Error ? error.message : String(error) }; } } async function main() { logSection('n8n MCP Essentials Tool Test Suite'); try { // Initialize server log('\n๐Ÿš€ Initializing MCP server...', colors.cyan); const server = new N8NDocumentationMCPServer(); // Wait for initialization await new Promise(resolve => setTimeout(resolve, 1000)); // Test nodes const testNodes = [ 'nodes-base.httpRequest', 'nodes-base.webhook', 'nodes-base.code', 'nodes-base.set', 'nodes-base.if', 'nodes-base.postgres', 'nodes-base.openAi', 'nodes-base.googleSheets', 'nodes-base.slack', 'nodes-base.merge' ]; const results = []; for (const nodeType of testNodes) { const result = await testNodeEssentials(server, nodeType); results.push(result); } // Summary logSection('Test Summary'); const successful = results.filter(r => r.success); const totalFullSize = successful.reduce((sum, r) => sum + r.fullSize, 0); const totalEssentialSize = successful.reduce((sum, r) => sum + r.essentialSize, 0); const avgReduction = successful.reduce((sum, r) => sum + r.sizeReduction, 0) / successful.length; log(`\nโœ… Successful tests: ${successful.length}/${results.length}`, colors.green); if (successful.length > 0) { log(`\n๐Ÿ“Š Overall Statistics:`, colors.bright); log(` Total full size: ${formatBytes(totalFullSize)}`); log(` Total essential size: ${formatBytes(totalEssentialSize)}`); log(` Average reduction: ${avgReduction.toFixed(1)}%`, colors.bright + colors.green); log(`\n๐Ÿ† Best Performers:`, colors.bright); const sorted = successful.sort((a, b) => b.sizeReduction - a.sizeReduction); sorted.slice(0, 3).forEach((r, i) => { log(` ${i + 1}. ${r.nodeType}: ${r.sizeReduction}% reduction (${formatBytes(r.fullSize)} โ†’ ${formatBytes(r.essentialSize)})`); }); } const failed = results.filter(r => !r.success); if (failed.length > 0) { log(`\nโŒ Failed tests:`, colors.red); failed.forEach(r => { log(` - ${r.nodeType}: ${r.error}`, colors.red); }); } // Save detailed results const reportPath = join(process.cwd(), 'test-results-essentials.json'); writeFileSync(reportPath, JSON.stringify({ timestamp: new Date().toISOString(), summary: { totalTests: results.length, successful: successful.length, failed: failed.length, averageReduction: avgReduction, totalFullSize, totalEssentialSize }, results }, null, 2)); log(`\n๐Ÿ“„ Detailed results saved to: ${reportPath}`, colors.cyan); // Recommendations logSection('Recommendations'); if (avgReduction > 90) { log('โœจ Excellent! The essentials tool is achieving >90% size reduction.', colors.green); } else if (avgReduction > 80) { log('๐Ÿ‘ Good! The essentials tool is achieving 80-90% size reduction.', colors.yellow); log(' Consider reviewing nodes with lower reduction rates.'); } else { log('โš ๏ธ The average size reduction is below 80%.', colors.yellow); log(' Review the essential property lists for optimization.'); } // Test specific functionality logSection('Testing Advanced Features'); // Test error handling log('\n๐Ÿงช Testing error handling...', colors.cyan); try { await server.executeTool('get_node_essentials', { nodeType: 'non-existent-node' }); log(' โŒ Error handling failed - should have thrown error', colors.red); } catch (error) { log(' โœ… Error handling works correctly', colors.green); } // Test alternative node type formats log('\n๐Ÿงช Testing alternative node type formats...', colors.cyan); const alternativeFormats = [ { input: 'httpRequest', expected: 'nodes-base.httpRequest' }, { input: 'nodes-base.httpRequest', expected: 'nodes-base.httpRequest' }, { input: 'HTTPREQUEST', expected: 'nodes-base.httpRequest' } ]; for (const format of alternativeFormats) { try { const result = await server.executeTool('get_node_essentials', { nodeType: format.input }); if (result.nodeType === format.expected) { log(` โœ… "${format.input}" โ†’ "${format.expected}"`, colors.green); } else { log(` โŒ "${format.input}" โ†’ "${result.nodeType}" (expected "${format.expected}")`, colors.red); } } catch (error) { log(` โŒ "${format.input}" โ†’ Error: ${error}`, colors.red); } } log('\nโœจ Test suite completed!', colors.bright + colors.green); } catch (error) { log(`\nโŒ Fatal error: ${error}`, colors.red); process.exit(1); } } // Run the test main().catch(error => { console.error('Unhandled error:', error); process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/88-888/n8n-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server