n8n-mcp 2.59.3 → 2.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +19 -0
- package/README.md +16 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +144 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js +1 -1
- package/dist/mcp/tools-documentation.d.ts +2 -2
- package/dist/mcp/tools-documentation.d.ts.map +1 -1
- package/dist/mcp/tools-documentation.js +16 -6
- package/dist/mcp/tools-documentation.js.map +1 -1
- package/dist/mcp/tools-n8n-manager.d.ts +2 -0
- package/dist/mcp/tools-n8n-manager.d.ts.map +1 -1
- package/dist/mcp/tools-n8n-manager.js +9 -1
- package/dist/mcp/tools-n8n-manager.js.map +1 -1
- package/dist/services/node-specific-validators.d.ts +7 -0
- package/dist/services/node-specific-validators.d.ts.map +1 -1
- package/dist/services/node-specific-validators.js +211 -11
- package/dist/services/node-specific-validators.js.map +1 -1
- package/dist/services/workflow-diff-engine.d.ts.map +1 -1
- package/dist/services/workflow-diff-engine.js +2 -2
- package/dist/services/workflow-diff-engine.js.map +1 -1
- package/package.json +2 -2
- package/ui-apps/dist/execution-history/index.html +58 -89
- package/ui-apps/dist/health-dashboard/index.html +58 -89
- package/ui-apps/dist/operation-result/index.html +58 -89
- package/ui-apps/dist/validation-summary/index.html +58 -89
- package/ui-apps/dist/workflow-list/index.html +58 -89
package/.env.example
CHANGED
|
@@ -122,6 +122,25 @@ AUTH_TOKEN=your-secure-token-here
|
|
|
122
122
|
# Default: (empty - all tools enabled)
|
|
123
123
|
# DISABLED_TOOLS=
|
|
124
124
|
|
|
125
|
+
# Per-Operation Tool Filtering
|
|
126
|
+
# Disable specific operations within a tool without losing its read paths.
|
|
127
|
+
# Useful for sensitive deployments that need read-only access
|
|
128
|
+
# to tools that bundle read and write operations under one name.
|
|
129
|
+
#
|
|
130
|
+
# Format: Semicolon-separated list of <tool_name>:<comma_separated_operations>
|
|
131
|
+
# Operation names match the action / mode enum values in each tool's schema.
|
|
132
|
+
#
|
|
133
|
+
# Eligible tools and their operations:
|
|
134
|
+
# n8n_executions — action: get, list, delete
|
|
135
|
+
# n8n_workflow_versions — mode: list, get, rollback, delete, prune
|
|
136
|
+
#
|
|
137
|
+
# Read-only deployment recipe (blocks all destructive operations):
|
|
138
|
+
# DISABLED_TOOL_OPERATIONS=n8n_workflow_versions:delete,rollback,prune;n8n_executions:delete
|
|
139
|
+
#
|
|
140
|
+
# Combine with n8n API key RBAC for defence in depth.
|
|
141
|
+
# Default: (empty - all operations enabled)
|
|
142
|
+
# DISABLED_TOOL_OPERATIONS=
|
|
143
|
+
|
|
125
144
|
# =========================
|
|
126
145
|
# MULTI-TENANT CONFIGURATION
|
|
127
146
|
# =========================
|
package/README.md
CHANGED
|
@@ -389,6 +389,22 @@ These tools require `N8N_API_URL` and `N8N_API_KEY` in your configuration.
|
|
|
389
389
|
#### System Tools
|
|
390
390
|
- **`n8n_health_check`** - Check n8n API connectivity and features
|
|
391
391
|
|
|
392
|
+
### Read-Only Deployment
|
|
393
|
+
|
|
394
|
+
For governance-sensitive environments, use both env vars together. Fully disable purely write/destructive tools:
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
DISABLED_TOOLS=n8n_create_workflow,n8n_update_full_workflow,n8n_update_partial_workflow,n8n_delete_workflow,n8n_autofix_workflow,n8n_deploy_template,n8n_test_workflow,n8n_generate_workflow,n8n_manage_credentials,n8n_manage_datatable
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
For tools that bundle read and write operations under one name, block only the destructive operations while keeping `list` and `get`:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
DISABLED_TOOL_OPERATIONS=n8n_workflow_versions:delete,rollback,prune;n8n_executions:delete
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Combine with a read-only n8n API key (Settings → API in your n8n instance) for defence in depth. See [Read-Only Deployment Recipe](./docs/HTTP_DEPLOYMENT.md#read-only-deployment-recipe) for the full setup guide.
|
|
407
|
+
|
|
392
408
|
## Documentation
|
|
393
409
|
|
|
394
410
|
- [Self-Hosting Guide](./docs/SELF_HOSTING.md) - npx, Docker, Railway, and local installation
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export declare class N8NDocumentationMCPServer {
|
|
|
19
19
|
private previousToolTimestamp;
|
|
20
20
|
private earlyLogger;
|
|
21
21
|
private disabledToolsCache;
|
|
22
|
+
private disabledToolOperationsCache;
|
|
23
|
+
private filteredToolDefinitionsCache;
|
|
22
24
|
private useSharedDatabase;
|
|
23
25
|
private sharedDbState;
|
|
24
26
|
private isShutdown;
|
|
@@ -36,6 +38,8 @@ export declare class N8NDocumentationMCPServer {
|
|
|
36
38
|
private dbHealthChecked;
|
|
37
39
|
private validateDatabaseHealth;
|
|
38
40
|
private getDisabledTools;
|
|
41
|
+
private getDisabledToolOperations;
|
|
42
|
+
private buildFilteredToolDefinitions;
|
|
39
43
|
private setupHandlers;
|
|
40
44
|
private sanitizeValidationResult;
|
|
41
45
|
private validateToolParams;
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAgDA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAA2B,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,cAAc,EAAyB,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAgHnE,UAAU,gBAAgB;IACxB,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,EAAE,CAAgC;IAC1C,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,qBAAqB,CAAsB;IACnD,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,uBAAuB,CAAC,CAA0B;IAC1D,OAAO,CAAC,qBAAqB,CAA0C;gBAE3D,eAAe,CAAC,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,gBAAgB;IAmGzG,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,yBAAyB;IAWjC,OAAO,CAAC,cAAc;IAoBhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YA+Cd,kBAAkB;YAoDlB,wBAAwB;IA0BtC,OAAO,CAAC,kBAAkB;YA6CZ,iBAAiB;IAa/B,OAAO,CAAC,eAAe,CAAkB;YAE3B,sBAAsB;IAgDpC,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/server.js
CHANGED
|
@@ -88,6 +88,8 @@ class N8NDocumentationMCPServer {
|
|
|
88
88
|
this.previousToolTimestamp = Date.now();
|
|
89
89
|
this.earlyLogger = null;
|
|
90
90
|
this.disabledToolsCache = null;
|
|
91
|
+
this.disabledToolOperationsCache = null;
|
|
92
|
+
this.filteredToolDefinitionsCache = null;
|
|
91
93
|
this.useSharedDatabase = false;
|
|
92
94
|
this.sharedDbState = null;
|
|
93
95
|
this.isShutdown = false;
|
|
@@ -389,6 +391,102 @@ class N8NDocumentationMCPServer {
|
|
|
389
391
|
this.disabledToolsCache = new Set(tools);
|
|
390
392
|
return this.disabledToolsCache;
|
|
391
393
|
}
|
|
394
|
+
getDisabledToolOperations() {
|
|
395
|
+
if (this.disabledToolOperationsCache !== null) {
|
|
396
|
+
return this.disabledToolOperationsCache;
|
|
397
|
+
}
|
|
398
|
+
const result = new Map();
|
|
399
|
+
let envVal = process.env.DISABLED_TOOL_OPERATIONS || '';
|
|
400
|
+
if (!envVal) {
|
|
401
|
+
this.disabledToolOperationsCache = result;
|
|
402
|
+
this.filteredToolDefinitionsCache = new Map();
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
if (envVal.length > 10000) {
|
|
406
|
+
logger_1.logger.warn(`DISABLED_TOOL_OPERATIONS environment variable too long (${envVal.length} chars), truncating to 10000`);
|
|
407
|
+
envVal = envVal.substring(0, 10000);
|
|
408
|
+
}
|
|
409
|
+
let entries = envVal.split(';').map(e => e.trim()).filter(Boolean);
|
|
410
|
+
if (entries.length > 50) {
|
|
411
|
+
logger_1.logger.warn(`DISABLED_TOOL_OPERATIONS contains ${entries.length} entries, limiting to first 50`);
|
|
412
|
+
entries = entries.slice(0, 50);
|
|
413
|
+
}
|
|
414
|
+
for (const entry of entries) {
|
|
415
|
+
const colonIdx = entry.indexOf(':');
|
|
416
|
+
if (colonIdx === -1)
|
|
417
|
+
continue;
|
|
418
|
+
const toolName = entry.substring(0, colonIdx).trim();
|
|
419
|
+
const opsStr = entry.substring(colonIdx + 1).trim();
|
|
420
|
+
if (!toolName || !opsStr)
|
|
421
|
+
continue;
|
|
422
|
+
const ops = opsStr.split(',').map(o => o.trim().toLowerCase()).filter(Boolean);
|
|
423
|
+
if (ops.length === 0)
|
|
424
|
+
continue;
|
|
425
|
+
const existing = result.get(toolName) ?? new Set();
|
|
426
|
+
ops.forEach(op => existing.add(op));
|
|
427
|
+
result.set(toolName, existing);
|
|
428
|
+
}
|
|
429
|
+
for (const [toolName, ops] of result) {
|
|
430
|
+
const paramName = tools_n8n_manager_1.TOOL_OPERATION_PARAM[toolName];
|
|
431
|
+
if (!paramName) {
|
|
432
|
+
logger_1.logger.warn(`DISABLED_TOOL_OPERATIONS: unknown tool '${toolName}' — no per-operation filtering applied. Eligible tools: ${Object.keys(tools_n8n_manager_1.TOOL_OPERATION_PARAM).join(', ')}`);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const tool = tools_n8n_manager_1.n8nManagementTools.find(t => t.name === toolName);
|
|
436
|
+
const enumValues = tool?.inputSchema?.properties?.[paramName]?.enum ?? [];
|
|
437
|
+
for (const op of ops) {
|
|
438
|
+
if (enumValues.length > 0 && !enumValues.includes(op)) {
|
|
439
|
+
logger_1.logger.warn(`DISABLED_TOOL_OPERATIONS: '${op}' is not a valid ${paramName} for '${toolName}' (valid: ${enumValues.join(', ')}); it will have no effect.`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if (result.size > 0) {
|
|
444
|
+
const summary = [...result.entries()]
|
|
445
|
+
.map(([t, ops]) => `${t}: [${[...ops].join(', ')}]`)
|
|
446
|
+
.join('; ');
|
|
447
|
+
logger_1.logger.info(`Disabled tool operations configured: ${summary}`);
|
|
448
|
+
}
|
|
449
|
+
this.disabledToolOperationsCache = result;
|
|
450
|
+
this.filteredToolDefinitionsCache = this.buildFilteredToolDefinitions(result);
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
buildFilteredToolDefinitions(disabledOps) {
|
|
454
|
+
const cache = new Map();
|
|
455
|
+
for (const [toolName, ops] of disabledOps) {
|
|
456
|
+
const paramName = tools_n8n_manager_1.TOOL_OPERATION_PARAM[toolName];
|
|
457
|
+
if (!paramName)
|
|
458
|
+
continue;
|
|
459
|
+
const original = tools_n8n_manager_1.n8nManagementTools.find(t => t.name === toolName);
|
|
460
|
+
if (!original)
|
|
461
|
+
continue;
|
|
462
|
+
const cloned = JSON.parse(JSON.stringify(original));
|
|
463
|
+
const param = cloned.inputSchema?.properties?.[paramName];
|
|
464
|
+
if (param?.enum) {
|
|
465
|
+
param.enum = param.enum.filter(v => !ops.has(v.toLowerCase()));
|
|
466
|
+
if (param.enum.length === 0) {
|
|
467
|
+
logger_1.logger.warn(`DISABLED_TOOL_OPERATIONS: all operations for '${toolName}' are disabled ` +
|
|
468
|
+
`but the tool still appears in ListTools. ` +
|
|
469
|
+
`Consider adding '${toolName}' to DISABLED_TOOLS instead.`);
|
|
470
|
+
}
|
|
471
|
+
if (param.description) {
|
|
472
|
+
const disabledList = [...ops].join(', ');
|
|
473
|
+
param.description = `${param.description} (disabled by server policy: ${disabledList})`;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const disabledList = [...ops].join(', ');
|
|
477
|
+
cloned.description = `${cloned.description}\n\n> Operations disabled by server policy: ${disabledList}`;
|
|
478
|
+
const destructive = tools_n8n_manager_1.DESTRUCTIVE_TOOL_OPERATIONS[toolName];
|
|
479
|
+
if (destructive && cloned.annotations) {
|
|
480
|
+
const remaining = param?.enum ?? [];
|
|
481
|
+
const stillDestructive = remaining.some(v => destructive.has(String(v).toLowerCase()));
|
|
482
|
+
if (!stillDestructive) {
|
|
483
|
+
cloned.annotations = { ...cloned.annotations, readOnlyHint: true, destructiveHint: false };
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
cache.set(toolName, cloned);
|
|
487
|
+
}
|
|
488
|
+
return cache;
|
|
489
|
+
}
|
|
392
490
|
setupHandlers() {
|
|
393
491
|
this.server.setRequestHandler(types_js_1.InitializeRequestSchema, async (request) => {
|
|
394
492
|
const clientVersion = request.params.protocolVersion;
|
|
@@ -471,6 +569,10 @@ class N8NDocumentationMCPServer {
|
|
|
471
569
|
description: tool.description
|
|
472
570
|
});
|
|
473
571
|
});
|
|
572
|
+
const disabledToolOps = this.getDisabledToolOperations();
|
|
573
|
+
if (disabledToolOps.size > 0 && this.filteredToolDefinitionsCache) {
|
|
574
|
+
tools = tools.map(tool => this.filteredToolDefinitionsCache.get(tool.name) ?? tool);
|
|
575
|
+
}
|
|
474
576
|
ui_1.UIAppRegistry.injectToolMeta(tools);
|
|
475
577
|
return { tools };
|
|
476
578
|
});
|
|
@@ -493,7 +595,8 @@ class N8NDocumentationMCPServer {
|
|
|
493
595
|
message: `Tool '${name}' is not available in this deployment. It has been disabled via DISABLED_TOOLS environment variable.`,
|
|
494
596
|
tool: name
|
|
495
597
|
}, null, 2)
|
|
496
|
-
}]
|
|
598
|
+
}],
|
|
599
|
+
isError: true
|
|
497
600
|
};
|
|
498
601
|
}
|
|
499
602
|
let processedArgs = args;
|
|
@@ -542,6 +645,30 @@ class N8NDocumentationMCPServer {
|
|
|
542
645
|
if (processedArgs) {
|
|
543
646
|
processedArgs = JSON.parse(JSON.stringify(processedArgs));
|
|
544
647
|
}
|
|
648
|
+
const disabledToolOps = this.getDisabledToolOperations();
|
|
649
|
+
const disabledOpsForTool = disabledToolOps.get(name);
|
|
650
|
+
if (disabledOpsForTool && disabledOpsForTool.size > 0) {
|
|
651
|
+
const paramName = tools_n8n_manager_1.TOOL_OPERATION_PARAM[name];
|
|
652
|
+
if (paramName) {
|
|
653
|
+
const requestedOp = processedArgs?.[paramName];
|
|
654
|
+
if (requestedOp && disabledOpsForTool.has(String(requestedOp).toLowerCase())) {
|
|
655
|
+
logger_1.logger.warn(`Attempted to call disabled operation: ${name}.${requestedOp}`);
|
|
656
|
+
return {
|
|
657
|
+
content: [{
|
|
658
|
+
type: 'text',
|
|
659
|
+
text: JSON.stringify({
|
|
660
|
+
error: 'OPERATION_DISABLED',
|
|
661
|
+
message: `Operation '${requestedOp}' on tool '${name}' is disabled by server policy.`,
|
|
662
|
+
tool: name,
|
|
663
|
+
operation: requestedOp,
|
|
664
|
+
disabledOperations: [...disabledOpsForTool]
|
|
665
|
+
}, null, 2)
|
|
666
|
+
}],
|
|
667
|
+
isError: true
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
545
672
|
const isAdditionalTool = this.additionalToolsByName.has(name);
|
|
546
673
|
try {
|
|
547
674
|
logger_1.logger.debug(`Executing tool: ${name}`, (0, redaction_1.summarizeToolCallArgs)(processedArgs));
|
|
@@ -1008,6 +1135,17 @@ class N8NDocumentationMCPServer {
|
|
|
1008
1135
|
if (disabledTools.has(name)) {
|
|
1009
1136
|
throw new Error(`Tool '${name}' is disabled via DISABLED_TOOLS environment variable`);
|
|
1010
1137
|
}
|
|
1138
|
+
const disabledToolOps = this.getDisabledToolOperations();
|
|
1139
|
+
const disabledOpsForTool = disabledToolOps.get(name);
|
|
1140
|
+
if (disabledOpsForTool && disabledOpsForTool.size > 0) {
|
|
1141
|
+
const paramName = tools_n8n_manager_1.TOOL_OPERATION_PARAM[name];
|
|
1142
|
+
if (paramName) {
|
|
1143
|
+
const requestedOp = args[paramName];
|
|
1144
|
+
if (requestedOp && disabledOpsForTool.has(String(requestedOp).toLowerCase())) {
|
|
1145
|
+
throw new Error(`Operation '${requestedOp}' on tool '${name}' is disabled by server policy`);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1011
1149
|
logger_1.logger.info(`Tool execution: ${name}`, (0, redaction_1.summarizeToolCallArgs)(args));
|
|
1012
1150
|
if (typeof args !== 'object' || args === null) {
|
|
1013
1151
|
throw new Error(`Invalid arguments for tool ${name}: expected object, got ${typeof args}`);
|
|
@@ -2403,7 +2541,7 @@ Full documentation is being prepared. For now, use get_node_essentials for confi
|
|
|
2403
2541
|
totalVersions: versions.length,
|
|
2404
2542
|
hasVersionHistory: versions.length > 0
|
|
2405
2543
|
};
|
|
2406
|
-
this.cache.set(cacheKey, summary,
|
|
2544
|
+
this.cache.set(cacheKey, summary, 86400);
|
|
2407
2545
|
return summary;
|
|
2408
2546
|
}
|
|
2409
2547
|
versionMetadataUnavailable(nodeType, extra = {}) {
|
|
@@ -2998,10 +3136,12 @@ Full documentation is being prepared. For now, use get_node_essentials for confi
|
|
|
2998
3136
|
};
|
|
2999
3137
|
}
|
|
3000
3138
|
async getToolsDocumentation(topic, depth = 'essentials') {
|
|
3139
|
+
const disabledToolOps = this.getDisabledToolOperations();
|
|
3001
3140
|
if (!topic || topic === 'overview') {
|
|
3002
|
-
return (0, tools_documentation_1.getToolsOverview)(depth);
|
|
3141
|
+
return (0, tools_documentation_1.getToolsOverview)(depth, disabledToolOps.size > 0 ? disabledToolOps : undefined);
|
|
3003
3142
|
}
|
|
3004
|
-
|
|
3143
|
+
const toolDisabledOps = disabledToolOps.get(topic);
|
|
3144
|
+
return (0, tools_documentation_1.getToolDocumentation)(topic, depth, toolDisabledOps);
|
|
3005
3145
|
}
|
|
3006
3146
|
async connect(transport) {
|
|
3007
3147
|
await this.ensureInitialized();
|