update
Modify existing n8n workflow files by providing updated JSON content and file paths to streamline automation development and maintenance.
Instructions
Update an existing n8n workflow
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the workflow file relative to workflows root | |
| workflow | Yes | The updated workflow JSON object |
Implementation Reference
- src/workflows/manager.ts:427-492 (handler)Main handler function that performs the actual update: preserves workflow metadata (ID, createdAt), writes the new JSON to file, marks as edited, updates documentation and credentials.async updateWorkflow(workflowPath: string, workflow: any): Promise<any> { try { const fullPath = path.join(this.workflowsPath, workflowPath); // Try to preserve the existing workflow ID if it exists try { const existingContent = await fs.readFile(fullPath, 'utf-8'); const existingWorkflow = JSON.parse(existingContent); // Preserve important metadata from existing workflow if (existingWorkflow.id && !workflow.id) { workflow.id = existingWorkflow.id; console.error(`Preserving workflow ID: ${workflow.id}`); } if (existingWorkflow.createdAt && !workflow.createdAt) { workflow.createdAt = existingWorkflow.createdAt; } // Always update the updatedAt timestamp workflow.updatedAt = new Date().toISOString(); } catch (readError) { // File might not exist yet or might be invalid JSON console.error('Could not read existing workflow, creating new'); } await fs.writeFile(fullPath, stringifyWorkflowFile(workflow)); // Mark as edited in change tracker const relativePath = path.relative(this.workflowsPath, fullPath); await this.changeTracker.markEdited(relativePath); // Update documentation const workflowName = path.basename(workflowPath, '.json'); try { const customInstructions = await this.documenter.getCustomInstructions(); await this.documenter.updateWorkflowDocumentation(workflowName, workflow, 'update', customInstructions); // Extract and update credentials const credentials = this.initializer.extractCredentialsFromWorkflow(workflow); if (credentials.size > 0) { await this.initializer.updateEnvExample(credentials); } // Update README with workflow list const allWorkflows = await this.getWorkflowList(); await this.initializer.updateReadmeWorkflowList(allWorkflows); } catch (docError) { console.error('Failed to update documentation:', docError); // Don't fail the workflow update if documentation fails } return { content: [ { type: 'text', text: `✅ Workflow Updated!\n\n` + `📁 File: ${workflowPath}\n` + `📝 Name: ${workflowName}\n\n` + `The workflow and documentation have been updated.`, }, ], }; } catch (error) { throw new Error(`Failed to update workflow: ${error}`); } }
- src/tools/handler.ts:42-46 (handler)ToolHandler switch case that dispatches 'update' tool calls to WorkflowManager.updateWorkflowcase 'update': return await this.workflowManager.updateWorkflow( args?.path as string, args?.workflow as any );
- src/tools/registry.ts:55-72 (schema)Input schema definition for the 'update' tool, specifying path and workflow object as required inputs.{ name: 'update', description: 'Update an existing n8n workflow', inputSchema: { type: 'object', properties: { path: { type: 'string', description: 'Path to the workflow file relative to workflows root', }, workflow: { type: 'object', description: 'The updated workflow JSON object', }, }, required: ['path', 'workflow'], }, },
- src/server/mcflow.ts:80-85 (registration)MCP server registration for tool calls, which invokes ToolHandler.handleTool for any tool including 'update'this.server.setRequestHandler(CallToolRequestSchema, async (request) => { return await this.toolHandler.handleTool( request.params.name, request.params.arguments ); });
- src/server/mcflow.ts:76-78 (registration)MCP server registration for listing tools, which returns the tool definitions including 'update' from registry.tsthis.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: getToolDefinitions(), }));