Skip to main content
Glama

n8n_deploy_template

Deploy workflow templates from n8n.io to your n8n instance, automatically fixing common issues and returning workflow details.

Instructions

Deploy a workflow template from n8n.io directly to your n8n instance. Deploys first, then auto-fixes common issues (expression format, typeVersions). Returns workflow ID, required credentials, and fixes applied.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
templateIdYesTemplate ID from n8n.io (required)
nameNoCustom workflow name (default: template name)
autoUpgradeVersionsNoAutomatically upgrade node typeVersions to latest supported (default: true)
autoFixNoAuto-apply fixes after deployment for expression format issues, missing = prefix, etc. (default: true)
stripCredentialsNoRemove credential references from nodes - user configures in n8n UI (default: true)

Implementation Reference

  • Core implementation of n8n_deploy_template tool. Fetches template by ID from local database, processes it (strips credentials if requested, upgrades node versions, auto-fixes issues), deploys to n8n instance via API creating inactive workflow, returns workflow ID, required credentials list, fixes applied, and n8n UI URL.
    export async function handleDeployTemplate(
      args: unknown,
      templateService: TemplateService,
      repository: NodeRepository,
      context?: InstanceContext
    ): Promise<McpToolResponse> {
      try {
        const client = ensureApiConfigured(context);
        const input = deployTemplateSchema.parse(args);
    
        // Fetch template
        const template = await templateService.getTemplate(input.templateId, 'full');
        if (!template) {
          return {
            success: false,
            error: `Template ${input.templateId} not found`,
            details: {
              hint: 'Use search_templates to find available templates',
              templateUrl: `https://n8n.io/workflows/${input.templateId}`
            }
          };
        }
    
        // Extract workflow from template (deep copy to avoid mutation)
        const workflow = JSON.parse(JSON.stringify(template.workflow));
        if (!workflow || !workflow.nodes) {
          return {
            success: false,
            error: 'Template has invalid workflow structure',
            details: { templateId: input.templateId }
          };
        }
    
        // Set workflow name
        const workflowName = input.name || template.name;
    
        // Collect required credentials before stripping
        const requiredCredentials: RequiredCredential[] = [];
        for (const node of workflow.nodes) {
          if (node.credentials && typeof node.credentials === 'object') {
            for (const [credType] of Object.entries(node.credentials)) {
              requiredCredentials.push({
                nodeType: node.type,
                nodeName: node.name,
                credentialType: credType
              });
            }
          }
        }
    
        // Strip credentials if requested
        if (input.stripCredentials) {
          workflow.nodes = workflow.nodes.map((node: any) => {
            const { credentials, ...rest } = node;
            return rest;
          });
        }
    
        // Auto-upgrade typeVersions if requested
        if (input.autoUpgradeVersions) {
          const autoFixer = new WorkflowAutoFixer(repository);
    
          // Run validation to get issues to fix
          const validator = new WorkflowValidator(repository, EnhancedConfigValidator);
          const validationResult = await validator.validateWorkflow(workflow, {
            validateNodes: true,
            validateConnections: false,
            validateExpressions: false,
            profile: 'runtime'
          });
    
          // Generate fixes focused on typeVersion upgrades
          const fixResult = await autoFixer.generateFixes(
            workflow,
            validationResult,
            [],
            { fixTypes: ['typeversion-upgrade', 'typeversion-correction'] }
          );
    
          // Apply fixes to workflow
          if (fixResult.operations.length > 0) {
            for (const op of fixResult.operations) {
              if (op.type === 'updateNode' && op.updates) {
                const node = workflow.nodes.find((n: any) =>
                  n.id === op.nodeId || n.name === op.nodeName
                );
                if (node) {
                  for (const [path, value] of Object.entries(op.updates)) {
                    if (path === 'typeVersion') {
                      node.typeVersion = value;
                    }
                  }
                }
              }
            }
          }
        }
    
        // Identify trigger type
        const triggerNode = workflow.nodes.find((n: any) =>
          n.type?.includes('Trigger') ||
          n.type?.includes('webhook') ||
          n.type === 'n8n-nodes-base.webhook'
        );
        const triggerType = triggerNode?.type?.split('.').pop() || 'manual';
    
        // Create workflow via API (always creates inactive)
        // Deploy first, then fix - this ensures the workflow exists before we modify it
        const createdWorkflow = await client.createWorkflow({
          name: workflowName,
          nodes: workflow.nodes,
          connections: workflow.connections,
          settings: workflow.settings || { executionOrder: 'v1' }
        });
    
        // Get base URL for workflow link
        const apiConfig = context ? getN8nApiConfigFromContext(context) : getN8nApiConfig();
        const baseUrl = apiConfig?.baseUrl?.replace('/api/v1', '') || '';
    
        // Auto-fix common issues after deployment (expression format, etc.)
        let fixesApplied: AppliedFix[] = [];
        let fixSummary = '';
        let autoFixStatus: 'success' | 'failed' | 'skipped' = 'skipped';
    
        if (input.autoFix) {
          try {
            // Run autofix on the deployed workflow
            const autofixResult = await handleAutofixWorkflow(
              {
                id: createdWorkflow.id,
                applyFixes: true,
                fixTypes: ['expression-format', 'typeversion-upgrade'],
                confidenceThreshold: 'medium'
              },
              repository,
              context
            );
    
            if (autofixResult.success && autofixResult.data) {
              const fixData = autofixResult.data as AutofixResultData;
              autoFixStatus = 'success';
              if (fixData.fixesApplied && fixData.fixesApplied > 0) {
                fixesApplied = fixData.fixes || [];
                fixSummary = ` Auto-fixed ${fixData.fixesApplied} issue(s).`;
              }
            }
          } catch (fixError) {
            // Log but don't fail - autofix is best-effort
            autoFixStatus = 'failed';
            logger.warn('Auto-fix failed after template deployment', {
              workflowId: createdWorkflow.id,
              error: fixError instanceof Error ? fixError.message : 'Unknown error'
            });
            fixSummary = ' Auto-fix failed (workflow deployed successfully).';
          }
        }
    
        return {
          success: true,
          data: {
            workflowId: createdWorkflow.id,
            name: createdWorkflow.name,
            active: false,
            nodeCount: workflow.nodes.length,
            triggerType,
            requiredCredentials: requiredCredentials.length > 0 ? requiredCredentials : undefined,
            url: baseUrl ? `${baseUrl}/workflow/${createdWorkflow.id}` : undefined,
            templateId: input.templateId,
            templateUrl: template.url || `https://n8n.io/workflows/${input.templateId}`,
            autoFixStatus,
            fixesApplied: fixesApplied.length > 0 ? fixesApplied : undefined
          },
          message: `Workflow "${createdWorkflow.name}" deployed successfully from template ${input.templateId}.${fixSummary} ${
            requiredCredentials.length > 0
              ? `Configure ${requiredCredentials.length} credential(s) in n8n to activate.`
              : ''
          }`
        };
      } catch (error) {
        if (error instanceof z.ZodError) {
          return {
            success: false,
            error: 'Invalid input',
            details: { errors: error.errors }
          };
        }
    
        if (error instanceof N8nApiError) {
          return {
            success: false,
            error: getUserFriendlyErrorMessage(error),
            code: error.code,
            details: error.details as Record<string, unknown> | undefined
          };
        }
    
        return {
          success: false,
          error: error instanceof Error ? error.message : 'Unknown error occurred'
        };
      }
    }
  • ToolDefinition object defining the tool name, description, and inputSchema for validation. Part of n8nManagementTools array export.
    {
      name: 'n8n_deploy_template',
      description: `Deploy a workflow template from n8n.io directly to your n8n instance. Deploys first, then auto-fixes common issues (expression format, typeVersions). Returns workflow ID, required credentials, and fixes applied.`,
      inputSchema: {
        type: 'object',
        properties: {
          templateId: {
            type: 'number',
            description: 'Template ID from n8n.io (required)'
          },
          name: {
            type: 'string',
            description: 'Custom workflow name (default: template name)'
          },
          autoUpgradeVersions: {
            type: 'boolean',
            default: true,
            description: 'Automatically upgrade node typeVersions to latest supported (default: true)'
          },
          autoFix: {
            type: 'boolean',
            default: true,
            description: 'Auto-apply fixes after deployment for expression format issues, missing = prefix, etc. (default: true)'
          },
          stripCredentials: {
            type: 'boolean',
            default: true,
            description: 'Remove credential references from nodes - user configures in n8n UI (default: true)'
          }
        },
        required: ['templateId']
      }
    }
  • The tool is defined and exported as part of the n8nManagementTools array, which is imported and registered in the MCP engine.
      {
        name: 'n8n_deploy_template',
        description: `Deploy a workflow template from n8n.io directly to your n8n instance. Deploys first, then auto-fixes common issues (expression format, typeVersions). Returns workflow ID, required credentials, and fixes applied.`,
        inputSchema: {
          type: 'object',
          properties: {
            templateId: {
              type: 'number',
              description: 'Template ID from n8n.io (required)'
            },
            name: {
              type: 'string',
              description: 'Custom workflow name (default: template name)'
            },
            autoUpgradeVersions: {
              type: 'boolean',
              default: true,
              description: 'Automatically upgrade node typeVersions to latest supported (default: true)'
            },
            autoFix: {
              type: 'boolean',
              default: true,
              description: 'Auto-apply fixes after deployment for expression format issues, missing = prefix, etc. (default: true)'
            },
            stripCredentials: {
              type: 'boolean',
              default: true,
              description: 'Remove credential references from nodes - user configures in n8n UI (default: true)'
            }
          },
          required: ['templateId']
        }
      }
    ];
  • Detailed documentation structure for the tool, used by the tools_documentation tool to provide help and examples.
    import { ToolDocumentation } from '../types';
    
    export const n8nDeployTemplateDoc: ToolDocumentation = {
      name: 'n8n_deploy_template',
      category: 'workflow_management',
      essentials: {
        description: 'Deploy a workflow template from n8n.io directly to your n8n instance. Deploys first, then auto-fixes common issues (expression format, typeVersions).',
        keyParameters: ['templateId', 'name', 'autoUpgradeVersions', 'autoFix', 'stripCredentials'],
        example: 'n8n_deploy_template({templateId: 2776, name: "My Deployed Template"})',
        performance: 'Network-dependent',
        tips: [
          'Auto-fixes expression format issues after deployment',
          'Workflow created inactive - configure credentials in n8n UI first',
          'Returns list of required credentials and fixes applied',
          'Use search_templates to find template IDs'
        ]
      },
      full: {
        description: 'Deploys a workflow template from n8n.io directly to your n8n instance. This tool deploys first, then automatically fixes common issues like missing expression prefixes (=) and outdated typeVersions. Templates are stored locally and fetched from the database. The workflow is always created in an inactive state, allowing you to configure credentials before activation.',
        parameters: {
          templateId: { type: 'number', required: true, description: 'Template ID from n8n.io (find via search_templates)' },
          name: { type: 'string', description: 'Custom workflow name (default: template name)' },
          autoUpgradeVersions: { type: 'boolean', description: 'Upgrade node typeVersions to latest supported (default: true)' },
          autoFix: { type: 'boolean', description: 'Auto-apply fixes after deployment for expression format issues, missing = prefix, etc. (default: true)' },
          stripCredentials: { type: 'boolean', description: 'Remove credential references - user configures in n8n UI (default: true)' }
        },
        returns: 'Object with workflowId, name, nodeCount, triggerType, requiredCredentials array, url, templateId, templateUrl, autoFixStatus (success/failed/skipped), and fixesApplied array',
        examples: [
          `// Deploy template with default settings (auto-fix enabled)
    n8n_deploy_template({templateId: 2776})`,
          `// Deploy with custom name
    n8n_deploy_template({
      templateId: 2776,
      name: "My Google Drive to Airtable Sync"
    })`,
          `// Deploy without auto-fix (not recommended)
    n8n_deploy_template({
      templateId: 2776,
      autoFix: false
    })`,
          `// Keep original node versions (useful for compatibility)
    n8n_deploy_template({
      templateId: 2776,
      autoUpgradeVersions: false
    })`
        ],
        useCases: [
          'Quickly deploy pre-built workflow templates',
          'Set up common automation patterns',
          'Bootstrap new projects with proven workflows',
          'Deploy templates found via search_templates'
        ],
        performance: 'Network-dependent - Typically 300-800ms (template fetch + workflow creation + autofix)',
        bestPractices: [
          'Use search_templates to find templates by use case',
          'Review required credentials in the response',
          'Check autoFixStatus in response - "success", "failed", or "skipped"',
          'Check fixesApplied in response to see what was automatically corrected',
          'Configure credentials in n8n UI before activating',
          'Test workflow before connecting to production systems'
        ],
        pitfalls: [
          '**REQUIRES N8N_API_URL and N8N_API_KEY environment variables** - tool unavailable without n8n API access',
          'Workflows created in INACTIVE state - must configure credentials and activate in n8n',
          'Templates may reference services you do not have (Slack, Google, etc.)',
          'Template database must be populated - run npm run fetch:templates if templates not found',
          'Some issues may not be auto-fixable (e.g., missing required fields that need user input)'
        ],
        relatedTools: ['search_templates', 'get_template', 'n8n_create_workflow', 'n8n_autofix_workflow']
      }
    };
Behavior4/5

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

Annotations indicate this is a non-read-only, non-destructive, open-world operation. The description adds valuable behavioral context beyond annotations: it specifies the two-step process ('Deploys first, then auto-fixes'), details what gets fixed ('expression format, typeVersions'), and describes the return values ('workflow ID, required credentials, and fixes applied'). This compensates for the lack of an output schema and provides operational insight.

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

Conciseness5/5

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

The description is efficiently structured in two sentences: the first states the core action and auto-fix feature, and the second specifies the return values. Every sentence adds value without repetition, and it's front-loaded with the main purpose. No wasted words or unnecessary details.

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

Completeness4/5

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

Given the tool's complexity (deployment with auto-fixing), lack of output schema, and annotations covering safety (non-destructive), the description is mostly complete. It explains the process, fixes applied, and return values, which addresses key behavioral aspects. However, it doesn't mention error handling, rate limits, or authentication needs, leaving minor gaps for an agent to infer.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema fully documents all 5 parameters. The description doesn't add any parameter-specific semantics beyond what's in the schema (e.g., it doesn't explain 'templateId' sourcing or 'autoFix' details). However, it implies the tool's overall behavior involves parameters like 'autoUpgradeVersions' and 'autoFix', but this is redundant with the schema. Baseline 3 is appropriate as the schema carries the burden.

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

Purpose5/5

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

The description clearly states the specific action ('Deploy a workflow template'), resource ('from n8n.io'), and destination ('to your n8n instance'), distinguishing it from siblings like 'get_template' (read-only) or 'n8n_create_workflow' (manual creation). It also mentions the auto-fix functionality, which differentiates it from basic deployment tools.

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

Usage Guidelines4/5

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

The description implies usage context by specifying it deploys 'from n8n.io directly to your n8n instance' and mentions auto-fixing, suggesting it's for template-based workflow setup. However, it doesn't explicitly state when to use this versus alternatives like 'n8n_create_workflow' (for manual creation) or 'n8n_update_full_workflow' (for modifications), nor does it mention prerequisites or exclusions.

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/czlonkowski/n8n-mcp'

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