@path58/p58-n8n 0.2.7 → 0.2.9
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/CHANGELOG.md +14 -0
- package/dist/mcp/server.bundle.cjs +64 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.9] - 2026-03-11
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`execute_workflow` `not_found` guidance** — When the webhook POST completes but no execution record is found in n8n (rare timing race), the response now includes actionable guidance to retry instead of the opaque `"Execution status: not_found."` message.
|
|
13
|
+
- **`setup_check` DB health** — Now runs a live `SELECT 1` against the database and reports `db_connected` and `db_error` (exact error string) in the diagnostic output. `catalog_ready` now reflects actual DB reachability instead of always returning `true`. Issues list surfaces DB errors (e.g., circuit breaker) with guidance.
|
|
14
|
+
|
|
15
|
+
## [0.2.8] - 2026-03-11
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Webhook path extraction for `build_workflow` workflows** — `extractWebhookPath` now correctly reads the top-level `node.webhookId` set by `addWebhookIdIfNeeded()` in `build_workflow`. Previously it only checked `parameters.webhookId` and `parameters.path`, causing the path to always be null for `build_workflow`-created webhook workflows, leading to wrong webhook URLs.
|
|
20
|
+
- **Webhook 404 after activation (timing)** — `test_workflow` and `execute_workflow` now wait 3 seconds (up from 1.5s) after activating a clone workflow before POSTing. If a 404 is still received, they retry up to 3 times with backoff (1s, 2s). This handles n8n 2.x's async webhook registration.
|
|
21
|
+
|
|
8
22
|
## [0.2.7] - 2026-03-11
|
|
9
23
|
|
|
10
24
|
### Fixed
|
|
@@ -18473,7 +18473,7 @@ var import_types22 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
18473
18473
|
var config = {
|
|
18474
18474
|
// Server identity
|
|
18475
18475
|
SERVER_NAME: "p58-n8n",
|
|
18476
|
-
SERVER_VERSION: "0.2.
|
|
18476
|
+
SERVER_VERSION: "0.2.9",
|
|
18477
18477
|
// Database configuration (from environment)
|
|
18478
18478
|
SUPABASE_URL: process.env.SUPABASE_URL,
|
|
18479
18479
|
SUPABASE_KEY: process.env.SUPABASE_KEY,
|
|
@@ -37464,7 +37464,7 @@ function extractWebhookPath(workflow) {
|
|
|
37464
37464
|
if (!trigger)
|
|
37465
37465
|
return null;
|
|
37466
37466
|
const params = trigger.parameters ?? {};
|
|
37467
|
-
const shortPath = typeof params.path === "string" && params.path.length > 0 && params.path || typeof params.webhookId === "string" && params.webhookId.length > 0 && params.webhookId || null;
|
|
37467
|
+
const shortPath = typeof params.path === "string" && params.path.length > 0 && params.path || typeof params.webhookId === "string" && params.webhookId.length > 0 && params.webhookId || typeof trigger.webhookId === "string" && trigger.webhookId.length > 0 && trigger.webhookId || null;
|
|
37468
37468
|
if (!shortPath)
|
|
37469
37469
|
return null;
|
|
37470
37470
|
const wfId = workflow.id;
|
|
@@ -37580,15 +37580,28 @@ async function testViaClone(workflow, triggerType, testPayload, timeoutMs, apiCo
|
|
|
37580
37580
|
result_summary: "Test clone could not be activated \u2014 check credentials in n8n Settings \u2192 Credentials."
|
|
37581
37581
|
};
|
|
37582
37582
|
}
|
|
37583
|
-
await new Promise((r) => setTimeout(r,
|
|
37584
|
-
|
|
37585
|
-
|
|
37586
|
-
|
|
37587
|
-
|
|
37588
|
-
|
|
37589
|
-
|
|
37583
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
37584
|
+
let webhookPosted = false;
|
|
37585
|
+
for (let attempt = 0; attempt < 3 && !webhookPosted; attempt++) {
|
|
37586
|
+
try {
|
|
37587
|
+
if (attempt > 0)
|
|
37588
|
+
await new Promise((r) => setTimeout(r, 1e3 * attempt));
|
|
37589
|
+
await postWebhook(buildN8nHostUrl(), webhookPath, testPayload, Math.min(timeoutMs, 15e3));
|
|
37590
|
+
webhookPosted = true;
|
|
37591
|
+
} catch (webhookErr) {
|
|
37592
|
+
const errMsg = webhookErr instanceof Error ? webhookErr.message : String(webhookErr);
|
|
37593
|
+
const is404 = errMsg.includes("404") || errMsg.includes("not found");
|
|
37594
|
+
const isTimeout = errMsg.includes("timeout");
|
|
37595
|
+
if (isTimeout) {
|
|
37596
|
+
webhookPosted = true;
|
|
37597
|
+
break;
|
|
37598
|
+
}
|
|
37599
|
+
if (!is404 || attempt === 2)
|
|
37600
|
+
throw webhookErr;
|
|
37601
|
+
import_logging31.logger.debug("test_workflow: webhook 404 on attempt, retrying", { attempt, webhookPath });
|
|
37602
|
+
}
|
|
37590
37603
|
}
|
|
37591
|
-
await new Promise((r) => setTimeout(r,
|
|
37604
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
37592
37605
|
const deadline = Date.now() + Math.min(timeoutMs, 3e4);
|
|
37593
37606
|
let latestExecId = null;
|
|
37594
37607
|
let nodeDebug;
|
|
@@ -37930,15 +37943,27 @@ async function executeViaClone(config3, workflow, inputData, timeoutMs) {
|
|
|
37930
37943
|
note: "Execution clone could not be activated. This typically means credentials referenced by the workflow are not configured in n8n. Check n8n Settings \u2192 Credentials."
|
|
37931
37944
|
};
|
|
37932
37945
|
}
|
|
37933
|
-
await new Promise((r) => setTimeout(r,
|
|
37946
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
37934
37947
|
const payload = inputData ?? buildDefaultWebhookPayload();
|
|
37935
|
-
|
|
37936
|
-
|
|
37937
|
-
|
|
37938
|
-
|
|
37939
|
-
|
|
37940
|
-
|
|
37941
|
-
|
|
37948
|
+
let webhookPosted = false;
|
|
37949
|
+
for (let attempt = 0; attempt < 3 && !webhookPosted; attempt++) {
|
|
37950
|
+
try {
|
|
37951
|
+
if (attempt > 0)
|
|
37952
|
+
await new Promise((r) => setTimeout(r, 1e3 * attempt));
|
|
37953
|
+
await postWebhook(buildN8nHostUrl(), webhookPath, payload, Math.min(timeoutMs, 15e3));
|
|
37954
|
+
webhookPosted = true;
|
|
37955
|
+
} catch (webhookErr) {
|
|
37956
|
+
const errMsg = webhookErr instanceof Error ? webhookErr.message : String(webhookErr);
|
|
37957
|
+
const is404 = errMsg.includes("404") || errMsg.includes("not found");
|
|
37958
|
+
const isTimeout = errMsg.includes("timeout");
|
|
37959
|
+
if (isTimeout) {
|
|
37960
|
+
webhookPosted = true;
|
|
37961
|
+
break;
|
|
37962
|
+
}
|
|
37963
|
+
if (!is404 || attempt === 2)
|
|
37964
|
+
throw webhookErr;
|
|
37965
|
+
import_logging32.logger.debug("execute_workflow: webhook 404 on attempt, retrying", { attempt, cloneId });
|
|
37966
|
+
}
|
|
37942
37967
|
}
|
|
37943
37968
|
const { executionId, node_debug, executionStatus, executionError } = await fetchLatestExecutionDebug(config3, cloneId, timeoutMs);
|
|
37944
37969
|
if (executionStatus === "success") {
|
|
@@ -37948,7 +37973,7 @@ async function executeViaClone(config3, workflow, inputData, timeoutMs) {
|
|
|
37948
37973
|
} catch {
|
|
37949
37974
|
}
|
|
37950
37975
|
}
|
|
37951
|
-
const note = executionStatus === "error" && executionError ? `Execution failed: ${executionError}. See node_debug for the failing node details. Fix the issue and call execute_workflow again.` : executionStatus === "success" ? `Workflow executed successfully via temporary clone. Original workflow (${workflow.id}) is now active.` : `Execution status: ${executionStatus}.`;
|
|
37976
|
+
const note = executionStatus === "error" && executionError ? `Execution failed: ${executionError}. See node_debug for the failing node details. Fix the issue and call execute_workflow again.` : executionStatus === "success" ? `Workflow executed successfully via temporary clone. Original workflow (${workflow.id}) is now active.` : executionStatus === "not_found" ? `Webhook POST completed but no execution record was found in n8n. This can happen when n8n drops the execution before recording it. Retry execute_workflow once \u2014 if it fails again, check n8n logs for errors.` : `Execution status: ${executionStatus}.`;
|
|
37952
37977
|
return {
|
|
37953
37978
|
executionId,
|
|
37954
37979
|
result: { status: executionStatus, node_debug },
|
|
@@ -44440,6 +44465,7 @@ When values are collected, marks matching factory.gaps entries as resolved for a
|
|
|
44440
44465
|
};
|
|
44441
44466
|
|
|
44442
44467
|
// dist/mcp/tools/handlers/setup-check.js
|
|
44468
|
+
init_validatorPostgresClient();
|
|
44443
44469
|
var SETUP_GUIDE_URL2 = "https://github.com/tsvika58/p58-n8n/blob/main/docs/AGENT_INSTALL.md";
|
|
44444
44470
|
var N8N_PROBE_TIMEOUT_MS = 2e3;
|
|
44445
44471
|
var N8N_PROBE_PORTS = [5678, 5679];
|
|
@@ -44472,7 +44498,16 @@ function buildToolCounts() {
|
|
|
44472
44498
|
const tier1 = OFFLINE_TOOLS.size;
|
|
44473
44499
|
return { tier1, tier2_7: total - tier1 };
|
|
44474
44500
|
}
|
|
44475
|
-
function
|
|
44501
|
+
async function checkDbHealth() {
|
|
44502
|
+
try {
|
|
44503
|
+
await validatorQuery("SELECT 1 AS ok", []);
|
|
44504
|
+
return { connected: true };
|
|
44505
|
+
} catch (err) {
|
|
44506
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
44507
|
+
return { connected: false, error: msg };
|
|
44508
|
+
}
|
|
44509
|
+
}
|
|
44510
|
+
function collectIssues(apiKeySet, n8nConnected, probes, dbConnected, dbError) {
|
|
44476
44511
|
const issues = [];
|
|
44477
44512
|
if (!apiKeySet) {
|
|
44478
44513
|
issues.push("N8N_API_KEY not set \u2014 Tier 2-7 deploy tools unavailable");
|
|
@@ -44490,6 +44525,10 @@ function collectIssues(apiKeySet, n8nConnected, probes) {
|
|
|
44490
44525
|
if (apiKeySet && !n8nConnected) {
|
|
44491
44526
|
issues.push("N8N_API_KEY is set but n8n is unreachable \u2014 check N8N_API_URL and ensure n8n is running");
|
|
44492
44527
|
}
|
|
44528
|
+
if (!dbConnected) {
|
|
44529
|
+
const detail = dbError ? `: ${dbError}` : "";
|
|
44530
|
+
issues.push(`Database unavailable${detail} \u2014 catalog features degraded, pattern fallback active`);
|
|
44531
|
+
}
|
|
44493
44532
|
return issues;
|
|
44494
44533
|
}
|
|
44495
44534
|
async function buildReport() {
|
|
@@ -44502,7 +44541,8 @@ async function buildReport() {
|
|
|
44502
44541
|
if (!n8nUrl) {
|
|
44503
44542
|
probes = await discoverN8nInstances();
|
|
44504
44543
|
}
|
|
44505
|
-
const
|
|
44544
|
+
const dbHealth = await checkDbHealth();
|
|
44545
|
+
const issues = collectIssues(apiKeySet, n8nConnected, probes, dbHealth.connected, dbHealth.error);
|
|
44506
44546
|
const toolCounts = buildToolCounts();
|
|
44507
44547
|
const report = {
|
|
44508
44548
|
server_version: config.SERVER_VERSION,
|
|
@@ -44511,7 +44551,9 @@ async function buildReport() {
|
|
|
44511
44551
|
n8n_connected: n8nConnected,
|
|
44512
44552
|
n8n_api_key_set: apiKeySet,
|
|
44513
44553
|
credential_count: credentialCount,
|
|
44514
|
-
catalog_ready:
|
|
44554
|
+
catalog_ready: dbHealth.connected,
|
|
44555
|
+
db_connected: dbHealth.connected,
|
|
44556
|
+
...dbHealth.error ? { db_error: dbHealth.error } : {},
|
|
44515
44557
|
tools_available: toolCounts,
|
|
44516
44558
|
issues,
|
|
44517
44559
|
setup_guide: SETUP_GUIDE_URL2
|