Skip to main content
Glama

n8n-MCP

by 88-888
validation-summary.tsβ€’5.53 kB
#!/usr/bin/env node /** * Run validation on templates and provide a clean summary */ import { existsSync } from 'fs'; import path from 'path'; import { NodeRepository } from '../database/node-repository'; import { createDatabaseAdapter } from '../database/database-adapter'; import { WorkflowValidator } from '../services/workflow-validator'; import { EnhancedConfigValidator } from '../services/enhanced-config-validator'; import { TemplateRepository } from '../templates/template-repository'; import { Logger } from '../utils/logger'; const logger = new Logger({ prefix: '[validation-summary]' }); async function runValidationSummary() { const dbPath = path.join(process.cwd(), 'data', 'nodes.db'); if (!existsSync(dbPath)) { logger.error('Database not found. Run npm run rebuild first.'); process.exit(1); } const db = await createDatabaseAdapter(dbPath); const repository = new NodeRepository(db); const templateRepository = new TemplateRepository(db); const validator = new WorkflowValidator( repository, EnhancedConfigValidator ); try { const templates = await templateRepository.getAllTemplates(50); const results = { total: templates.length, valid: 0, invalid: 0, noErrors: 0, errorCategories: { unknownNodes: 0, missingRequired: 0, expressionErrors: 0, connectionErrors: 0, cycles: 0, other: 0 }, commonUnknownNodes: new Map<string, number>(), stickyNoteIssues: 0 }; for (const template of templates) { try { const workflow = JSON.parse(template.workflow_json || '{}'); const validationResult = await validator.validateWorkflow(workflow, { profile: 'minimal' // Use minimal profile to focus on critical errors }); if (validationResult.valid) { results.valid++; } else { results.invalid++; } if (validationResult.errors.length === 0) { results.noErrors++; } // Categorize errors validationResult.errors.forEach((error: any) => { const errorMsg = typeof error.message === 'string' ? error.message : JSON.stringify(error.message); if (errorMsg.includes('Unknown node type')) { results.errorCategories.unknownNodes++; const match = errorMsg.match(/Unknown node type: (.+)/); if (match) { const nodeType = match[1]; results.commonUnknownNodes.set(nodeType, (results.commonUnknownNodes.get(nodeType) || 0) + 1); } } else if (errorMsg.includes('missing_required')) { results.errorCategories.missingRequired++; if (error.nodeName?.includes('Sticky Note')) { results.stickyNoteIssues++; } } else if (errorMsg.includes('Expression error')) { results.errorCategories.expressionErrors++; } else if (errorMsg.includes('connection') || errorMsg.includes('Connection')) { results.errorCategories.connectionErrors++; } else if (errorMsg.includes('cycle')) { results.errorCategories.cycles++; } else { results.errorCategories.other++; } }); } catch (error) { results.invalid++; } } // Print summary console.log('\n' + '='.repeat(80)); console.log('WORKFLOW VALIDATION SUMMARY'); console.log('='.repeat(80)); console.log(`\nTemplates analyzed: ${results.total}`); console.log(`Valid workflows: ${results.valid} (${((results.valid / results.total) * 100).toFixed(1)}%)`); console.log(`Workflows without errors: ${results.noErrors} (${((results.noErrors / results.total) * 100).toFixed(1)}%)`); console.log('\nError Categories:'); console.log(` - Unknown nodes: ${results.errorCategories.unknownNodes}`); console.log(` - Missing required properties: ${results.errorCategories.missingRequired}`); console.log(` (Sticky note issues: ${results.stickyNoteIssues})`); console.log(` - Expression errors: ${results.errorCategories.expressionErrors}`); console.log(` - Connection errors: ${results.errorCategories.connectionErrors}`); console.log(` - Workflow cycles: ${results.errorCategories.cycles}`); console.log(` - Other errors: ${results.errorCategories.other}`); if (results.commonUnknownNodes.size > 0) { console.log('\nTop Unknown Node Types:'); const sortedNodes = Array.from(results.commonUnknownNodes.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 10); sortedNodes.forEach(([nodeType, count]) => { console.log(` - ${nodeType} (${count} occurrences)`); }); } console.log('\nKey Insights:'); const stickyNotePercent = ((results.stickyNoteIssues / results.errorCategories.missingRequired) * 100).toFixed(1); console.log(` - ${stickyNotePercent}% of missing required property errors are from Sticky Notes`); console.log(` - Most workflows have some validation warnings (best practices)`); console.log(` - Expression validation is working well`); console.log(` - Node type normalization is handling most cases correctly`); } catch (error) { logger.error('Failed to run validation summary:', error); process.exit(1); } finally { db.close(); } } // Run summary runValidationSummary().catch(error => { logger.error('Summary failed:', 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