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