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
    };

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