feat: add n8n_validate_workflow tool (v2.6.3)

- NEW: n8n_validate_workflow tool to validate workflows from n8n instance by ID
- Fetches workflow via API and runs comprehensive validation
- Uses existing WorkflowValidator for consistency
- Supports all validation profiles and options
- Updated start_here tool with new workflow lifecycle info
- Updated README with new tool documentation
- Updated Claude Project Setup instructions

This completes the workflow lifecycle management:
discover → build → validate → deploy → execute → monitor

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-06-26 16:07:46 +02:00
parent bcfdc9627d
commit 34b5ff5d35
7 changed files with 295 additions and 7 deletions

View File

@@ -6,7 +6,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
n8n-mcp is a comprehensive documentation and knowledge server that provides AI assistants with complete access to n8n node information through the Model Context Protocol (MCP). It serves as a bridge between n8n's workflow automation platform and AI models, enabling them to understand and work with n8n nodes effectively.
## ✅ Latest Updates (v2.6.2)
## ✅ Latest Updates (v2.6.3)
### Update (v2.6.3) - n8n Instance Workflow Validation:
-**NEW: n8n_validate_workflow tool** - Validate workflows directly from n8n instance by ID
-**Fetches and validates** - Retrieves workflow from n8n API and runs comprehensive validation
-**Same validation logic** - Uses existing WorkflowValidator for consistency
-**Full validation options** - Supports all validation profiles and options
-**Integrated workflow** - Part of complete lifecycle: discover → build → validate → deploy → execute
-**No JSON needed** - AI agents can validate by just providing workflow ID
### Update (v2.6.2) - Enhanced Workflow Creation Validation:
-**NEW: Node type validation** - Verifies node types actually exist in n8n
@@ -180,6 +188,7 @@ src/
│ ├── test-workflow-validation.ts # Test workflow validation (NEW in v2.5.0)
│ ├── test-ai-workflow-validation.ts # Test AI workflow validation (NEW in v2.5.1)
│ ├── test-mcp-tools.ts # Test MCP tool enhancements (NEW in v2.5.1)
│ ├── test-n8n-validate-workflow.ts # Test n8n_validate_workflow tool (NEW in v2.6.3)
│ ├── test-typeversion-validation.ts # Test typeVersion validation (NEW in v2.6.1)
│ ├── fetch-templates.ts # Fetch workflow templates from n8n.io (NEW in v2.4.1)
│ └── test-templates.ts # Test template functionality (NEW in v2.4.1)
@@ -233,6 +242,7 @@ npm run test:mcp-tools # Test MCP tool enhancements
npm run test:single-session # Test single session HTTP
npm run test:template-validation # Test template validation
npm run test:n8n-manager # Test n8n management tools integration
npm run test:n8n-validate-workflow # Test n8n_validate_workflow tool
npm run test:typeversion-validation # Test typeVersion validation
# Workflow Validation Commands:
@@ -372,6 +382,7 @@ These tools are only available when N8N_API_URL and N8N_API_KEY are configured:
- `n8n_update_workflow` - Update existing workflows
- `n8n_delete_workflow` - Delete workflows permanently
- `n8n_list_workflows` - List workflows with filtering
- `n8n_validate_workflow` - **NEW v2.6.3** Validate workflow from n8n instance by ID
#### Execution Management
- `n8n_trigger_webhook_workflow` - Trigger workflows via webhook URL

View File

@@ -2,7 +2,7 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/czlonkowski/n8n-mcp?style=social)](https://github.com/czlonkowski/n8n-mcp)
[![Version](https://img.shields.io/badge/version-2.6.2-blue.svg)](https://github.com/czlonkowski/n8n-mcp)
[![Version](https://img.shields.io/badge/version-2.6.3-blue.svg)](https://github.com/czlonkowski/n8n-mcp)
[![Docker](https://img.shields.io/badge/docker-ghcr.io%2Fczlonkowski%2Fn8n--mcp-green.svg)](https://github.com/czlonkowski/n8n-mcp/pkgs/container/n8n-mcp)
A Model Context Protocol (MCP) server that provides AI assistants with comprehensive access to n8n node documentation, properties, and operations. Deploy in minutes to give Claude and other AI assistants deep knowledge about n8n's 525+ workflow automation nodes.
@@ -221,6 +221,7 @@ These tools allow you to manage n8n workflows directly. Configure with `N8N_API_
- **`n8n_update_workflow`** - Update existing workflows
- **`n8n_delete_workflow`** - Delete workflows permanently
- **`n8n_list_workflows`** - List workflows with filtering and pagination
- **`n8n_validate_workflow`** - Validate workflows already in n8n by ID (NEW in v2.6.3)
#### Execution Management
- **`n8n_trigger_webhook_workflow`** - Trigger workflows via webhook URL
@@ -474,6 +475,14 @@ Current database coverage (n8n v1.99.1):
## 🔄 Recent Updates
### v2.6.3 - n8n Instance Workflow Validation
- ✅ **NEW**: `n8n_validate_workflow` tool - Validate workflows directly from n8n instance by ID
- ✅ **FETCHES**: Retrieves workflow from n8n API and runs comprehensive validation
- ✅ **CONSISTENT**: Uses same WorkflowValidator for reliability
- ✅ **FLEXIBLE**: Supports all validation profiles and options
- ✅ **INTEGRATED**: Part of complete workflow lifecycle management
- ✅ **SIMPLE**: AI agents need only workflow ID, no JSON required
### v2.6.2 - Enhanced Workflow Creation Validation
- ✅ **NEW**: Node type validation - Verifies node types actually exist in n8n
- ✅ **FIXED**: Critical issue with `nodes-base.webhook` validation - now caught before database lookup
@@ -577,6 +586,7 @@ You are an expert in n8n automation software. Your role is to answer questions a
- `validate_node_minimal(nodeType, config)` - Quick required fields check
- `validate_node_operation(nodeType, config, profile)` - Full smart validation
- `validate_workflow(workflow)` - Complete workflow validation including AI connections
- `n8n_validate_workflow({id: 'workflow-id'})` - Validate workflows already in n8n (NEW!)
5. **AI Tool Integration** (when building AI workflows):
- `get_node_as_tool_info(nodeType)` - Learn how to use ANY node as AI tool
@@ -590,6 +600,7 @@ You are an expert in n8n automation software. Your role is to answer questions a
- **Use validate_node_minimal first** - fastest way to check required fields
- **Avoid get_node_info** - returns 100KB+ of data; use get_node_essentials instead
- **Pre-built templates exist** - check get_node_for_task() for common scenarios
- **Validate existing workflows** - use n8n_validate_workflow() to check workflows in n8n
## Response Structure
@@ -626,6 +637,13 @@ You are an expert in n8n automation software. Your role is to answer questions a
3. validate_node_minimal() on the configuration
4. Provide ready-to-use solution
### n8n Workflow Management (if API configured)
1. n8n_list_workflows() // see existing workflows
2. n8n_get_workflow({id: 'workflow-id'}) // fetch specific workflow
3. n8n_validate_workflow({id: 'workflow-id'}) // validate existing workflow
4. n8n_update_workflow() // update if validation shows issues
5. n8n_trigger_webhook_workflow() // execute via webhook
## Important Rules
- Start with essentials, not full node info

View File

@@ -1,6 +1,6 @@
{
"name": "n8n-mcp",
"version": "2.6.2",
"version": "2.6.3",
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
"main": "dist/index.js",
"scripts": {
@@ -32,6 +32,7 @@
"test:ai-workflow-validation": "node dist/scripts/test-ai-workflow-validation.js",
"test:mcp-tools": "node dist/scripts/test-mcp-tools.js",
"test:n8n-manager": "node dist/scripts/test-n8n-manager-integration.js",
"test:n8n-validate-workflow": "node dist/scripts/test-n8n-validate-workflow.js",
"test:typeversion-validation": "node dist/scripts/test-typeversion-validation.js",
"db:rebuild": "node dist/scripts/rebuild-database.js",
"db:init": "node -e \"new (require('./dist/services/sqlite-storage-service').SQLiteStorageService)(); console.log('Database initialized')\"",

View File

@@ -20,6 +20,9 @@ import {
} from '../utils/n8n-errors';
import { logger } from '../utils/logger';
import { z } from 'zod';
import { WorkflowValidator } from '../services/workflow-validator';
import { EnhancedConfigValidator } from '../services/enhanced-config-validator';
import { NodeRepository } from '../database/node-repository';
// Singleton n8n API client instance
let apiClient: N8nApiClient | null = null;
@@ -80,6 +83,16 @@ const listWorkflowsSchema = z.object({
excludePinnedData: z.boolean().optional(),
});
const validateWorkflowSchema = z.object({
id: z.string(),
options: z.object({
validateNodes: z.boolean().optional(),
validateConnections: z.boolean().optional(),
validateExpressions: z.boolean().optional(),
profile: z.enum(['minimal', 'runtime', 'ai-friendly', 'strict']).optional(),
}).optional(),
});
const triggerWebhookSchema = z.object({
webhookUrl: z.string().url(),
httpMethod: z.enum(['GET', 'POST', 'PUT', 'DELETE']).optional(),
@@ -473,6 +486,94 @@ export async function handleListWorkflows(args: unknown): Promise<McpToolRespons
}
}
export async function handleValidateWorkflow(
args: unknown,
repository: NodeRepository
): Promise<McpToolResponse> {
try {
const client = ensureApiConfigured();
const input = validateWorkflowSchema.parse(args);
// First, fetch the workflow from n8n
const workflowResponse = await handleGetWorkflow({ id: input.id });
if (!workflowResponse.success) {
return workflowResponse; // Return the error from fetching
}
const workflow = workflowResponse.data as Workflow;
// Create validator instance using the provided repository
const validator = new WorkflowValidator(repository, EnhancedConfigValidator);
// Run validation
const validationResult = await validator.validateWorkflow(workflow, input.options);
// Format the response (same format as the regular validate_workflow tool)
const response: any = {
valid: validationResult.valid,
workflowId: workflow.id,
workflowName: workflow.name,
summary: {
totalNodes: validationResult.statistics.totalNodes,
enabledNodes: validationResult.statistics.enabledNodes,
triggerNodes: validationResult.statistics.triggerNodes,
validConnections: validationResult.statistics.validConnections,
invalidConnections: validationResult.statistics.invalidConnections,
expressionsValidated: validationResult.statistics.expressionsValidated,
errorCount: validationResult.errors.length,
warningCount: validationResult.warnings.length
}
};
if (validationResult.errors.length > 0) {
response.errors = validationResult.errors.map(e => ({
node: e.nodeName || 'workflow',
message: e.message,
details: e.details
}));
}
if (validationResult.warnings.length > 0) {
response.warnings = validationResult.warnings.map(w => ({
node: w.nodeName || 'workflow',
message: w.message,
details: w.details
}));
}
if (validationResult.suggestions.length > 0) {
response.suggestions = validationResult.suggestions;
}
return {
success: true,
data: response
};
} catch (error) {
if (error instanceof z.ZodError) {
return {
success: false,
error: 'Invalid input',
details: { errors: error.errors }
};
}
if (error instanceof N8nApiError) {
return {
success: false,
error: getUserFriendlyErrorMessage(error),
code: error.code
};
}
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error occurred'
};
}
}
// Execution Management Handlers
export async function handleTriggerWebhookWorkflow(args: unknown): Promise<McpToolResponse> {
@@ -688,7 +789,8 @@ export async function handleListAvailableTools(): Promise<McpToolResponse> {
{ name: 'n8n_get_workflow_minimal', description: 'Get minimal workflow info' },
{ name: 'n8n_update_workflow', description: 'Update existing workflows' },
{ name: 'n8n_delete_workflow', description: 'Delete workflows' },
{ name: 'n8n_list_workflows', description: 'List workflows with filters' }
{ name: 'n8n_list_workflows', description: 'List workflows with filters' },
{ name: 'n8n_validate_workflow', description: 'Validate workflow from n8n instance' }
]
},
{

View File

@@ -242,6 +242,10 @@ export class N8NDocumentationMCPServer {
return n8nHandlers.handleDeleteWorkflow(args);
case 'n8n_list_workflows':
return n8nHandlers.handleListWorkflows(args);
case 'n8n_validate_workflow':
await this.ensureInitialized();
if (!this.repository) throw new Error('Repository not initialized');
return n8nHandlers.handleValidateWorkflow(args, this.repository);
case 'n8n_trigger_webhook_workflow':
return n8nHandlers.handleTriggerWebhookWorkflow(args);
case 'n8n_get_execution':
@@ -1215,8 +1219,9 @@ Full documentation is being prepared. For now, use get_node_essentials for confi
purpose: "Configure nodes with the right settings"
},
"3. Validate": {
tools: ["validate_node_minimal", "validate_node_operation", "validate_workflow"],
purpose: "Ensure your workflow is correct before deployment"
tools: ["validate_node_minimal", "validate_node_operation", "validate_workflow", "n8n_validate_workflow"],
purpose: "Ensure your workflow is correct before deployment",
new: "n8n_validate_workflow - Validate workflows already in n8n by ID"
},
"4. Deploy": {
tools: ["n8n_create_workflow", "n8n_update_workflow", "n8n_list_workflows"],
@@ -1234,7 +1239,8 @@ Full documentation is being prepared. For now, use get_node_essentials for confi
"2. get_node_essentials('nodes-base.slack') - Get configuration",
"3. validate_node_operation() - Validate settings",
"4. n8n_create_workflow() - Deploy to n8n",
"5. n8n_trigger_webhook_workflow() - Execute via webhook"
"5. n8n_validate_workflow({id: 'workflow-id'}) - Validate deployed workflow",
"6. n8n_trigger_webhook_workflow() - Execute via webhook"
]
}
}

View File

@@ -202,6 +202,43 @@ export const n8nManagementTools: ToolDefinition[] = [
}
}
},
{
name: 'n8n_validate_workflow',
description: `Validate a workflow from n8n instance by ID. Fetches the workflow and runs comprehensive validation including node configurations, connections, and expressions. Returns detailed validation report with errors, warnings, and suggestions.`,
inputSchema: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'Workflow ID to validate'
},
options: {
type: 'object',
description: 'Validation options',
properties: {
validateNodes: {
type: 'boolean',
description: 'Validate node configurations (default: true)'
},
validateConnections: {
type: 'boolean',
description: 'Validate workflow connections (default: true)'
},
validateExpressions: {
type: 'boolean',
description: 'Validate n8n expressions (default: true)'
},
profile: {
type: 'string',
enum: ['minimal', 'runtime', 'ai-friendly', 'strict'],
description: 'Validation profile to use (default: runtime)'
}
}
}
},
required: ['id']
}
},
// Execution Management Tools
{

View File

@@ -0,0 +1,113 @@
#!/usr/bin/env ts-node
/**
* Test script for the n8n_validate_workflow tool
*
* This script tests the new tool that fetches a workflow from n8n
* and validates it using the existing validation logic.
*/
import { config } from 'dotenv';
import { handleValidateWorkflow } from '../mcp/handlers-n8n-manager';
import { NodeRepository } from '../database/node-repository';
import { createDatabaseAdapter } from '../database/database-adapter';
import { Logger } from '../utils/logger';
import * as path from 'path';
// Load environment variables
config();
const logger = new Logger({ prefix: '[TestN8nValidateWorkflow]' });
async function testN8nValidateWorkflow() {
try {
// Check if n8n API is configured
if (!process.env.N8N_API_URL || !process.env.N8N_API_KEY) {
logger.error('N8N_API_URL and N8N_API_KEY must be set in environment variables');
process.exit(1);
}
logger.info('n8n API Configuration:', {
url: process.env.N8N_API_URL,
hasApiKey: !!process.env.N8N_API_KEY
});
// Initialize database
const dbPath = path.join(process.cwd(), 'data', 'nodes.db');
const db = await createDatabaseAdapter(dbPath);
const repository = new NodeRepository(db);
// Test cases
const testCases = [
{
name: 'Validate existing workflow with all options',
args: {
id: '1', // Replace with an actual workflow ID from your n8n instance
options: {
validateNodes: true,
validateConnections: true,
validateExpressions: true,
profile: 'runtime'
}
}
},
{
name: 'Validate with minimal profile',
args: {
id: '1', // Replace with an actual workflow ID
options: {
profile: 'minimal'
}
}
},
{
name: 'Validate connections only',
args: {
id: '1', // Replace with an actual workflow ID
options: {
validateNodes: false,
validateConnections: true,
validateExpressions: false
}
}
}
];
// Run test cases
for (const testCase of testCases) {
logger.info(`\nRunning test: ${testCase.name}`);
logger.info('Input:', JSON.stringify(testCase.args, null, 2));
try {
const result = await handleValidateWorkflow(testCase.args, repository);
if (result.success) {
logger.info('✅ Validation completed successfully');
logger.info('Result:', JSON.stringify(result.data, null, 2));
} else {
logger.error('❌ Validation failed');
logger.error('Error:', result.error);
if (result.details) {
logger.error('Details:', JSON.stringify(result.details, null, 2));
}
}
} catch (error) {
logger.error('❌ Test case failed with exception:', error);
}
logger.info('-'.repeat(80));
}
logger.info('\n✅ All tests completed');
} catch (error) {
logger.error('Test script failed:', error);
process.exit(1);
}
}
// Run the test
testN8nValidateWorkflow().catch(error => {
logger.error('Unhandled error:', error);
process.exit(1);
});