Skip to main content
Glama
ifmelate

n8n-workflow-builder-mcp

by ifmelate

add_connection

Create a connection between nodes in an n8n workflow by specifying source and target node IDs, their respective handles, and the workflow name.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
source_node_idYesThe ID of the source node for the connection
source_node_output_nameYesThe name of the output handle on the source node (e.g., 'main')
target_node_idYesThe ID of the target node for the connection
target_node_input_indexNoThe index for the target node's input handle (default: 0)
target_node_input_nameYesThe name of the input handle on the target node (e.g., 'main')
workflow_nameYesThe Name of the workflow to add the connection to

Implementation Reference

  • Main handler function that adds a connection between two nodes in an n8n workflow. Validates compatibility, checks for duplicates, updates the workflow.connections object, and persists changes.
    const createConnection = async (params) => {
        try {
            const {
                workflowId,
                sourceNodeId,
                targetNodeId,
                sourceOutput = 'main',
                targetInput = 'main'
            } = params;
    
            logger.info('Creating connection in workflow', {
                workflowId,
                sourceNodeId,
                targetNodeId,
                sourceOutput,
                targetInput
            });
    
            // Load workflow
            const workflow = await workflowStorage.loadWorkflow(workflowId);
            if (!workflow) {
                throw new Error(`Workflow with ID ${workflowId} not found`);
            }
    
            // Verify nodes exist
            const sourceNode = workflow.nodes.find(node => node.id === sourceNodeId);
            const targetNode = workflow.nodes.find(node => node.id === targetNodeId);
    
            if (!sourceNode) {
                throw new Error(`Source node with ID ${sourceNodeId} not found`);
            }
    
            if (!targetNode) {
                throw new Error(`Target node with ID ${targetNodeId} not found`);
            }
    
            // Check for self-connections
            if (sourceNodeId === targetNodeId) {
                throw new Error('Cannot create a connection from a node to itself');
            }
    
            // Verify connection compatibility
            const isCompatible = await checkConnectionCompatibility(sourceNode, targetNode, sourceOutput, targetInput);
            if (!isCompatible) {
                throw new Error(`Connection between ${sourceNode.type} and ${targetNode.type} is not compatible`);
            }
    
            // Initialize connections object if needed
            if (!workflow.connections) {
                workflow.connections = {};
            }
    
            if (!workflow.connections[sourceNodeId]) {
                workflow.connections[sourceNodeId] = {};
            }
    
            if (!workflow.connections[sourceNodeId][sourceOutput]) {
                workflow.connections[sourceNodeId][sourceOutput] = [];
            }
    
            // Check if connection already exists
            const existingConnection = workflow.connections[sourceNodeId][sourceOutput].find(
                conn => conn.node === targetNodeId && conn.type === targetInput
            );
    
            if (existingConnection) {
                logger.info('Connection already exists, skipping creation', {
                    sourceNodeId,
                    targetNodeId,
                    sourceOutput,
                    targetInput
                });
                return {
                    success: true,
                    workflow,
                    message: 'Connection already exists',
                    alreadyExists: true
                };
            }
    
            // Add connection with proper index
            const connectionsCount = workflow.connections[sourceNodeId][sourceOutput].length;
            workflow.connections[sourceNodeId][sourceOutput].push({
                node: targetNodeId,
                type: targetInput,
                index: connectionsCount
            });
    
            // Update workflow timestamp
            workflow.updatedAt = new Date().toISOString();
    
            // Save updated workflow to the same file
            const filePath = workflowId.includes('/') || workflowId.includes('\\') ?
                workflowId : `${workflowId}.json`;
    
            await workflowStorage.saveWorkflow(workflow.id || 'workflow', workflow, filePath);
    
            return {
                success: true,
                workflow,
                message: `Connection created from ${sourceNodeId}:${sourceOutput} to ${targetNodeId}:${targetInput}`
            };
        } catch (error) {
            logger.error('Error creating connection', { error: error.message });
            throw new Error(`Failed to create connection: ${error.message}`);
        }
    };
  • Registers the MCP tool using createTool, providing description, input schema, and linking to the createConnection handler.
    const createConnectionTool = createTool(
        'Create a connection between two nodes in a workflow',
        {
            workflowId: {
                type: 'string',
                description: 'ID or path of the workflow to modify'
            },
            sourceNodeId: {
                type: 'string',
                description: 'ID of the source node'
            },
            targetNodeId: {
                type: 'string',
                description: 'ID of the target node'
            },
            sourceOutput: {
                type: 'string',
                description: 'Output name on source node (default: "main")',
                optional: true
            },
            targetInput: {
                type: 'string',
                description: 'Input name on target node (default: "main")',
                optional: true
            }
        },
        createConnection
    );
  • Input schema definition for the add_connection tool parameters.
        workflowId: {
            type: 'string',
            description: 'ID or path of the workflow to modify'
        },
        sourceNodeId: {
            type: 'string',
            description: 'ID of the source node'
        },
        targetNodeId: {
            type: 'string',
            description: 'ID of the target node'
        },
        sourceOutput: {
            type: 'string',
            description: 'Output name on source node (default: "main")',
            optional: true
        },
        targetInput: {
            type: 'string',
            description: 'Input name on target node (default: "main")',
            optional: true
        }
    },
  • Helper function to validate if a connection between two nodes is compatible before adding it.
    const checkConnectionCompatibility = async (sourceNode, targetNode, sourceOutput = 'main', targetInput = 'main') => {
        try {
            // Get node type definitions
            const sourceNodeDef = await getNodeTypeDefinition(sourceNode.type);
            const targetNodeDef = await getNodeTypeDefinition(targetNode.type);
    
            if (!sourceNodeDef || !targetNodeDef) {
                logger.warn('Unable to validate connection compatibility due to missing node definitions', {
                    sourceType: sourceNode.type,
                    targetType: targetNode.type
                });
                // Default to allowing connection if we can't validate
                return true;
            }
    
            // Check for trigger nodes - triggers can only be source nodes, not target nodes
            const sourceCategories = new Set(sourceNodeDef.categories || []);
            const targetCategories = new Set(targetNodeDef.categories || []);
    
            if (targetCategories.has('Trigger')) {
                logger.warn('Invalid connection: Target node is a Trigger node', {
                    targetType: targetNode.type
                });
                return false;
            }
    
            // Additional compatibility checks could be added here based on node definitions
            // For now, we'll return true for most connections as n8n is quite flexible
    
            return true;
        } catch (error) {
            logger.error('Error checking connection compatibility', {
                error: error.message,
                sourceNode: sourceNode.id,
                targetNode: targetNode.id
            });
            // Default to allowing connection if we encounter an error during validation
            return true;
        }
    };
  • Central registration where connection tools, including createConnectionTool (add_connection), are grouped and exported for MCP use.
    // Connection management tools
    const connectionTools = {
        create: createConnectionTool,
        remove: removeConnectionTool,
        removeAll: removeNodeConnectionsTool
    };
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Tool has no description.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness1/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Tool has no description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Tool has no description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Tool has no description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose1/5

Does the description clearly state what the tool does and how it differs from similar tools?

Tool has no description.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Tool has no description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/ifmelate/n8n-workflow-builder-mcp'

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