Understanding n8n-mcp Node Version Migration Paths and Breaking Change Detection
n8n-mcp provides a full-stack version-migration pipeline that combines a static breaking-changes registry with dynamic schema diffs to detect breaking changes, calculate severity scores, and automatically migrate node configurations between versions.
The czlonkowski/n8n-mcp repository implements an intelligent migration system for n8n nodes that enables both AI tools and developers to safely upgrade workflow configurations across version boundaries. This system addresses the critical challenge of n8n-mcp node version migration by detecting breaking changes before they impact production workflows and applying automated fixes where possible. By merging hard-coded registry knowledge with live schema comparisons, the pipeline delivers actionable migration plans with confidence scoring.
The Migration Pipeline Architecture
The n8n-mcp migration system centers on three tightly integrated services that handle discovery, analysis, and execution:
BreakingChangesRegistry(src/services/breaking-changes-registry.ts) – Maintains a static list of known property changes, breakage flags, and migration strategies.BreakingChangeDetector(src/services/breaking-change-detector.ts) – Merges registry entries with live schema comparisons to produce aVersionUpgradeAnalysisobject containing severity ratings and recommendations.NodeMigrationService(src/services/node-migration-service.ts) – Consumes the analysis to apply auto-migratable changes and validate the resulting configuration.
Breaking-Changes Registry (Static Knowledge)
The BREAKING_CHANGES_REGISTRY serves as the authoritative knowledge base for n8n-mcp node version migration. Each entry maps a specific version range to a property change and includes machine-readable migration instructions.
Registry entries contain these critical fields:
nodeType– Full n8n identifier (e.g.,n8n-nodes-base.webhook) or*for global changes.fromVersion/toVersion– The specific upgrade path the entry describes.propertyName– Dot-notation path to the affected parameter (e.g.,parameters.inputFieldMapping).changeType– Classification asadded,removed,renamed,type_changed,requirement_changed, ordefault_changed.isBreaking– Boolean flag indicating whether the change breaks existing workflows.migrationStrategy– Machine-readable action such asadd_property,remove_property, orrename_propertywith default values.autoMigratable– Boolean indicating if the change can be applied without human intervention.severity–LOW,MEDIUM, orHIGHimpact rating.
Developers query the registry using helper functions defined in the same file: getBreakingChangesForNode, getAllChangesForNode, and hasBreakingChanges.
Dynamic Breaking Change Detection
While the registry covers known changes, the BreakingChangeDetector class performs dynamic breaking change detection by diffing JSON schemas stored in the SQLite database via NodeRepository.getNodeVersion.
The detection flow in BreakingChangeDetector.analyzeVersionUpgrade executes as follows:
- Registry lookup –
getRegistryChangesretrieves all matching static entries for the version pair. - Schema diff –
detectDynamicChangesflattens property trees usingflattenPropertiesfor both versions, then flags:- Added properties (breaking only if marked
required). - Removed properties (always breaking).
- Requirement changes (breaking when a property becomes required).
- Added properties (breaking only if marked
- Merge –
mergeChangesdeduplicates registry and dynamic entries, sorting results by severity. - Analysis –
calculateOverallSeverityaggregates counts of breaking versus auto-migratable changes to determine the upgrade's risk level. - Recommendations –
generateRecommendationsproduces human-readable guidance (e.g., "⚠ 2 breaking change(s) detected. Review carefully before applying.").
The resulting VersionUpgradeAnalysis object (defined at lines 33-43 of the detector file) serves as the single source of truth for downstream tooling.
Auto-Migration Service
The NodeMigrationService transforms analysis results into concrete configuration updates. The migrateNode method orchestrates the smart migration process:
- Invokes the detector to obtain a full
VersionUpgradeAnalysis. - Clones the original node and updates
typeVersionusingparseVersion. - Iterates through
analysis.changesand applies every entry whereautoMigratableequalstrueviaapplyMigration. - Collects manual actions into
remainingIssuesfor human review. - Returns a
MigrationResultcontainingappliedMigrations,remainingIssues, and aconfidencescore (HIGH,MEDIUM, orLOW).
The service also provides validateMigratedNode for lightweight sanity checks on common nodes (Webhook, Execute Workflow, etc.) and migrateWorkflowNodes for batch processing entire workflows while aggregating confidence scores across all nodes.
MCP Tool Integration
The MCP server exposes the get_node tool (declared in src/mcp/tools.ts lines 77-95) with multiple operational modes for n8n-mcp node version migration queries:
{
"mode": "breaking",
"fromVersion": "1.0",
"toVersion": "1.1"
}
When mode is set to breaking, the server routes the request through src/mcp/server.ts (lines 2899-2910) to invoke BreakingChangeDetector.hasBreakingChanges and getBreakingChangesForNode, returning a concise JSON payload. Setting mode to migrations returns the full auto-migration plan generated by NodeMigrationService.
Discovering Migration Paths
To enumerate available upgrade paths for any node, use the registry helpers:
import { getTrackedVersionsForNode } from './services/breaking-changes-registry';
const versions = getTrackedVersionsForNode('n8n-nodes-base.webhook');
// → ['1.0', '2.0', '2.1']
The getNodesWithVersionMigrations function returns every node type with at least one registry entry, enabling UI lists and documentation generators to present valid n8n-mcp node version migration options.
Practical Migration Examples
Querying Breaking Changes via MCP Client
import { MCPClient } from 'n8n-mcp';
const client = new MCPClient({ url: 'http://localhost:4000' });
async function showBreakingChanges(nodeType, from, to) {
const result = await client.callTool('get_node', {
nodeType,
mode: 'breaking',
fromVersion: from,
toVersion: to,
});
console.log(`Breaking changes for ${nodeType} ${from} → ${to}:`);
console.table(result.breakingChanges);
}
showBreakingChanges(
'n8n-nodes-base.executeWorkflow',
'1.0',
'1.1'
);
Routing: The server handles this in src/mcp/server.ts by delegating to BreakingChangeDetector.hasBreakingChanges and getBreakingChangesForNode.
Executing a Single Node Migration
import { NodeRepository } from 'n8n-mcp/src/database/node-repository';
import { NodeVersionService } from 'n8n-mcp/src/services/node-version-service';
import { BreakingChangeDetector } from 'n8n-mcp/src/services/breaking-change-detector';
import { NodeMigrationService } from 'n8n-mcp/src/services/node-migration-service';
const repo = new NodeRepository();
const versionSrv = new NodeVersionService(repo);
const detector = new BreakingChangeDetector(repo);
const migrator = new NodeMigrationService(versionSrv, detector);
const webhookNode = {
id: '1',
type: 'n8n-nodes-base.webhook',
typeVersion: 2.0,
parameters: { path: '/myhook' },
};
async function migrate() {
const result = await migrator.migrateNode(webhookNode, '2.0', '2.1');
console.log('Applied migrations:', result.appliedMigrations);
console.log('Remaining manual issues:', result.remainingIssues);
}
migrate();
The output includes appliedMigrations entries describing actions like adding webhookId with a generated UUID, driven by the migrationStrategy defined in breaking-changes-registry.ts (lines 73-86).
Batch Migrating an Entire Workflow
import { NodeMigrationService } from 'n8n-mcp/src/services/node-migration-service';
import { NodeRepository } from 'n8n-mcp/src/database/node-repository';
import { BreakingChangeDetector } from 'n8n-mcp/src/services/breaking-change-detector';
import { NodeVersionService } from 'n8n-mcp/src/services/node-version-service';
async function migrateWorkflow(workflow) {
const repo = new NodeRepository();
const versionSrv = new NodeVersionService(repo);
const detector = new BreakingChangeDetector(repo);
const migrator = new NodeMigrationService(versionSrv, detector);
const targets = {};
for (const node of workflow.nodes) {
if (node.typeVersion < 2) {
targets[node.id] = '2.1';
}
}
const report = await migrator.migrateWorkflowNodes(workflow, targets);
console.log('Overall confidence:', report.overallConfidence);
console.table(report.results.map(r => ({
nodeId: r.nodeId,
confidence: r.confidence,
remainingIssues: r.remainingIssues.length,
})));
}
This leverages NodeMigrationService.migrateWorkflowNodes (lines 78-90 of the service file) to process multiple nodes while maintaining workflow integrity.
Summary
- n8n-mcp node version migration combines a static
BREAKING_CHANGES_REGISTRYwith dynamic schema diffing to identify breaking changes between any two versions. - The
BreakingChangeDetectorproduces aVersionUpgradeAnalysiscontaining severity scores, change counts, and actionable recommendations by merging registry knowledge with live property comparisons. NodeMigrationServiceapplies auto-migratable changes (add, remove, rename, set default) while flagging manual issues, returning aconfidencerating for the migration.- The MCP server exposes these capabilities through the
get_nodetool withbreakingandmigrationsmodes for AI-driven workflow maintenance. - Registry helpers like
getTrackedVersionsForNodeenable discovery of valid upgrade paths without executing migrations.
Frequently Asked Questions
How does n8n-mcp detect breaking changes between node versions?
n8n-mcp employs a hybrid approach. First, it queries the BREAKING_CHANGES_REGISTRY in src/services/breaking-changes-registry.ts for known changes between specific versions. Second, the BreakingChangeDetector in src/services/breaking-change-detector.ts performs a dynamic diff of the JSON schemas retrieved via NodeRepository.getNodeVersion, flagging added required properties, removed properties, and requirement changes. These sources merge into a single VersionUpgradeAnalysis object.
What is the difference between registry-based and dynamic detection?
The registry provides human-curated knowledge about semantic changes (e.g., "parameter X was renamed to Y") including migration hints and auto-migration strategies. Dynamic detection compares the actual property schemas stored in the database to catch undocumented changes, type modifications, or requirement shifts that lack registry entries. The system merges both to ensure comprehensive coverage.
Can all breaking changes be automatically migrated?
No. Only changes marked with autoMigratable: true in the registry can be handled by NodeMigrationService.applyMigration. These typically include simple additions with defaults, removals, or renames. Changes requiring human judgment—such as logic-dependent value mappings or complex type conversions—appear in the remainingIssues array of the MigrationResult for manual review.
How do I check available migration paths for a specific node?
Import getTrackedVersionsForNode from src/services/breaking-changes-registry.ts and pass the node type identifier (e.g., n8n-nodes-base.webhook). This returns an array of version strings tracked in the registry. For a global view, use getNodesWithVersionMigrations to list every node type with defined migration entries, useful for building upgrade dashboards or documentation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →