n8n-mcp 2.66.2 → 2.67.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 +3 -2
- package/README.md +2 -2
- package/data/nodes.db +0 -0
- package/dist/community/community-node-fetcher.d.ts +4 -1
- package/dist/community/community-node-fetcher.d.ts.map +1 -1
- package/dist/community/community-node-fetcher.js +5 -3
- package/dist/community/community-node-fetcher.js.map +1 -1
- package/dist/community/community-node-service.d.ts +3 -0
- package/dist/community/community-node-service.d.ts.map +1 -1
- package/dist/community/community-node-service.js +59 -4
- package/dist/community/community-node-service.js.map +1 -1
- package/dist/database/node-repository.d.ts +1 -0
- package/dist/database/node-repository.d.ts.map +1 -1
- package/dist/database/node-repository.js +7 -0
- package/dist/database/node-repository.js.map +1 -1
- package/dist/mcp/handlers-n8n-manager.d.ts +2 -0
- package/dist/mcp/handlers-n8n-manager.d.ts.map +1 -1
- package/dist/mcp/handlers-n8n-manager.js +116 -28
- package/dist/mcp/handlers-n8n-manager.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +8 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-docs/workflow_management/n8n-evaluations.d.ts.map +1 -1
- package/dist/mcp/tool-docs/workflow_management/n8n-evaluations.js +32 -17
- package/dist/mcp/tool-docs/workflow_management/n8n-evaluations.js.map +1 -1
- package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.d.ts.map +1 -1
- package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js +16 -1
- package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js.map +1 -1
- package/dist/mcp/tools-documentation.js +1 -1
- package/dist/mcp/tools-n8n-manager.d.ts.map +1 -1
- package/dist/mcp/tools-n8n-manager.js +8 -7
- package/dist/mcp/tools-n8n-manager.js.map +1 -1
- package/dist/services/n8n-api-client.d.ts +4 -1
- package/dist/services/n8n-api-client.d.ts.map +1 -1
- package/dist/services/n8n-api-client.js +30 -0
- package/dist/services/n8n-api-client.js.map +1 -1
- package/dist/services/n8n-version.d.ts +1 -0
- package/dist/services/n8n-version.d.ts.map +1 -1
- package/dist/services/n8n-version.js +2 -2
- package/dist/services/n8n-version.js.map +1 -1
- package/dist/services/workflow-diff-engine.d.ts +1 -0
- package/dist/services/workflow-diff-engine.d.ts.map +1 -1
- package/dist/services/workflow-diff-engine.js +124 -23
- package/dist/services/workflow-diff-engine.js.map +1 -1
- package/dist/types/n8n-api.d.ts +9 -0
- package/dist/types/n8n-api.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -57,6 +57,8 @@ exports.handleDeleteExecution = handleDeleteExecution;
|
|
|
57
57
|
exports.handleListTestRuns = handleListTestRuns;
|
|
58
58
|
exports.handleGetTestRun = handleGetTestRun;
|
|
59
59
|
exports.handleListTestCases = handleListTestCases;
|
|
60
|
+
exports.handleTriggerTestRun = handleTriggerTestRun;
|
|
61
|
+
exports.handleCancelTestRun = handleCancelTestRun;
|
|
60
62
|
exports.handleHealthCheck = handleHealthCheck;
|
|
61
63
|
exports.handleDiagnostic = handleDiagnostic;
|
|
62
64
|
exports.handleWorkflowVersions = handleWorkflowVersions;
|
|
@@ -87,6 +89,7 @@ const n8n_api_1 = require("../config/n8n-api");
|
|
|
87
89
|
const n8n_api_2 = require("../types/n8n-api");
|
|
88
90
|
const n8n_validation_1 = require("../services/n8n-validation");
|
|
89
91
|
const node_groups_1 = require("../services/node-groups");
|
|
92
|
+
const n8n_version_1 = require("../services/n8n-version");
|
|
90
93
|
const n8n_errors_1 = require("../utils/n8n-errors");
|
|
91
94
|
const logger_1 = require("../utils/logger");
|
|
92
95
|
const zod_1 = require("zod");
|
|
@@ -304,22 +307,30 @@ const listExecutionsSchema = zod_1.z.object({
|
|
|
304
307
|
status: optionalEmptyAware(zod_1.z.enum(['success', 'error', 'waiting'])),
|
|
305
308
|
includeData: zod_1.z.boolean().optional(),
|
|
306
309
|
});
|
|
310
|
+
const testRunPathId = zod_1.z.string().trim().min(1);
|
|
307
311
|
const listTestRunsSchema = zod_1.z.object({
|
|
308
|
-
workflowId:
|
|
312
|
+
workflowId: testRunPathId,
|
|
309
313
|
status: optionalEmptyAware(zod_1.z.enum(['new', 'running', 'completed', 'error', 'cancelled'])),
|
|
310
314
|
limit: zod_1.z.number().min(1).max(250).optional(),
|
|
311
315
|
cursor: optionalEmptyAware(zod_1.z.string()),
|
|
312
316
|
});
|
|
313
317
|
const getTestRunSchema = zod_1.z.object({
|
|
314
|
-
workflowId:
|
|
315
|
-
runId:
|
|
318
|
+
workflowId: testRunPathId,
|
|
319
|
+
runId: testRunPathId,
|
|
316
320
|
});
|
|
317
321
|
const listTestCasesSchema = zod_1.z.object({
|
|
318
|
-
workflowId:
|
|
319
|
-
runId:
|
|
322
|
+
workflowId: testRunPathId,
|
|
323
|
+
runId: testRunPathId,
|
|
320
324
|
limit: zod_1.z.number().min(1).max(250).optional(),
|
|
321
325
|
cursor: optionalEmptyAware(zod_1.z.string()),
|
|
322
326
|
});
|
|
327
|
+
const triggerTestRunSchema = zod_1.z.object({
|
|
328
|
+
workflowId: testRunPathId,
|
|
329
|
+
});
|
|
330
|
+
const cancelTestRunSchema = zod_1.z.object({
|
|
331
|
+
workflowId: testRunPathId,
|
|
332
|
+
runId: testRunPathId,
|
|
333
|
+
});
|
|
323
334
|
const workflowVersionsSchema = zod_1.z.object({
|
|
324
335
|
mode: zod_1.z.enum(['list', 'get', 'rollback', 'delete', 'prune']),
|
|
325
336
|
workflowId: zod_1.z.string().optional(),
|
|
@@ -1427,33 +1438,76 @@ async function handleDeleteExecution(args, context) {
|
|
|
1427
1438
|
};
|
|
1428
1439
|
}
|
|
1429
1440
|
}
|
|
1430
|
-
const
|
|
1431
|
-
|
|
1441
|
+
const TEST_RUN_QUOTA_HINT = 'n8n rejected the request (402): the plan\'s evaluation quota is used up. It caps how many workflows may have test runs, and this workflow does not hold one of the slots. Re-run a workflow that already has runs, or raise the limit on your n8n plan.';
|
|
1442
|
+
function testRunWriteScopeHint(scope) {
|
|
1443
|
+
return `n8n rejected the request (403). The API key lacks the ${scope} scope - that scope only exists on keys created on n8n 2.32+, so re-create the key there. Other causes: evaluations not licensed on this plan, or the key's owner lacks workflow:execute on this workflow.`;
|
|
1444
|
+
}
|
|
1445
|
+
const TEST_RUN_IDS_HINT = 'Workflow or test run not found. A runId must belong to the given workflowId; check both ids.';
|
|
1446
|
+
const TEST_RUN_WORKFLOW_HINT = "Workflow not found. Check the workflowId, and that the API key's owner has access to that workflow.";
|
|
1447
|
+
const READ_TEST_RUN_BASE = {
|
|
1448
|
+
minMinor: 30,
|
|
1449
|
+
capability: 'read test runs',
|
|
1450
|
+
scopeHint: 'n8n rejected the request (403). The API key lacks testRun scopes - keys created before n8n 2.30 do not have them; re-create the API key on n8n 2.30+. Other causes: evaluations not licensed on this plan, or the key\'s owner lacks access to this workflow.',
|
|
1451
|
+
};
|
|
1452
|
+
const LIST_TEST_RUNS_ERRORS = {
|
|
1453
|
+
...READ_TEST_RUN_BASE,
|
|
1454
|
+
notFoundHint: TEST_RUN_WORKFLOW_HINT,
|
|
1455
|
+
};
|
|
1456
|
+
const READ_TEST_RUN_ERRORS = {
|
|
1457
|
+
...READ_TEST_RUN_BASE,
|
|
1458
|
+
notFoundHint: TEST_RUN_IDS_HINT,
|
|
1459
|
+
};
|
|
1460
|
+
const TRIGGER_TEST_RUN_ERRORS = {
|
|
1461
|
+
minMinor: 32,
|
|
1462
|
+
capability: 'trigger runs from the API',
|
|
1463
|
+
scopeHint: testRunWriteScopeHint('testRun:create'),
|
|
1464
|
+
notFoundHint: TEST_RUN_WORKFLOW_HINT,
|
|
1465
|
+
conflictHint: 'The workflow has no evaluation trigger node. Add an evaluation trigger (n8n-nodes-base.evaluationTrigger) pointing at a dataset, save the workflow, then trigger the run.',
|
|
1466
|
+
postRoute: true,
|
|
1467
|
+
};
|
|
1468
|
+
const CANCEL_TEST_RUN_ERRORS = {
|
|
1469
|
+
minMinor: 32,
|
|
1470
|
+
capability: 'cancel runs from the API',
|
|
1471
|
+
scopeHint: testRunWriteScopeHint('testRun:cancel'),
|
|
1472
|
+
notFoundHint: TEST_RUN_IDS_HINT,
|
|
1473
|
+
conflictHint: "The test run already finished (status completed, error, or cancelled), so there is nothing to cancel. Use action='get_run' to see its final state.",
|
|
1474
|
+
postRoute: true,
|
|
1475
|
+
};
|
|
1476
|
+
async function testRunRouteGate(statusCode, context, options) {
|
|
1477
|
+
const client = getN8nApiClient(context);
|
|
1478
|
+
const version = client ? await client.refreshVersion().catch(() => null) : null;
|
|
1479
|
+
if (version) {
|
|
1480
|
+
return (0, n8n_version_1.versionAtLeast)(version, 2, options.minMinor)
|
|
1481
|
+
? null
|
|
1482
|
+
: `The evaluation API requires n8n 2.${options.minMinor}.0 or later; this instance runs ${version.version}. Upgrade the instance to ${options.capability}.`;
|
|
1483
|
+
}
|
|
1484
|
+
const requirement = `This endpoint requires n8n 2.${options.minMinor}.0 or later, and this instance's n8n version could not be read.`;
|
|
1485
|
+
return statusCode === 405 && options.postRoute
|
|
1486
|
+
? `${requirement} It rejected POST on the route, which is what an instance predating 2.${options.minMinor}.0 does. Upgrade the instance to ${options.capability}.`
|
|
1487
|
+
: `${requirement} Either the instance predates it, or the request simply did not match. ${options.notFoundHint}`;
|
|
1488
|
+
}
|
|
1489
|
+
async function handleTestRunError(error, context, options) {
|
|
1432
1490
|
if (error instanceof zod_1.z.ZodError) {
|
|
1433
1491
|
return { success: false, error: 'Invalid input', details: { errors: error.errors } };
|
|
1434
1492
|
}
|
|
1435
1493
|
if (error instanceof n8n_errors_1.N8nApiError) {
|
|
1494
|
+
if (error.statusCode === 402) {
|
|
1495
|
+
return { success: false, error: TEST_RUN_QUOTA_HINT, code: error.code };
|
|
1496
|
+
}
|
|
1436
1497
|
if (error.statusCode === 403) {
|
|
1437
|
-
return { success: false, error:
|
|
1498
|
+
return { success: false, error: options.scopeHint, code: error.code };
|
|
1438
1499
|
}
|
|
1439
|
-
if (error.statusCode ===
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
return {
|
|
1447
|
-
success: false,
|
|
1448
|
-
error: `The evaluation API requires n8n 2.30 or later; this instance runs ${version.version}. Upgrade the instance to read test runs.`,
|
|
1449
|
-
code: error.code,
|
|
1450
|
-
};
|
|
1500
|
+
if (error.statusCode === 409 && options.conflictHint) {
|
|
1501
|
+
return { success: false, error: options.conflictHint, code: error.code };
|
|
1502
|
+
}
|
|
1503
|
+
if (error.statusCode === 404 || error.statusCode === 405) {
|
|
1504
|
+
const gate = await testRunRouteGate(error.statusCode, context, options);
|
|
1505
|
+
if (gate) {
|
|
1506
|
+
return { success: false, error: gate, code: error.code };
|
|
1451
1507
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
code: error.code,
|
|
1456
|
-
};
|
|
1508
|
+
}
|
|
1509
|
+
if (error.statusCode === 404) {
|
|
1510
|
+
return { success: false, error: options.notFoundHint, code: error.code };
|
|
1457
1511
|
}
|
|
1458
1512
|
return { success: false, error: (0, n8n_errors_1.getUserFriendlyErrorMessage)(error), code: error.code };
|
|
1459
1513
|
}
|
|
@@ -1487,7 +1541,7 @@ async function handleListTestRuns(args, context) {
|
|
|
1487
1541
|
};
|
|
1488
1542
|
}
|
|
1489
1543
|
catch (error) {
|
|
1490
|
-
return handleTestRunError(error, context);
|
|
1544
|
+
return handleTestRunError(error, context, LIST_TEST_RUNS_ERRORS);
|
|
1491
1545
|
}
|
|
1492
1546
|
}
|
|
1493
1547
|
async function handleGetTestRun(args, context) {
|
|
@@ -1501,7 +1555,7 @@ async function handleGetTestRun(args, context) {
|
|
|
1501
1555
|
};
|
|
1502
1556
|
}
|
|
1503
1557
|
catch (error) {
|
|
1504
|
-
return handleTestRunError(error, context);
|
|
1558
|
+
return handleTestRunError(error, context, READ_TEST_RUN_ERRORS);
|
|
1505
1559
|
}
|
|
1506
1560
|
}
|
|
1507
1561
|
async function handleListTestCases(args, context) {
|
|
@@ -1526,7 +1580,41 @@ async function handleListTestCases(args, context) {
|
|
|
1526
1580
|
};
|
|
1527
1581
|
}
|
|
1528
1582
|
catch (error) {
|
|
1529
|
-
return handleTestRunError(error, context);
|
|
1583
|
+
return handleTestRunError(error, context, READ_TEST_RUN_ERRORS);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
async function handleTriggerTestRun(args, context) {
|
|
1587
|
+
try {
|
|
1588
|
+
const client = ensureApiConfigured(context);
|
|
1589
|
+
const input = triggerTestRunSchema.parse(args || {});
|
|
1590
|
+
const response = await client.triggerTestRun(input.workflowId);
|
|
1591
|
+
return {
|
|
1592
|
+
success: true,
|
|
1593
|
+
data: {
|
|
1594
|
+
...response,
|
|
1595
|
+
_note: `Run started. Cases execute asynchronously - poll with action='get_run', runId='${response.id}' until status is completed, error, or cancelled.`
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
catch (error) {
|
|
1600
|
+
return handleTestRunError(error, context, TRIGGER_TEST_RUN_ERRORS);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
async function handleCancelTestRun(args, context) {
|
|
1604
|
+
try {
|
|
1605
|
+
const client = ensureApiConfigured(context);
|
|
1606
|
+
const input = cancelTestRunSchema.parse(args || {});
|
|
1607
|
+
const response = await client.cancelTestRun(input.workflowId, input.runId);
|
|
1608
|
+
return {
|
|
1609
|
+
success: true,
|
|
1610
|
+
data: {
|
|
1611
|
+
...response,
|
|
1612
|
+
_note: "Cancellation accepted. In-flight cases stop asynchronously - use action='get_run' to confirm the run reached status 'cancelled'."
|
|
1613
|
+
}
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
catch (error) {
|
|
1617
|
+
return handleTestRunError(error, context, CANCEL_TEST_RUN_ERRORS);
|
|
1530
1618
|
}
|
|
1531
1619
|
}
|
|
1532
1620
|
async function handleHealthCheck(context) {
|