mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-24 03:13:07 +00:00
fix: add n8n 1.121 availableInMCP and callerPolicy settings support (v2.26.4) (#445)
* fix: add n8n 1.121 availableInMCP and callerPolicy settings support (v2.26.4) n8n 1.121 introduced a new workflow setting `availableInMCP` (boolean) that controls whether a workflow is "Available in MCP". The sanitization whitelist was missing this field, causing it to be silently stripped during workflow updates. Changes: - Added `availableInMCP` to Zod schema in workflowSettingsSchema - Added `availableInMCP` and `callerPolicy` to safeSettingsProperties whitelist - Both settings are now preserved during workflow updates - Settings can be toggled via updateSettings operation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Conceived by Romuald Członkowski - www.aiadvisors.pl/en * test: update tests for callerPolicy and availableInMCP whitelist changes Updated 5 tests in n8n-validation.test.ts that expected callerPolicy to be filtered out. Since callerPolicy and availableInMCP are now whitelisted (n8n 1.121+), the tests now verify these settings are preserved during workflow updates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
25784142fe
commit
bac4936c6d
12
CHANGELOG.md
12
CHANGELOG.md
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [2.26.4] - 2025-11-26
|
||||||
|
|
||||||
|
### 🔧 Fixed
|
||||||
|
|
||||||
|
- **n8n 1.121 Compatibility**: Added support for new workflow settings introduced in n8n 1.121
|
||||||
|
- Added `availableInMCP` (boolean) to settings whitelist - controls "Available in MCP" toggle
|
||||||
|
- Added `callerPolicy` to settings whitelist - was already in schema but missing from sanitization
|
||||||
|
- Both settings are now preserved during workflow updates instead of being silently stripped
|
||||||
|
- Settings can be toggled via `updateSettings` operation: `{type: "updateSettings", settings: {availableInMCP: true}}`
|
||||||
|
|
||||||
|
**Conceived by Romuald Członkowski - [AiAdvisors](https://www.aiadvisors.pl/en)**
|
||||||
|
|
||||||
## [2.26.3] - 2025-11-26
|
## [2.26.3] - 2025-11-26
|
||||||
|
|
||||||
### 🔧 Fixed
|
### 🔧 Fixed
|
||||||
|
|||||||
BIN
data/nodes.db
BIN
data/nodes.db
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-mcp",
|
"name": "n8n-mcp",
|
||||||
"version": "2.26.3",
|
"version": "2.26.4",
|
||||||
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-mcp-runtime",
|
"name": "n8n-mcp-runtime",
|
||||||
"version": "2.26.3",
|
"version": "2.26.4",
|
||||||
"description": "n8n MCP Server Runtime Dependencies Only",
|
"description": "n8n MCP Server Runtime Dependencies Only",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export const workflowSettingsSchema = z.object({
|
|||||||
executionTimeout: z.number().optional(),
|
executionTimeout: z.number().optional(),
|
||||||
errorWorkflow: z.string().optional(),
|
errorWorkflow: z.string().optional(),
|
||||||
callerPolicy: z.enum(['any', 'workflowsFromSameOwner', 'workflowsFromAList']).optional(),
|
callerPolicy: z.enum(['any', 'workflowsFromSameOwner', 'workflowsFromAList']).optional(),
|
||||||
|
availableInMCP: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Default settings for workflow creation
|
// Default settings for workflow creation
|
||||||
@@ -181,7 +182,9 @@ export function cleanWorkflowForUpdate(workflow: Workflow): Partial<Workflow> {
|
|||||||
'executionTimeout',
|
'executionTimeout',
|
||||||
'errorWorkflow',
|
'errorWorkflow',
|
||||||
'timezone',
|
'timezone',
|
||||||
'executionOrder'
|
'executionOrder',
|
||||||
|
'callerPolicy',
|
||||||
|
'availableInMCP',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (cleanedWorkflow.settings && typeof cleanedWorkflow.settings === 'object') {
|
if (cleanedWorkflow.settings && typeof cleanedWorkflow.settings === 'object') {
|
||||||
|
|||||||
@@ -403,45 +403,47 @@ describe('n8n-validation', () => {
|
|||||||
settings: {
|
settings: {
|
||||||
executionOrder: 'v1' as const,
|
executionOrder: 'v1' as const,
|
||||||
saveDataSuccessExecution: 'none' as const,
|
saveDataSuccessExecution: 'none' as const,
|
||||||
callerPolicy: 'workflowsFromSameOwner' as const, // Filtered out (not in OpenAPI spec)
|
callerPolicy: 'workflowsFromSameOwner' as const, // Now whitelisted (n8n 1.121+)
|
||||||
timeSavedPerExecution: 5, // Filtered out (UI-only property)
|
timeSavedPerExecution: 5, // Filtered out (UI-only property)
|
||||||
},
|
},
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
const cleaned = cleanWorkflowForUpdate(workflow);
|
const cleaned = cleanWorkflowForUpdate(workflow);
|
||||||
|
|
||||||
// Unsafe properties filtered out, safe properties kept
|
// Unsafe properties filtered out, safe properties kept (callerPolicy now whitelisted)
|
||||||
expect(cleaned.settings).toEqual({
|
expect(cleaned.settings).toEqual({
|
||||||
executionOrder: 'v1',
|
executionOrder: 'v1',
|
||||||
saveDataSuccessExecution: 'none'
|
saveDataSuccessExecution: 'none',
|
||||||
|
callerPolicy: 'workflowsFromSameOwner'
|
||||||
});
|
});
|
||||||
expect(cleaned.settings).not.toHaveProperty('callerPolicy');
|
|
||||||
expect(cleaned.settings).not.toHaveProperty('timeSavedPerExecution');
|
expect(cleaned.settings).not.toHaveProperty('timeSavedPerExecution');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter out callerPolicy (Issue #248 - API limitation)', () => {
|
it('should preserve callerPolicy and availableInMCP (n8n 1.121+ settings)', () => {
|
||||||
const workflow = {
|
const workflow = {
|
||||||
name: 'Test Workflow',
|
name: 'Test Workflow',
|
||||||
nodes: [],
|
nodes: [],
|
||||||
connections: {},
|
connections: {},
|
||||||
settings: {
|
settings: {
|
||||||
executionOrder: 'v1' as const,
|
executionOrder: 'v1' as const,
|
||||||
callerPolicy: 'workflowsFromSameOwner' as const, // Filtered out
|
callerPolicy: 'workflowsFromSameOwner' as const, // Now whitelisted
|
||||||
|
availableInMCP: true, // New in n8n 1.121
|
||||||
errorWorkflow: 'N2O2nZy3aUiBRGFN',
|
errorWorkflow: 'N2O2nZy3aUiBRGFN',
|
||||||
},
|
},
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
const cleaned = cleanWorkflowForUpdate(workflow);
|
const cleaned = cleanWorkflowForUpdate(workflow);
|
||||||
|
|
||||||
// callerPolicy filtered out (causes API errors), safe properties kept
|
// callerPolicy and availableInMCP now whitelisted (n8n 1.121+)
|
||||||
expect(cleaned.settings).toEqual({
|
expect(cleaned.settings).toEqual({
|
||||||
executionOrder: 'v1',
|
executionOrder: 'v1',
|
||||||
|
callerPolicy: 'workflowsFromSameOwner',
|
||||||
|
availableInMCP: true,
|
||||||
errorWorkflow: 'N2O2nZy3aUiBRGFN'
|
errorWorkflow: 'N2O2nZy3aUiBRGFN'
|
||||||
});
|
});
|
||||||
expect(cleaned.settings).not.toHaveProperty('callerPolicy');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter all settings properties correctly (Issue #248 - API design)', () => {
|
it('should preserve all whitelisted settings properties including callerPolicy (Issue #248 - updated for n8n 1.121)', () => {
|
||||||
const workflow = {
|
const workflow = {
|
||||||
name: 'Test Workflow',
|
name: 'Test Workflow',
|
||||||
nodes: [],
|
nodes: [],
|
||||||
@@ -455,14 +457,14 @@ describe('n8n-validation', () => {
|
|||||||
saveExecutionProgress: false,
|
saveExecutionProgress: false,
|
||||||
executionTimeout: 300,
|
executionTimeout: 300,
|
||||||
errorWorkflow: 'error-workflow-id',
|
errorWorkflow: 'error-workflow-id',
|
||||||
callerPolicy: 'workflowsFromAList' as const, // Filtered out (not in OpenAPI spec)
|
callerPolicy: 'workflowsFromAList' as const, // Now whitelisted (n8n 1.121+)
|
||||||
|
availableInMCP: false, // New in n8n 1.121
|
||||||
},
|
},
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
const cleaned = cleanWorkflowForUpdate(workflow);
|
const cleaned = cleanWorkflowForUpdate(workflow);
|
||||||
|
|
||||||
// Safe properties kept, unsafe properties filtered out
|
// All whitelisted properties kept including callerPolicy and availableInMCP
|
||||||
// See: https://community.n8n.io/t/api-workflow-update-endpoint-doesnt-support-setting-callerpolicy/161916
|
|
||||||
expect(cleaned.settings).toEqual({
|
expect(cleaned.settings).toEqual({
|
||||||
executionOrder: 'v0',
|
executionOrder: 'v0',
|
||||||
timezone: 'UTC',
|
timezone: 'UTC',
|
||||||
@@ -471,9 +473,10 @@ describe('n8n-validation', () => {
|
|||||||
saveManualExecutions: false,
|
saveManualExecutions: false,
|
||||||
saveExecutionProgress: false,
|
saveExecutionProgress: false,
|
||||||
executionTimeout: 300,
|
executionTimeout: 300,
|
||||||
errorWorkflow: 'error-workflow-id'
|
errorWorkflow: 'error-workflow-id',
|
||||||
|
callerPolicy: 'workflowsFromAList',
|
||||||
|
availableInMCP: false
|
||||||
});
|
});
|
||||||
expect(cleaned.settings).not.toHaveProperty('callerPolicy');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle workflows without settings gracefully', () => {
|
it('should handle workflows without settings gracefully', () => {
|
||||||
@@ -494,7 +497,6 @@ describe('n8n-validation', () => {
|
|||||||
nodes: [],
|
nodes: [],
|
||||||
connections: {},
|
connections: {},
|
||||||
settings: {
|
settings: {
|
||||||
callerPolicy: 'workflowsFromSameOwner' as const, // Filtered out
|
|
||||||
timeSavedPerExecution: 5, // Filtered out (UI-only)
|
timeSavedPerExecution: 5, // Filtered out (UI-only)
|
||||||
someOtherProperty: 'value', // Filtered out
|
someOtherProperty: 'value', // Filtered out
|
||||||
},
|
},
|
||||||
@@ -514,19 +516,19 @@ describe('n8n-validation', () => {
|
|||||||
connections: {},
|
connections: {},
|
||||||
settings: {
|
settings: {
|
||||||
executionOrder: 'v1' as const, // Whitelisted
|
executionOrder: 'v1' as const, // Whitelisted
|
||||||
callerPolicy: 'workflowsFromSameOwner' as const, // Filtered out
|
callerPolicy: 'workflowsFromSameOwner' as const, // Now whitelisted (n8n 1.121+)
|
||||||
timezone: 'America/New_York', // Whitelisted
|
timezone: 'America/New_York', // Whitelisted
|
||||||
someOtherProperty: 'value', // Filtered out
|
someOtherProperty: 'value', // Filtered out
|
||||||
},
|
},
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
const cleaned = cleanWorkflowForUpdate(workflow);
|
const cleaned = cleanWorkflowForUpdate(workflow);
|
||||||
// Should keep only whitelisted properties
|
// Should keep only whitelisted properties (callerPolicy now whitelisted)
|
||||||
expect(cleaned.settings).toEqual({
|
expect(cleaned.settings).toEqual({
|
||||||
executionOrder: 'v1',
|
executionOrder: 'v1',
|
||||||
|
callerPolicy: 'workflowsFromSameOwner',
|
||||||
timezone: 'America/New_York'
|
timezone: 'America/New_York'
|
||||||
});
|
});
|
||||||
expect(cleaned.settings).not.toHaveProperty('callerPolicy');
|
|
||||||
expect(cleaned.settings).not.toHaveProperty('someOtherProperty');
|
expect(cleaned.settings).not.toHaveProperty('someOtherProperty');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user