feat: add n8n_generate_workflow tool for hosted workflow generation

Add new MCP tool that enables AI-powered workflow generation from natural
language descriptions. Uses handler delegation pattern — hosting environments
inject a GenerateWorkflowHandler via EngineOptions, self-hosted instances
receive a hosted-only informational response.

Handler flows through N8NMCPEngine → SingleSessionHTTPServer →
N8NDocumentationMCPServer with helpers for createWorkflow, validateWorkflow,
autofixWorkflow, and getWorkflow.

Includes full tool documentation, tests, and corrected tools overview count.

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2026-03-31 12:32:31 +02:00
parent 3417c6701c
commit 198e773bb3
81 changed files with 784 additions and 177 deletions

View File

@@ -134,6 +134,20 @@ class ExpressionValidator {
combinedResult.valid = combinedResult.errors.length === 0;
return combinedResult;
}
static checkBareExpression(value, path, result) {
if (value.includes('{{') || value.startsWith('=')) {
return;
}
const trimmed = value.trim();
for (const { pattern, name } of this.BARE_EXPRESSION_PATTERNS) {
if (pattern.test(trimmed)) {
result.warnings.push((path ? `${path}: ` : '') +
`Possible unwrapped expression: "${trimmed}" looks like an n8n ${name} reference. ` +
`Use "={{ ${trimmed} }}" to evaluate it as an expression.`);
return;
}
}
}
static validateParametersRecursive(obj, context, result, path = '', visited = new WeakSet()) {
if (obj && typeof obj === 'object') {
if (visited.has(obj)) {
@@ -142,6 +156,7 @@ class ExpressionValidator {
visited.add(obj);
}
if (typeof obj === 'string') {
this.checkBareExpression(obj, path, result);
if (obj.includes('{{')) {
const validation = this.validateExpression(obj, context);
validation.errors.forEach(error => {
@@ -168,6 +183,16 @@ class ExpressionValidator {
}
}
exports.ExpressionValidator = ExpressionValidator;
ExpressionValidator.BARE_EXPRESSION_PATTERNS = [
{ pattern: /^\$json[.\[]/, name: '$json' },
{ pattern: /^\$node\[/, name: '$node' },
{ pattern: /^\$input\./, name: '$input' },
{ pattern: /^\$execution\./, name: '$execution' },
{ pattern: /^\$workflow\./, name: '$workflow' },
{ pattern: /^\$prevNode\./, name: '$prevNode' },
{ pattern: /^\$env\./, name: '$env' },
{ pattern: /^\$(now|today|itemIndex|runIndex)$/, name: 'built-in variable' },
];
ExpressionValidator.EXPRESSION_PATTERN = /\{\{([\s\S]+?)\}\}/g;
ExpressionValidator.VARIABLE_PATTERNS = {
json: /\$json(\.[a-zA-Z_][\w]*|\["[^"]+"\]|\['[^']+'\]|\[\d+\])*/g,