Skip to main content

Overview

A workflow in n8n is a directed graph of nodes connected by edges that define the flow of data. The n8n-MCP server provides comprehensive workflow validation to ensure your automation runs correctly.

Workflow Structure

Basic Components

interface Workflow {
  nodes: Node[];              // Array of node configurations
  connections: Connections;    // Connection graph
  settings?: Settings;         // Workflow-level settings
  name?: string;              // Workflow name
  active?: boolean;           // Whether workflow is active
}

Node Structure

interface Node {
  id: string;                 // Unique node identifier
  name: string;               // Display name
  type: string;               // Node type (e.g., "n8n-nodes-base.webhook")
  typeVersion: number;        // Node type version
  position: [number, number]; // [x, y] coordinates
  parameters: Record<string, any>;  // Node configuration
  credentials?: Record<string, any>; // Credential references
  disabled?: boolean;         // Whether node is disabled
}
Example Node:
{
  "id": "webhook-1",
  "name": "Webhook Trigger",
  "type": "n8n-nodes-base.webhook",
  "typeVersion": 1,
  "position": [250, 300],
  "parameters": {
    "path": "my-webhook",
    "httpMethod": "POST",
    "responseMode": "onReceived"
  }
}

Connection Structure

interface Connections {
  [sourceNodeName: string]: {
    [outputType: string]: Connection[][];
  };
}

interface Connection {
  node: string;     // Target node name
  type: string;     // Connection type: "main", "ai", "source"
  index: number;    // Output/input index
}
Example Connections:
{
  "Webhook Trigger": {
    "main": [
      [
        {
          "node": "HTTP Request",
          "type": "main",
          "index": 0
        }
      ]
    ]
  },
  "HTTP Request": {
    "main": [
      [
        {
          "node": "Slack",
          "type": "main",
          "index": 0
        }
      ]
    ]
  }
}
Connection Types:
  • main - Standard data flow (most common)
  • ai - AI agent tool connections (LangChain nodes)
  • source - Source data for AI operations

Workflow Validation

Validation Scope

The validate_workflow tool checks:
  • All nodes have valid configurations
  • Required parameters are set
  • Types match expected values
  • Complex structures (filter, resourceLocator) are correct
  • No syntax errors in code nodes
{
  "validateNodes": true  // Enable node validation
}
  • All connections reference existing nodes
  • Connection types are valid
  • Output/input indices are within bounds
  • No orphaned nodes (except triggers)
  • No circular dependencies
  • Connection graph is well-formed
{
  "validateConnections": true  // Enable connection validation
}
  • n8n expression syntax is correct (={{ ... }})
  • Referenced variables exist:
    • $json - Current item data
    • $node - Access other node data
    • $workflow - Workflow metadata
    • $execution - Execution info
  • Node references are valid
  • No undefined variable access
{
  "validateExpressions": true  // Enable expression validation
}

Validation Options

interface ValidationOptions {
  validateNodes?: boolean;           // Default: true
  validateConnections?: boolean;     // Default: true
  validateExpressions?: boolean;     // Default: true
  profile?: ValidationProfile;       // "minimal" | "runtime" | "ai-friendly" | "strict"
}

Validation Response

interface WorkflowValidationResult {
  valid: boolean;
  summary: {
    totalNodes: number;
    enabledNodes: number;
    triggerNodes: number;
    validConnections: number;
    invalidConnections: number;
    expressionsValidated: number;
    errorCount: number;
    warningCount: number;
  };
  errors: WorkflowError[];
  warnings: WorkflowWarning[];
  suggestions: string[];
}
Error Structure:
interface WorkflowError {
  node: string;       // Node name where error occurred
  message: string;    // Error description
  details: string;    // Additional context
}

Common Workflow Patterns

Webhook to API to Notification

{
  "nodes": [
    {
      "id": "webhook",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "contact-form",
        "httpMethod": "POST"
      }
    },
    {
      "id": "http",
      "name": "Save to CRM",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://api.crm.com/contacts",
        "method": "POST",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "email",
              "value": "={{ $json.email }}"
            }
          ]
        }
      }
    },
    {
      "id": "slack",
      "name": "Notify Team",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "resource": "message",
        "operation": "send",
        "channel": "#sales",
        "text": "New contact: {{ $json.email }}"
      }
    }
  ],
  "connections": {
    "Webhook": {
      "main": [[{"node": "Save to CRM", "type": "main", "index": 0}]]
    },
    "Save to CRM": {
      "main": [[{"node": "Notify Team", "type": "main", "index": 0}]]
    }
  }
}

Conditional Branching

{
  "nodes": [
    {
      "id": "trigger",
      "name": "Schedule",
      "type": "n8n-nodes-base.scheduleTrigger"
    },
    {
      "id": "if",
      "name": "Check Time",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "values": [
            {
              "conditions": [
                {
                  "leftValue": "={{ new Date().getHours() }}",
                  "operation": "largerEqual",
                  "rightValue": 9
                }
              ]
            }
          ]
        }
      }
    },
    {
      "id": "business-hours",
      "name": "Business Hours Action",
      "type": "n8n-nodes-base.noOp"
    },
    {
      "id": "after-hours",
      "name": "After Hours Action",
      "type": "n8n-nodes-base.noOp"
    }
  ],
  "connections": {
    "Schedule": {
      "main": [[{"node": "Check Time", "type": "main", "index": 0}]]
    },
    "Check Time": {
      "main": [
        [{"node": "Business Hours Action", "type": "main", "index": 0}],
        [{"node": "After Hours Action", "type": "main", "index": 0}]
      ]
    }
  }
}
If Node Outputs:
  • Output 0 (first array): True path
  • Output 1 (second array): False path

Error Handling

{
  "nodes": [
    {
      "id": "http",
      "name": "API Call",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://api.example.com/data"
      },
      "onError": "continueErrorOutput",
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    },
    {
      "id": "success",
      "name": "Process Success",
      "type": "n8n-nodes-base.set"
    },
    {
      "id": "error-handler",
      "name": "Handle Error",
      "type": "n8n-nodes-base.set",
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "error",
              "value": "={{ $json.error.message }}"
            }
          ]
        }
      }
    }
  ],
  "connections": {
    "API Call": {
      "main": [[{"node": "Process Success", "type": "main", "index": 0}]],
      "error": [[{"node": "Handle Error", "type": "main", "index": 0}]]
    }
  }
}
Error Output Configuration:
  • onError: "continueErrorOutput" - Route errors to error output
  • onError: "continueRegularOutput" - Continue with empty data
  • onError: "stopWorkflow" - Stop workflow execution

Connection Types

Main Connections

Standard data flow between nodes:
{
  "Source Node": {
    "main": [
      [
        {"node": "Target Node", "type": "main", "index": 0}
      ]
    ]
  }
}

Multiple Outputs

Nodes like If, Switch have multiple output paths:
{
  "If Node": {
    "main": [
      [{"node": "True Path", "type": "main", "index": 0}],
      [{"node": "False Path", "type": "main", "index": 0}]
    ]
  }
}

AI Connections

LangChain agent connections:
{
  "AI Agent": {
    "ai": [
      [
        {"node": "Tool Node", "type": "ai", "index": 0}
      ]
    ]
  }
}

Workflow Settings

interface Settings {
  executionOrder?: 'v0' | 'v1';       // Execution order version
  saveDataErrorExecution?: 'all' | 'none';  // Save error data
  saveDataSuccessExecution?: 'all' | 'none'; // Save success data
  saveManualExecutions?: boolean;     // Save manual runs
  callerPolicy?: 'workflowsFromSameOwner' | 'any'; // Who can call
  timezone?: string;                  // Workflow timezone
}

Validation Examples

Basic Validation

const result = await validate_workflow({
  workflow: {
    nodes: [...],
    connections: {...}
  }
})

if (!result.valid) {
  console.error('Validation failed:')
  result.errors.forEach(error => {
    console.error(`  [${error.node}] ${error.message}`)
  })
}

Strict Pre-Deployment Validation

const result = await validate_workflow({
  workflow: productionWorkflow,
  options: {
    validateNodes: true,
    validateConnections: true,
    validateExpressions: true,
    profile: "strict"  // Most thorough validation
  }
})

if (!result.valid) {
  throw new Error(`Cannot deploy: ${result.errors.length} errors found`)
}

// Check warnings too
if (result.warnings.length > 0) {
  console.warn('Warnings:', result.warnings)
}

Expression Validation

const result = await validate_workflow({
  workflow: {
    nodes: [
      {
        name: "Set Node",
        type: "n8n-nodes-base.set",
        parameters: {
          values: {
            string: [
              {
                name: "email",
                value: "={{ $json.user.email }}"  // Validate this expression
              }
            ]
          }
        }
      }
    ]
  },
  options: {
    validateExpressions: true
  }
})

Common Validation Errors

Missing Node Connection

{
  "node": "HTTP Request",
  "message": "Node has no input connection",
  "details": "Non-trigger nodes must have at least one input connection"
}
Fix: Connect a trigger or previous node to this node.

Invalid Connection Target

{
  "node": "Webhook",
  "message": "Connection references non-existent node 'Slak'",
  "details": "Target node 'Slak' not found in workflow"
}
Fix: Correct the node name typo or remove the invalid connection.

Expression Error

{
  "node": "Set Node",
  "message": "Invalid expression syntax in parameter 'value'",
  "details": "Unclosed bracket in expression: ={{ $json.name"
}
Fix: Close the expression: ={{ $json.name }}

Type Mismatch

{
  "node": "HTTP Request",
  "message": "Parameter 'sendBody' must be boolean, got string",
  "details": "Expected: true/false, Received: 'true'"
}
Fix: Use boolean value: "sendBody": true not "sendBody": "true"

Best Practices

Workflow Design Guidelines:
  1. Start with a trigger - Every workflow needs an entry point
  2. Use descriptive node names - “Webhook” → “Customer Form Webhook”
  3. Handle errors - Add error outputs and handlers
  4. Validate before deploy - Use strict profile validation
  5. Test expressions - Validate all ={{ }} expressions
  6. Document complex logic - Use Sticky Note nodes for comments
  7. Keep it simple - Break complex workflows into sub-workflows
  8. Avoid circular dependencies - Check connection graph

Workflow Execution Order

Nodes execute when all required inputs are ready:
{
  "settings": {
    "executionOrder": "v1"
  }
}
Benefits:
  • More intuitive
  • Better for parallel processing
  • Handles multiple inputs correctly

v0 (Legacy)

Nodes execute in linear order:
{
  "settings": {
    "executionOrder": "v0"
  }
}
Use v1 execution order for new workflows. It provides better handling of complex flows and parallel operations.

Testing Workflows

// 1. Build workflow
const workflow = {
  nodes: [...],
  connections: {...}
}

// 2. Validate structure
const validation = await validate_workflow({workflow})
if (!validation.valid) {
  throw new Error('Invalid workflow structure')
}

// 3. Validate each node
for (const node of workflow.nodes) {
  const nodeValidation = await validate_node({
    nodeType: node.type,
    config: node.parameters,
    profile: "strict"
  })
  
  if (!nodeValidation.valid) {
    console.error(`Node ${node.name} is invalid:`, nodeValidation.errors)
  }
}

// 4. Deploy with confidence

Next Steps

MCP Tools

Learn about workflow validation tools

Validation

Deep dive into validation system

Templates

Start with pre-built workflows

Node Search

Find nodes for your workflow

Build docs developers (and LLMs) love