Skip to main content
Glama

mcp-n8n-lint

An MCP (Model Context Protocol) server that lints n8n workflow exports for reliability problems: missing error workflows, HTTP calls without retries, retries that swallow errors, unauthenticated webhooks, hardcoded secrets, and a few readability issues.

It reads the exported workflow JSON only. It is deterministic, needs no network access and never calls the n8n API, so it is safe to run on exports you do not want to send anywhere.

Why an MCP server: an AI agent that builds or reviews n8n workflows can call lint_workflow after every change and get machine-readable findings with a one-line fix for each, instead of guessing what "reliable" means.

Install and run

Requires Node.js 20 or newer.

npm install
npm run build
npm test        # builds, then runs the vitest suite

The server speaks MCP over stdio. Run it directly with node dist/index.js, or register it in a client.

Claude Code

claude mcp add n8n-lint -- node /absolute/path/to/mcp-n8n-lint/dist/index.js

Any MCP client (JSON config)

{
  "mcpServers": {
    "n8n-lint": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-n8n-lint/dist/index.js"]
    }
  }
}

Related MCP server: n8n-ops-mcp

Tools

Tool

Input

Output

lint_workflow

workflow: the n8n export, as an object or as a JSON string

summary (count of findings per severity, plus total) and findings: a list of { ruleId, severity, node, message, fix }. node is the node name, or null for workflow-level findings. Findings are sorted error, warning, info.

list_rules

none

rules: a list of { id, name, severity, description }

explain_rule

ruleId, for example R002

id, name, severity, description, why (why the rule exists), howToFix, and unconfirmed (fields the rule relies on that the n8n docs do not confirm; see below)

Bad input (invalid JSON, no nodes array, unknown rule id) is returned as an MCP tool error, not a crash. The error text never quotes the input.

Rules

Id

Name

Severity

What it checks

R001

no-error-workflow

warning

settings.errorWorkflow is not set.

R002

http-no-retry

warning

An n8n-nodes-base.httpRequest node without retryOnFail: true.

R003

retry-with-continue

warning

retryOnFail: true together with onError set to continueRegularOutput or continueErrorOutput, or with the legacy continueOnFail: true.

R004

webhook-no-auth

warning

An n8n-nodes-base.webhook node whose parameters.authentication is absent or "none".

R005

hardcoded-secret

error

A node parameter that looks like a secret: a Bearer token, an sk-... key, a hex or base64-like string of 32+ characters, or a filled literal in a field named like apiKey, token, password, secret. Expressions (values starting with =) are ignored.

R006

disabled-node

info

A node with disabled: true.

R007

default-node-name

info

A node still named like its default (HTTP Request, Edit Fields2, Code, ...). Triggers and sticky notes are skipped.

R008

orphan-node

warning

A node (not a trigger, not a sticky note) with no incoming and no outgoing connection.

R005 never prints the value it found. Findings contain only the parameter path and the kind of match, with the value replaced by ********. Tests plant fake secrets in fixtures and assert that no part of them appears in any output.

Example

Input to lint_workflow (a small workflow with a fake placeholder token):

{
  "name": "Order intake",
  "nodes": [
    {
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": { "httpMethod": "POST", "path": "orders" },
      "position": [0, 0]
    },
    {
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://api.example.invalid/orders",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "Authorization", "value": "Bearer fake-bearer-token-0000000000000000" }
          ]
        }
      },
      "position": [200, 0]
    }
  ],
  "connections": {
    "Webhook": { "main": [[{ "node": "HTTP Request", "type": "main", "index": 0 }]] }
  },
  "settings": { "executionOrder": "v1" }
}

Output:

{
  "summary": { "error": 1, "warning": 3, "info": 1, "total": 5 },
  "findings": [
    {
      "ruleId": "R005",
      "severity": "error",
      "node": "HTTP Request",
      "message": "Parameter \"parameters.headerParameters.parameters[0].value\" looks like a hardcoded secret (literal value of \"Authorization\" header/field): ********",
      "fix": "Rotate the secret and move it into an n8n credential; clear \"parameters.headerParameters.parameters[0].value\"."
    },
    {
      "ruleId": "R001",
      "severity": "warning",
      "node": null,
      "message": "No error workflow is configured (settings.errorWorkflow is missing or empty).",
      "fix": "Set an error workflow (one that starts with an Error Trigger node) in Workflow Settings."
    },
    {
      "ruleId": "R002",
      "severity": "warning",
      "node": "HTTP Request",
      "message": "HTTP Request node has no retries (retryOnFail is not true).",
      "fix": "Turn on Retry On Fail for this node and set Max Tries and Wait Between Tries."
    },
    {
      "ruleId": "R004",
      "severity": "warning",
      "node": "Webhook",
      "message": "Webhook node does not require authentication.",
      "fix": "Set Authentication to Basic auth, Header auth or JWT auth on this node."
    },
    {
      "ruleId": "R007",
      "severity": "info",
      "node": "HTTP Request",
      "message": "Node uses a default name (\"HTTP Request\").",
      "fix": "Rename the node to describe what it does."
    }
  ]
}

How the n8n field names were checked

Field names were checked against docs.n8n.io (October 2026):

  • Confirmed in the Public API schema for the workflow and node objects: retryOnFail, maxTries, waitBetweenTries, onError, continueOnFail (marked deprecated, "use onError instead"), disabled, parameters, settings.errorWorkflow (the ID of the workflow that contains the Error Trigger node), and connections (keyed by source node name).

  • Confirmed in the n8n docs' reference for editing workflows with the n8n MCP tools (setNodeSettings): the onError values stopWorkflow, continueRegularOutput, continueErrorOutput.

  • Confirmed by example workflows embedded in the docs: the node types n8n-nodes-base.httpRequest, n8n-nodes-base.webhook and n8n-nodes-base.stickyNote, the default name HTTP Request, and the connections structure ({ "<source>": { "main": [[ { "node", "type", "index" } ]] } }).

  • Behavior: the Handle errors gracefully page says an error workflow "runs if an execution fails", and the node settings page says that On Error "Continue" proceeds despite the error. That is the basis for R001 and R003.

Pages used: Handle errors gracefully, Work with nodes, Webhook node, and the Public API reference.

Not confirmed by the documentation

These parts are based on observed export format, not documented. The rules are kept, and explain_rule repeats the note:

  • R004: parameters.authentication on the Webhook node, and the value "none". The docs list the options only by their UI labels (Basic auth, Header auth, JWT auth, None) and do not show the JSON key or values. The rule treats an absent key the same as "none", which is consistent with the documented example webhook (it has no authentication key), but this is an inference.

  • R007: default display names other than HTTP Request (for example Edit Fields). The list in the code is incomplete.

  • R008 (and R007): which node types count as triggers is decided by a type-name heuristic (type ends with Trigger, plus webhook, start, cron, interval).

  • R002: the docs describe retryOnFail as an optional boolean without stating its default. A missing field is treated as false.

  • R005: not tied to an n8n field. It is a pattern heuristic.

Limitations

  • Heuristics, not proof. R005 will produce false positives (for example a long identifier that looks like base64, or a placeholder in a token field) and false negatives (secrets split across fields, encoded, or short). R007 and R008 depend on lists and naming conventions.

  • Export formats change between n8n versions, and the rules only look at the fields listed above. Older exports, exports copied from the editor canvas (which have no settings), and workflows from other tools may be read differently. Run it on a current export if results look off.

  • Rules do not skip disabled nodes (R006 reports them, R002 to R005 and R008 still look at them), and R001 also flags a workflow that is itself an error handler (one that starts with an Error Trigger).

  • It reads one JSON document. It does not call the n8n API, check that the referenced error workflow exists, resolve credentials, run the workflow, or follow sub-workflows.

  • R002 says nothing about whether a call is safe to retry. Retrying non-idempotent requests (payments, emails) can cause duplicates.

  • It does not replace a human review. It finds a fixed set of common reliability problems, not logic errors.

  • Only the eight rules above exist.

Development

npm install
npm run build   # tsc -> dist/
npm test        # build + vitest (unit tests, fixture tests, end-to-end MCP client test)

Layout: src/rules.ts holds the rules, src/secrets.ts the secret detection, src/lint.ts the runner, src/server.ts the MCP tools. Test fixtures in tests/fixtures are synthetic workflows written for this project; all keys in them are obviously fake. Each rule has a rNNN-bad.json that triggers only that rule and a rNNN-good.json that does not trigger it.

License

MIT. See LICENSE.

Available Tools

3 tools
explain_ruleExplain lint ruleA

Explain why a rule exists and how to fix a finding. Also lists fields the rule relies on that the n8n docs do not confirm.

ParametersJSON Schema
NameRequiredDescriptionDefault
ruleIdYesRule id, for example "R002"

TDQS

A3.5/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It does disclose the content of the response (rationale, fix guidance, and docs-unconfirmed field dependencies), but says nothing about side effects, whether it is read-only, or what happens for an unknown ruleId.

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

Conciseness4/5

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

Two short sentences, front-loaded with the primary purpose and with no filler. The trailing clause about docs-unconfirmed fields is slightly cryptic but still informative rather than padding.

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?

For a simple one-parameter lookup with no output schema and no annotations, the description adequately covers what the tool returns. It leaves gaps only around error behavior for invalid rule ids and explicit relationship to the linting workflow.

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?

The single ruleId parameter is fully documented in the schema, including the 'R002' format example, so the description adds no parameter-level information. Baseline 3 applies when schema coverage is 100%.

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

Purpose4/5

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

States a specific verb and resource (explain a lint rule) and adds the useful detail that it covers both rule rationale and remediation of a finding. It is distinguishable from list_rules and lint_workflow by function, though it never names those siblings explicitly.

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

Usage Guidelines3/5

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

The phrase 'how to fix a finding' implies the natural trigger point (after lint_workflow surfaces a finding), but there is no explicit when-to-use statement, no when-not-to-use, and no routing to or from the sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lint_workflowLint n8n workflowB

Check an n8n workflow export (JSON) for reliability problems. Pass the workflow as an object or as a JSON string. Returns a severity summary and a list of findings.

ParametersJSON Schema
NameRequiredDescriptionDefault
workflowYesn8n workflow export, as an object or a JSON string

TDQS

B3.2/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full behavioral burden. "Check ... for reliability problems" implies a non-mutating analysis and it discloses the return content (severity summary plus findings), which helps. However, it does not confirm the operation is read-only, that it has no side effects on the workflow or server, or whether the workflow must already exist/be valid before linting.

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

Conciseness4/5

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

Three short sentences, front-loaded with what the tool does, followed by how to pass input and what comes back. No filler, though the input-format sentence overlaps with the schema description.

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?

For a single-parameter, non-mutating analysis tool with no output schema and full schema coverage, this is nearly sufficient: it explains input form and return shape. The main omission is the relationship to the rule-exploration siblings and any statement of statelessness/side-effect profile.

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 coverage is 100% with a single well-documented parameter, so the schema does the heavy lifting. The description's "Pass the workflow as an object or as a JSON string" largely restates the schema's own description and anyOf typing rather than adding new meaning (e.g., size limits or expected export shape). Baseline 3.

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

Purpose4/5

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

States a specific verb and resource: checking an n8n workflow export for reliability problems, and the title reinforces it. It is clearly distinct in function from list_rules and explain_rule, though it never explicitly differentiates itself from those siblings.

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

Usage Guidelines2/5

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

The description implies a use case (validating a workflow) but never states when to reach for this tool versus alternatives, nor any prerequisites such as the workflow needing to be a valid export. With sibling tools list_rules and explain_rule present, guidance about their relationship would have been valuable, and none is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_rulesList lint rulesB

List all lint rules with id, name, severity and description.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. It implies a read-only operation by saying 'List', but does not explicitly state read-only/safe behavior, auth requirements, rate limits, pagination, or ordering.

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?

A single front-loaded sentence that states the action, the resource, and the returned fields with no wasted words. It is appropriately sized for a simple list endpoint.

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?

For a zero-parameter list tool with no output schema, the description helpfully lists the returned fields (id, name, severity, description). It is mostly complete, though it omits pagination, ordering, and any behavioral context that would help an agent use it confidently.

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

Parameters4/5

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

The tool has zero parameters, so there is no parameter semantics to clarify and the baseline score is 4. The description appropriately focuses on the return fields instead.

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

Purpose4/5

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

The description states a specific verb ('List') and resource ('lint rules') and enumerates the returned fields. It is clear what the tool does, but it does not explicitly distinguish itself from sibling tools like explain_rule or lint_workflow.

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

Usage Guidelines2/5

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

There is no guidance on when to use this tool versus explain_rule or lint_workflow, nor any prerequisites, exclusions, or filtering context. The only implied usage comes from the word 'List', which is not enough to route among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedexplain_rule
    • First observedlint_workflow
    • First observedlist_rules

TDQS

A3.7/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct role: lint_workflow performs the analysis, list_rules enumerates rule metadata, and explain_rule provides rationale and fix guidance for a specific rule. There is no meaningful overlap, and an agent can easily select the right tool from the descriptions alone.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern in snake_case: lint_workflow, list_rules, explain_rule. This predictability makes the toolset easy to scan and remember.

Tool Count5/5

Three tools is exactly right for this focused linter server: one action tool and two rule-inspection tools. Each tool earns its place without redundancy or unnecessary surface area.

Completeness4/5

The core workflow of linting a workflow, listing rules, and explaining rules is fully covered. Minor gaps exist around rule configuration (e.g., enabling/disabling rules) or automated fixes, which are common in linters but not strictly necessary for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    C
    maintenance
    Safe MCP server and CLI tool for testing, scoring, and inspecting n8n workflows. Features 19 tools for workflow testing, execution traces, tiered scoring, and a built-in node catalog with 800+ node types. Designed with safety-first approach: no credential management, no secrets lifecycle, no auto-fix loops.
    19
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Provides ops-focused n8n tools for MCP-compatible agents, enabling listing, inspecting, triggering, validating, managing tags, running security audits, and safely editing n8n workflows with auto-backup and confirm gates.
    20
    7 npm
    1
    MIT