extract_code
Extract code nodes from n8n workflows into separate files for improved editing and organization.
Instructions
Extract code nodes to separate files in workflows/nodes/ for better editing
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| workflow | No | Specific workflow to extract code from (optional, extracts all if not specified) |
Input Schema (JSON Schema)
{
"properties": {
"workflow": {
"description": "Specific workflow to extract code from (optional, extracts all if not specified)",
"type": "string"
}
},
"type": "object"
}
Implementation Reference
- src/tools/handler.ts:202-222 (handler)Main handler implementation for the MCP 'extract_code' tool. Delegates to NodeManager.extractNodes() for specific workflows or extractAllNodes() for all workflows.case 'extract_code': const codeManager = new NodeManager(this.workflowsPath); await codeManager.initialize(); const workflowToExtract = args?.workflow as string | undefined; if (workflowToExtract) { const workflowPath = path.join(this.workflowsPath, 'flows', `${workflowToExtract}.json`); const result = await codeManager.extractNodes(workflowPath); return { content: [{ type: 'text', text: result.extracted.length > 0 ? `✅ Extracted ${result.extracted.length} code nodes from ${workflowToExtract}\n\n` + result.extracted.map((n: any) => `• ${n.nodeName} → ${n.filePath}`).join('\n') : `📭 No code nodes found in ${workflowToExtract}` }] }; } else { return await codeManager.extractAllNodes(); }
- src/server/mcflow.ts:76-85 (registration)MCP server registration of tool handlers: list tools via getToolDefinitions() (includes extract_code) and call via ToolHandler.handleTool().this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: getToolDefinitions(), })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { return await this.toolHandler.handleTool( request.params.name, request.params.arguments ); });
- src/tools/registry.ts:349-360 (schema)Tool schema definition including input schema for the 'extract_code' tool.name: 'extract_code', description: 'Extract code nodes to separate files in workflows/nodes/ for better editing', inputSchema: { type: 'object', properties: { workflow: { type: 'string', description: 'Specific workflow to extract code from (optional, extracts all if not specified)', }, }, }, },
- src/nodes/manager.ts:134-179 (helper)Core helper function that extracts JavaScript or Python code from n8n Code nodes to separate files, adds metadata headers, and updates the node to reference the file.private async extractCodeNode(node: any, workflowName: string): Promise<ExtractedNode | null> { // Check for Python in either mode or language parameter const language = (node.parameters?.mode === 'python' || node.parameters?.language === 'python') ? 'python' : 'javascript'; const code = language === 'python' ? node.parameters?.pythonCode : node.parameters?.jsCode; // Check if already extracted if (!code || code === '' || node.parameters._nodeFile) { return null; } const safeNodeName = this.sanitizeFilename(node.name); const extension = language === 'python' ? 'py' : 'js'; const fileName = `${safeNodeName}.${extension}`; const folderPath = path.join(this.nodesBasePath, 'code', workflowName); const filePath = path.join(folderPath, fileName); // Ensure directory exists (created only when needed) await fs.mkdir(folderPath, { recursive: true }); // Write code with header const header = this.generateHeader('code', node.name, workflowName, language); await fs.writeFile(filePath, header + code); // Clear code content and store file reference const relativeFilePath = path.relative(this.workflowsPath, filePath); if (language === 'python') { node.parameters.pythonCode = ''; } else { node.parameters.jsCode = ''; } node.parameters._nodeFile = relativeFilePath; return { nodeId: node.id || node.name, nodeName: node.name, nodeType: 'code', subType: language, filePath: relativeFilePath, hash: this.hashContent(code) }; }
- src/nodes/manager.ts:536-559 (helper)Helper method called by the handler when no specific workflow is provided; iterates over all workflow JSON files and extracts nodes from them.async extractAllNodes(): Promise<any> { const flowsDir = path.join(this.workflowsPath, 'flows'); const files = await fs.readdir(flowsDir); const results = []; for (const file of files) { if (file.endsWith('.json') && !file.includes('package.json')) { const filePath = path.join(flowsDir, file); const result = await this.extractNodes(filePath); if (result.extracted.length > 0) { results.push({ workflow: file.replace('.json', ''), extracted: result.extracted }); } } } return { content: [{ type: 'text', text: this.formatExtractionResults(results) }] };