@path58/p58-n8n 0.2.3 → 0.2.4
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/AGENT_INSTALL.md +5 -5
- package/CHANGELOG.md +39 -5
- package/README.md +10 -9
- package/dist/mcp/server.bundle.cjs +229 -84
- package/package.json +3 -3
package/AGENT_INSTALL.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## What is p58-n8n?
|
|
10
10
|
|
|
11
|
-
p58-n8n is an MCP server that gives LLMs the ability to validate, build, deploy, and manage n8n workflows. It provides
|
|
11
|
+
p58-n8n is an MCP server that gives LLMs the ability to validate, build, deploy, and manage n8n workflows. It provides 35 tools organized in tiers:
|
|
12
12
|
|
|
13
13
|
- **Tier 1 (offline):** `validate_workflow`, `list_nodes`, `get_operation_schema`, `suggest_fix`, `check_parameter` — work immediately, no env vars needed
|
|
14
14
|
- **Tier 2-7 (require n8n):** `build_workflow`, `list_credentials`, `activate_workflow`, `execute_workflow`, `test_workflow`, `plan_workflow`, etc. — require connection to user's n8n instance
|
|
@@ -40,7 +40,7 @@ Determine which AI client the user is using. Check for config files in this orde
|
|
|
40
40
|
| **Claude Desktop** | `~/.config/Claude/claude_desktop_config.json` | Linux |
|
|
41
41
|
| **Claude Code** | Use `claude mcp add` CLI command | All |
|
|
42
42
|
| **Cursor** | `~/.cursor/mcp.json` | All |
|
|
43
|
-
| **
|
|
43
|
+
| **Gemini CLI** | `~/.gemini/settings.json` or `~/.gemini/antigravity/mcp_config.json` | All |
|
|
44
44
|
| **VS Code (Copilot)** | `.vscode/mcp.json` in workspace | All |
|
|
45
45
|
|
|
46
46
|
**Detection method:** Check if these files exist. If multiple exist, ask the user which client they want to configure.
|
|
@@ -101,7 +101,7 @@ The API key cannot be auto-discovered. The user must provide it or create one.
|
|
|
101
101
|
|
|
102
102
|
## Step 4: Write the Configuration
|
|
103
103
|
|
|
104
|
-
### For Claude Desktop / Cursor /
|
|
104
|
+
### For Claude Desktop / Cursor / Gemini CLI / VS Code (JSON config)
|
|
105
105
|
|
|
106
106
|
Read the existing config file, then add p58-n8n inside the `mcpServers` object. Do NOT overwrite existing MCP servers.
|
|
107
107
|
|
|
@@ -159,7 +159,7 @@ The MCP server config is only read at startup. After writing the config:
|
|
|
159
159
|
| **Claude Desktop** | Quit completely (Cmd+Q on macOS), then reopen |
|
|
160
160
|
| **Claude Code** | Exit and restart the CLI session |
|
|
161
161
|
| **Cursor** | Restart Cursor (Cmd+Shift+P → Reload Window) |
|
|
162
|
-
| **
|
|
162
|
+
| **Gemini CLI** | Exit and restart the CLI session, or use the MCP refresh command |
|
|
163
163
|
|
|
164
164
|
**CRITICAL:** On macOS, closing the window is NOT enough for Claude Desktop. The user must Cmd+Q to fully quit.
|
|
165
165
|
|
|
@@ -232,4 +232,4 @@ Once installed, the user can ask their AI assistant to:
|
|
|
232
232
|
|
|
233
233
|
---
|
|
234
234
|
|
|
235
|
-
**Package:** `@path58/p58-n8n` | **npm:** https://www.npmjs.com/package/@path58/p58-n8n | **Version:** 0.2.
|
|
235
|
+
**Package:** `@path58/p58-n8n` | **npm:** https://www.npmjs.com/package/@path58/p58-n8n | **Version:** 0.2.4+
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ 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.4] - 2026-03-10
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Lazy initialization** — MCP server defers tool registration and fixer registry loading until after stdio handshake completes; eliminates cold-start timeouts on strict-timeout clients (Gemini CLI / Antigravity)
|
|
13
|
+
- **`setup_check` tool** — new Tier 7 diagnostic tool that validates server health, n8n connectivity, and database access in a single call; total tools now **35** across 7 tiers
|
|
14
|
+
- **Gemini CLI support** — installation guide and documentation updated with Gemini CLI / Antigravity configuration examples
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Documentation overhauled for v0.2.4: replaced Windsurf references with Gemini CLI throughout AGENT_INSTALL.md, README.md, and FRIEND_ONBOARDING.md
|
|
19
|
+
- Fixed broken `docs/INSTALLATION.md` links in README (file never existed) — now point to AGENT_INSTALL.md
|
|
20
|
+
- Standardized `N8N_API_URL` environment variable naming across all documentation
|
|
21
|
+
- Updated catalog counts in documentation: 1,545 nodes, 679 credentials, 35 tools
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Server initialization no longer blocks the MCP handshake — clients with < 5s timeouts can now connect reliably
|
|
26
|
+
- Startup version banner now correctly reports v0.2.4
|
|
27
|
+
- **Friend & family UX hardening** — 5 catalog tool handlers now return `CATALOG_UNREACHABLE` or `DB_NOT_CONFIGURED` with setup guide URLs instead of opaque "internal error" when database issues occur
|
|
28
|
+
- DB pool auto-sizes for catalog-only users (max 3 connections, no keepAlive) — prevents resource exhaustion for friends without n8n
|
|
29
|
+
- Startup health check confirms database connectivity before accepting tool calls
|
|
30
|
+
- Shutdown race condition eliminated — in-flight request tracker waits up to 5s for active queries before pool disposal
|
|
31
|
+
- `makeDbNotConfiguredResponse` now includes `isError: true` flag so LLMs recognize the error
|
|
32
|
+
- `plan_workflow` description updated to note that `build_workflow` requires n8n API access
|
|
33
|
+
|
|
34
|
+
## [0.2.3] - 2026-03-09
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Internal release — build and bundle pipeline fixes
|
|
39
|
+
|
|
8
40
|
## [0.2.2] - 2026-03-09
|
|
9
41
|
|
|
10
42
|
### Fixed
|
|
@@ -98,8 +130,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
98
130
|
- npm package published as `@path58/p58-n8n`
|
|
99
131
|
- ESM module support with shebang for direct `npx` execution
|
|
100
132
|
|
|
101
|
-
[0.2.
|
|
102
|
-
[0.2.
|
|
103
|
-
[0.2.
|
|
104
|
-
[0.
|
|
105
|
-
[0.
|
|
133
|
+
[0.2.4]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.2.4
|
|
134
|
+
[0.2.3]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.2.3
|
|
135
|
+
[0.2.2]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.2.2
|
|
136
|
+
[0.2.1]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.2.1
|
|
137
|
+
[0.2.0]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.2.0
|
|
138
|
+
[0.1.1]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.1.1
|
|
139
|
+
[0.1.0]: https://github.com/tsvika58/p58-n8n/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@path58/p58-n8n)
|
|
6
6
|
[](LICENSE)
|
|
7
|
-
[](https://github.com/tsvika58/p58-n8n/actions/workflows/ci.yml)
|
|
8
8
|
|
|
9
9
|
p58-n8n is an MCP server that gives your AI assistant deep knowledge of n8n — **1,545 nodes**, **12,619 operations**, **38,005 parameter rules** — so it can plan, build, validate, fix, and deploy workflows correctly. No manual iteration. No broken JSON.
|
|
10
10
|
|
|
11
|
-
> **🤖 AI Agent?** If you are an LLM assistant and a user asked you to install this MCP server, **stop here and read [`AGENT_INSTALL.md`](https://github.com/tsvika58/n8n
|
|
11
|
+
> **🤖 AI Agent?** If you are an LLM assistant and a user asked you to install this MCP server, **stop here and read [`AGENT_INSTALL.md`](https://github.com/tsvika58/p58-n8n/blob/main/AGENT_INSTALL.md)** — it has the complete autonomous installation guide with client detection, n8n auto-discovery, config templates for all clients, and verification steps. Everything you need to install p58-n8n without asking the user unnecessary questions.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -58,9 +58,9 @@ Config file location: `~/Library/Application Support/Claude/claude_desktop_confi
|
|
|
58
58
|
|
|
59
59
|
> **Note:** Validation tools (`validate_workflow`, `list_nodes`, etc.) work immediately without any env vars. The `N8N_API_URL` and `N8N_API_KEY` are only needed for deploy, execute, and credential tools.
|
|
60
60
|
|
|
61
|
-
**Cursor /
|
|
61
|
+
**Cursor / Gemini CLI** — same JSON format, add to your client's MCP config file. See [AGENT_INSTALL.md](https://github.com/tsvika58/p58-n8n/blob/main/AGENT_INSTALL.md) for all supported clients.
|
|
62
62
|
|
|
63
|
-
**LLM-assisted setup** — if you're an AI agent helping a user install p58-n8n, read [AGENT_INSTALL.md](https://github.com/tsvika58/n8n
|
|
63
|
+
**LLM-assisted setup** — if you're an AI agent helping a user install p58-n8n, read [AGENT_INSTALL.md](https://github.com/tsvika58/p58-n8n/blob/main/AGENT_INSTALL.md) for the autonomous installation guide.
|
|
64
64
|
|
|
65
65
|
### 3. Try it
|
|
66
66
|
|
|
@@ -126,7 +126,7 @@ p58-n8n uses 80% less token context than n8n-mcp by serving structured catalog d
|
|
|
126
126
|
|
|
127
127
|
---
|
|
128
128
|
|
|
129
|
-
##
|
|
129
|
+
## 35 Tools in 7 Tiers
|
|
130
130
|
|
|
131
131
|
### Tier 1 — Validation & Analysis
|
|
132
132
|
|
|
@@ -196,6 +196,7 @@ p58-n8n uses 80% less token context than n8n-mcp by serving structured catalog d
|
|
|
196
196
|
| Tool | What it does |
|
|
197
197
|
|------|-------------|
|
|
198
198
|
| `collect_config` | Detect missing node configuration from your live n8n instance (covers 2,494 known gaps) |
|
|
199
|
+
| `setup_check` | Diagnostic report — server version, n8n connectivity, credential count, tool availability |
|
|
199
200
|
|
|
200
201
|
Full reference with input/output schemas: [docs/TOOLS.md](docs/TOOLS.md)
|
|
201
202
|
|
|
@@ -235,11 +236,11 @@ p58-n8n will: call `get_credential_schema` for Slack → `create_credential` wit
|
|
|
235
236
|
|
|
236
237
|
## Installation
|
|
237
238
|
|
|
238
|
-
See [
|
|
239
|
+
See [AGENT_INSTALL.md](https://github.com/tsvika58/p58-n8n/blob/main/AGENT_INSTALL.md) for full setup instructions:
|
|
239
240
|
|
|
240
241
|
- Claude Desktop (macOS, Windows, Linux)
|
|
241
242
|
- Claude Code (one-command setup)
|
|
242
|
-
- Cursor and
|
|
243
|
+
- Cursor and Gemini CLI
|
|
243
244
|
- Global install vs npx
|
|
244
245
|
- Troubleshooting
|
|
245
246
|
|
|
@@ -274,7 +275,7 @@ MIT — see [LICENSE](LICENSE) for details.
|
|
|
274
275
|
|
|
275
276
|
p58-n8n is in **soft launch** (friends & family). Issues and feedback welcome:
|
|
276
277
|
|
|
277
|
-
- **Bugs:** [GitHub Issues](https://github.com/tsvika58/n8n
|
|
278
|
+
- **Bugs:** [GitHub Issues](https://github.com/tsvika58/p58-n8n/issues)
|
|
278
279
|
- **Email:** tvagman@gmail.com
|
|
279
280
|
|
|
280
281
|
---
|
|
@@ -284,7 +285,7 @@ p58-n8n is in **soft launch** (friends & family). Issues and feedback welcome:
|
|
|
284
285
|
p58-n8n runs as a local stdio MCP server. No cloud services required for basic use.
|
|
285
286
|
|
|
286
287
|
```
|
|
287
|
-
AI Client (Claude / Cursor /
|
|
288
|
+
AI Client (Claude / Cursor / Gemini CLI)
|
|
288
289
|
↕ MCP Protocol (stdio)
|
|
289
290
|
p58-n8n Server
|
|
290
291
|
├── Validation Engine (L1-L6, ~1.4s)
|
|
@@ -3014,22 +3014,28 @@ function buildPoolOptions() {
|
|
|
3014
3014
|
}
|
|
3015
3015
|
function createPool(cfg) {
|
|
3016
3016
|
const timeoutMs = getEnvNumber("DB_STATEMENT_TIMEOUT_MS", 3e4);
|
|
3017
|
+
const isCatalogOnly = !!(process.env.P58_DATABASE_URL || process.env.MCP_DATABASE_URL) && !process.env.N8N_API_KEY;
|
|
3017
3018
|
const pool = new import_pg.Pool({
|
|
3018
3019
|
host: cfg.host,
|
|
3019
3020
|
port: resolvePoolPort(cfg),
|
|
3020
3021
|
user: cfg.user,
|
|
3021
3022
|
password: cfg.password,
|
|
3022
3023
|
database: cfg.database,
|
|
3023
|
-
|
|
3024
|
-
|
|
3024
|
+
// Friends: 3 max (1 active + 2 burst). Full mode: 10.
|
|
3025
|
+
max: getEnvNumber("VALIDATOR_DB_POOL_MAX", isCatalogOnly ? 3 : 10),
|
|
3026
|
+
// Friends: 0 min — don't hold connections when idle. Full mode: 1.
|
|
3027
|
+
min: getEnvNumber("VALIDATOR_DB_POOL_MIN", isCatalogOnly ? 0 : 1),
|
|
3025
3028
|
// allowExitOnIdle: true — prevents zombie processes when MCP session ends (RAG-4.35.5)
|
|
3026
|
-
|
|
3027
|
-
|
|
3029
|
+
// Friends: 30s idle (release fast). Full mode: 60s.
|
|
3030
|
+
idleTimeoutMillis: isCatalogOnly ? 3e4 : 6e4,
|
|
3031
|
+
// Friends: 10s connect timeout (fail fast). Full mode: 15s.
|
|
3032
|
+
connectionTimeoutMillis: isCatalogOnly ? 1e4 : 15e3,
|
|
3028
3033
|
statement_timeout: timeoutMs,
|
|
3029
3034
|
options: buildPoolOptions(),
|
|
3030
3035
|
allowExitOnIdle: true,
|
|
3031
|
-
keepAlive:
|
|
3032
|
-
|
|
3036
|
+
// Friends: no keepAlive (let connections close naturally). Full mode: keepAlive.
|
|
3037
|
+
keepAlive: !isCatalogOnly,
|
|
3038
|
+
...isCatalogOnly ? {} : { keepAliveInitialDelayMillis: 1e4 }
|
|
3033
3039
|
});
|
|
3034
3040
|
pool.on("error", (err) => {
|
|
3035
3041
|
console.warn(`[pg-pool] Idle connection error (non-fatal): ${err.message}`);
|
|
@@ -3041,6 +3047,24 @@ function getValidatorPool() {
|
|
|
3041
3047
|
validatorPool = createPool(getValidatorDbConfig());
|
|
3042
3048
|
return validatorPool;
|
|
3043
3049
|
}
|
|
3050
|
+
async function warmSingleConnection(pool) {
|
|
3051
|
+
const client = await pool.connect();
|
|
3052
|
+
await client.query("SELECT 1");
|
|
3053
|
+
client.release();
|
|
3054
|
+
}
|
|
3055
|
+
async function warmValidatorPool() {
|
|
3056
|
+
if (poolWarmed)
|
|
3057
|
+
return;
|
|
3058
|
+
const pool = getValidatorPool();
|
|
3059
|
+
const minConns = getEnvNumber("VALIDATOR_DB_POOL_MIN", 1);
|
|
3060
|
+
try {
|
|
3061
|
+
for (let i = 0; i < minConns; i++)
|
|
3062
|
+
await warmSingleConnection(pool);
|
|
3063
|
+
poolWarmed = true;
|
|
3064
|
+
} catch (error) {
|
|
3065
|
+
console.warn("Validator pool warm-up failed, continuing with lazy connection creation:", error);
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3044
3068
|
async function validatorQuery(sql, params = []) {
|
|
3045
3069
|
const client = await getValidatorPool().connect();
|
|
3046
3070
|
const onClientError = (err) => {
|
|
@@ -3062,7 +3086,7 @@ async function shutdownValidatorPool() {
|
|
|
3062
3086
|
validatorPool = null;
|
|
3063
3087
|
}
|
|
3064
3088
|
}
|
|
3065
|
-
var import_pg, dotenv, path, import_url, import_connection, __filename, __dirname, PROJECT_ROOT, validatorPool;
|
|
3089
|
+
var import_pg, dotenv, path, import_url, import_connection, __filename, __dirname, PROJECT_ROOT, validatorPool, poolWarmed;
|
|
3066
3090
|
var init_validatorPostgresClient = __esm({
|
|
3067
3091
|
"dist/db/validatorPostgresClient.js"() {
|
|
3068
3092
|
"use strict";
|
|
@@ -3077,6 +3101,7 @@ var init_validatorPostgresClient = __esm({
|
|
|
3077
3101
|
dotenv.config({ path: path.resolve(PROJECT_ROOT, ".env.supabase") });
|
|
3078
3102
|
dotenv.config({ path: path.resolve(PROJECT_ROOT, ".env") });
|
|
3079
3103
|
validatorPool = null;
|
|
3104
|
+
poolWarmed = false;
|
|
3080
3105
|
}
|
|
3081
3106
|
});
|
|
3082
3107
|
|
|
@@ -18436,7 +18461,7 @@ var init_cached_catalog_adapter = __esm({
|
|
|
18436
18461
|
// dist/mcp/server.js
|
|
18437
18462
|
var server_exports = {};
|
|
18438
18463
|
__export(server_exports, {
|
|
18439
|
-
|
|
18464
|
+
isServerInitialized: () => isServerInitialized,
|
|
18440
18465
|
logStartupSummary: () => logStartupSummary
|
|
18441
18466
|
});
|
|
18442
18467
|
module.exports = __toCommonJS(server_exports);
|
|
@@ -18448,7 +18473,7 @@ var import_types22 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
18448
18473
|
var config = {
|
|
18449
18474
|
// Server identity
|
|
18450
18475
|
SERVER_NAME: "p58-n8n",
|
|
18451
|
-
SERVER_VERSION: "0.2.
|
|
18476
|
+
SERVER_VERSION: "0.2.4",
|
|
18452
18477
|
// Database configuration (from environment)
|
|
18453
18478
|
SUPABASE_URL: process.env.SUPABASE_URL,
|
|
18454
18479
|
SUPABASE_KEY: process.env.SUPABASE_KEY,
|
|
@@ -19180,6 +19205,30 @@ async function injectResponseMetadata(sessionId, toolName, response, executionSt
|
|
|
19180
19205
|
return instrumented;
|
|
19181
19206
|
}
|
|
19182
19207
|
|
|
19208
|
+
// dist/mcp/in-flight-tracker.js
|
|
19209
|
+
var inflightCount = 0;
|
|
19210
|
+
function incrementInflight() {
|
|
19211
|
+
inflightCount++;
|
|
19212
|
+
}
|
|
19213
|
+
function decrementInflight() {
|
|
19214
|
+
if (inflightCount > 0)
|
|
19215
|
+
inflightCount--;
|
|
19216
|
+
}
|
|
19217
|
+
function waitForInflightRequests(timeoutMs) {
|
|
19218
|
+
if (inflightCount === 0)
|
|
19219
|
+
return Promise.resolve();
|
|
19220
|
+
return new Promise((resolve2) => {
|
|
19221
|
+
const deadline = setTimeout(resolve2, timeoutMs);
|
|
19222
|
+
const poll = setInterval(() => {
|
|
19223
|
+
if (inflightCount <= 0) {
|
|
19224
|
+
clearInterval(poll);
|
|
19225
|
+
clearTimeout(deadline);
|
|
19226
|
+
resolve2();
|
|
19227
|
+
}
|
|
19228
|
+
}, 50);
|
|
19229
|
+
});
|
|
19230
|
+
}
|
|
19231
|
+
|
|
19183
19232
|
// dist/validation/l1-structure.js
|
|
19184
19233
|
async function validateL1Structure(workflowJson) {
|
|
19185
19234
|
const startTime = performance.now();
|
|
@@ -30389,7 +30438,13 @@ var AutoFixerRegistry = class _AutoFixerRegistry {
|
|
|
30389
30438
|
}
|
|
30390
30439
|
}
|
|
30391
30440
|
};
|
|
30392
|
-
var
|
|
30441
|
+
var _fixerRegistry = null;
|
|
30442
|
+
function getFixerRegistry() {
|
|
30443
|
+
if (!_fixerRegistry) {
|
|
30444
|
+
_fixerRegistry = new AutoFixerRegistry();
|
|
30445
|
+
}
|
|
30446
|
+
return _fixerRegistry;
|
|
30447
|
+
}
|
|
30393
30448
|
|
|
30394
30449
|
// node_modules/axios/lib/helpers/bind.js
|
|
30395
30450
|
function bind(fn, thisArg) {
|
|
@@ -34887,7 +34942,7 @@ async function runAutofixOnWorkflow(workflowJson, issues) {
|
|
|
34887
34942
|
const { applied: credApplied, changelog: credChangelog } = preAssignCredentials(workflow, issues);
|
|
34888
34943
|
const errorIssues = issues.filter((i) => i.severity === "error");
|
|
34889
34944
|
const problems = errorIssues.map(issueToValidationProblem);
|
|
34890
|
-
const fixResult = await
|
|
34945
|
+
const fixResult = await getFixerRegistry().applyFixes(workflow, problems);
|
|
34891
34946
|
const fixChangelog = buildChangelog(fixResult.results);
|
|
34892
34947
|
return {
|
|
34893
34948
|
fixedWorkflow: fixResult.workflow,
|
|
@@ -35282,10 +35337,10 @@ How it works:
|
|
|
35282
35337
|
|
|
35283
35338
|
Validation levels:
|
|
35284
35339
|
- L1: JSON structure, required fields, duplicate node names
|
|
35285
|
-
- L2: Node types exist in catalog (1,
|
|
35286
|
-
- L3: Credential types valid (
|
|
35287
|
-
- L4: Connection patterns exist (
|
|
35288
|
-
- L5: Required parameters configured (
|
|
35340
|
+
- L2: Node types exist in catalog (1,545 nodes)
|
|
35341
|
+
- L3: Credential types valid (679 credentials) \u2014 includes available_credentials lookup
|
|
35342
|
+
- L4: Connection patterns exist (7,642 rules)
|
|
35343
|
+
- L5: Required parameters configured (38,005 params)
|
|
35289
35344
|
- L6: Pattern validation (flow integrity, security, expressions)
|
|
35290
35345
|
|
|
35291
35346
|
Returns detailed issues with severity, location, and suggested fixes.
|
|
@@ -35488,7 +35543,7 @@ var getOperationSchemaToolDefinition = {
|
|
|
35488
35543
|
name: "get_operation_schema",
|
|
35489
35544
|
description: `Get parameter requirements for a specific n8n node operation.
|
|
35490
35545
|
|
|
35491
|
-
Returns the exact required and optional parameters from our
|
|
35546
|
+
Returns the exact required and optional parameters from our 38,005 parameter catalog.
|
|
35492
35547
|
Use this to prevent parameter hallucination when generating n8n workflows.
|
|
35493
35548
|
|
|
35494
35549
|
Examples:
|
|
@@ -36574,6 +36629,77 @@ Examples:
|
|
|
36574
36629
|
}
|
|
36575
36630
|
};
|
|
36576
36631
|
|
|
36632
|
+
// dist/mcp/tools/handlers/shared/n8n-guard.js
|
|
36633
|
+
var SETUP_GUIDE_URL = "https://github.com/tsvika58/p58-n8n/blob/main/docs/AGENT_INSTALL.md";
|
|
36634
|
+
var OFFLINE_TOOLS = /* @__PURE__ */ new Set([
|
|
36635
|
+
"validate_workflow",
|
|
36636
|
+
"get_operation_schema",
|
|
36637
|
+
"check_parameter",
|
|
36638
|
+
"suggest_fix",
|
|
36639
|
+
"list_operations",
|
|
36640
|
+
"list_nodes",
|
|
36641
|
+
"get_node_info",
|
|
36642
|
+
"find_similar_pattern",
|
|
36643
|
+
"get_session_metrics",
|
|
36644
|
+
"get_credential_schema",
|
|
36645
|
+
"setup_check"
|
|
36646
|
+
]);
|
|
36647
|
+
function requiresN8nApiKey(toolName) {
|
|
36648
|
+
return !OFFLINE_TOOLS.has(toolName);
|
|
36649
|
+
}
|
|
36650
|
+
function makeN8nNotConfiguredError() {
|
|
36651
|
+
return {
|
|
36652
|
+
content: [
|
|
36653
|
+
{
|
|
36654
|
+
type: "text",
|
|
36655
|
+
text: JSON.stringify({
|
|
36656
|
+
error: `This tool requires n8n connection. Set N8N_API_URL and N8N_API_KEY in your MCP config. See: ${SETUP_GUIDE_URL}`
|
|
36657
|
+
})
|
|
36658
|
+
}
|
|
36659
|
+
],
|
|
36660
|
+
isError: true
|
|
36661
|
+
};
|
|
36662
|
+
}
|
|
36663
|
+
function isDbConfigError(error) {
|
|
36664
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
36665
|
+
return msg.includes("Missing required validator DB environment variable");
|
|
36666
|
+
}
|
|
36667
|
+
function isDbConnectionError(error) {
|
|
36668
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
36669
|
+
return msg.includes("ECONNREFUSED") || msg.includes("ETIMEDOUT") || msg.includes("connect ETIMEDOUT") || msg.includes("after calling end on the pool") || msg.includes("Connection terminated") || msg.includes("getaddrinfo ENOTFOUND") || msg.includes("too many connections") || msg.includes("remaining connection slots");
|
|
36670
|
+
}
|
|
36671
|
+
function makeDbNotConfiguredResponse() {
|
|
36672
|
+
return {
|
|
36673
|
+
content: [
|
|
36674
|
+
{
|
|
36675
|
+
type: "text",
|
|
36676
|
+
text: JSON.stringify({
|
|
36677
|
+
error: "DB_NOT_CONFIGURED",
|
|
36678
|
+
message: "Catalog features require P58_DATABASE_URL. Set P58_DATABASE_URL in your MCP config to enable this tool.",
|
|
36679
|
+
setup_guide: SETUP_GUIDE_URL
|
|
36680
|
+
})
|
|
36681
|
+
}
|
|
36682
|
+
],
|
|
36683
|
+
isError: true
|
|
36684
|
+
};
|
|
36685
|
+
}
|
|
36686
|
+
function makeDbConnectionErrorResponse() {
|
|
36687
|
+
return {
|
|
36688
|
+
content: [
|
|
36689
|
+
{
|
|
36690
|
+
type: "text",
|
|
36691
|
+
text: JSON.stringify({
|
|
36692
|
+
error: "CATALOG_UNREACHABLE",
|
|
36693
|
+
message: "Catalog database is unreachable. Verify your P58_DATABASE_URL is correct and the database server is accessible. If the problem persists, contact Tsvika.",
|
|
36694
|
+
hint: "Check: (1) connection string starts with postgresql://mcp_friend... (2) port is 6543 (transaction pooler) (3) network allows outbound to AWS eu-north-1",
|
|
36695
|
+
setup_guide: SETUP_GUIDE_URL
|
|
36696
|
+
})
|
|
36697
|
+
}
|
|
36698
|
+
],
|
|
36699
|
+
isError: true
|
|
36700
|
+
};
|
|
36701
|
+
}
|
|
36702
|
+
|
|
36577
36703
|
// dist/mcp/middleware/response-compression.js
|
|
36578
36704
|
function selectFields(item, fields) {
|
|
36579
36705
|
const result = {};
|
|
@@ -36693,8 +36819,11 @@ async function handleListOperations(args) {
|
|
|
36693
36819
|
return toMCPResponse(response);
|
|
36694
36820
|
} catch (error) {
|
|
36695
36821
|
const originalError = error instanceof Error ? error : new Error(String(error));
|
|
36696
|
-
|
|
36697
|
-
|
|
36822
|
+
if (isDbConfigError(originalError))
|
|
36823
|
+
return makeDbNotConfiguredResponse();
|
|
36824
|
+
if (isDbConnectionError(originalError))
|
|
36825
|
+
return makeDbConnectionErrorResponse();
|
|
36826
|
+
return toMCPResponse(createInternalError(correlationId, originalError));
|
|
36698
36827
|
}
|
|
36699
36828
|
}
|
|
36700
36829
|
var listOperationsToolDefinition = {
|
|
@@ -36791,13 +36920,16 @@ async function handleListNodes(args) {
|
|
|
36791
36920
|
return toMCPResponse(response);
|
|
36792
36921
|
} catch (error) {
|
|
36793
36922
|
const originalError = error instanceof Error ? error : new Error(String(error));
|
|
36794
|
-
|
|
36795
|
-
|
|
36923
|
+
if (isDbConfigError(originalError))
|
|
36924
|
+
return makeDbNotConfiguredResponse();
|
|
36925
|
+
if (isDbConnectionError(originalError))
|
|
36926
|
+
return makeDbConnectionErrorResponse();
|
|
36927
|
+
return toMCPResponse(createInternalError(correlationId, originalError));
|
|
36796
36928
|
}
|
|
36797
36929
|
}
|
|
36798
36930
|
var listNodesToolDefinition = {
|
|
36799
36931
|
name: "list_nodes",
|
|
36800
|
-
description: `List all available n8n nodes (1,
|
|
36932
|
+
description: `List all available n8n nodes (1,545 total) with filtering and pagination.
|
|
36801
36933
|
|
|
36802
36934
|
Use this to discover available nodes before generating workflows. The tool supports:
|
|
36803
36935
|
- Pagination: Use limit (1-100) and offset for large result sets
|
|
@@ -36954,8 +37086,11 @@ async function handleGetNodeInfo(args) {
|
|
|
36954
37086
|
return toMCPResponse(response);
|
|
36955
37087
|
} catch (error) {
|
|
36956
37088
|
const originalError = error instanceof Error ? error : new Error(String(error));
|
|
36957
|
-
|
|
36958
|
-
|
|
37089
|
+
if (isDbConfigError(originalError))
|
|
37090
|
+
return makeDbNotConfiguredResponse();
|
|
37091
|
+
if (isDbConnectionError(originalError))
|
|
37092
|
+
return makeDbConnectionErrorResponse();
|
|
37093
|
+
return toMCPResponse(createInternalError(correlationId, originalError));
|
|
36959
37094
|
}
|
|
36960
37095
|
}
|
|
36961
37096
|
var getNodeInfoToolDefinition = {
|
|
@@ -37043,8 +37178,11 @@ async function handleFindSimilarPattern(args) {
|
|
|
37043
37178
|
return toMCPResponse(response);
|
|
37044
37179
|
} catch (error) {
|
|
37045
37180
|
const originalError = error instanceof Error ? error : new Error(String(error));
|
|
37046
|
-
|
|
37047
|
-
|
|
37181
|
+
if (isDbConfigError(originalError))
|
|
37182
|
+
return makeDbNotConfiguredResponse();
|
|
37183
|
+
if (isDbConnectionError(originalError))
|
|
37184
|
+
return makeDbConnectionErrorResponse();
|
|
37185
|
+
return toMCPResponse(createInternalError(correlationId, originalError));
|
|
37048
37186
|
}
|
|
37049
37187
|
}
|
|
37050
37188
|
var findSimilarPatternToolDefinition = {
|
|
@@ -37241,8 +37379,8 @@ schemas, build_workflow handles validation, autofix, and deployment automaticall
|
|
|
37241
37379
|
|
|
37242
37380
|
Runs L1-L4 validation before creating:
|
|
37243
37381
|
- L1: JSON structure, required fields
|
|
37244
|
-
- L2: Node types exist in catalog (1,
|
|
37245
|
-
- L3: Credential types are valid (
|
|
37382
|
+
- L2: Node types exist in catalog (1,545 nodes)
|
|
37383
|
+
- L3: Credential types are valid (679 credentials)
|
|
37246
37384
|
- L4: Connection patterns exist
|
|
37247
37385
|
|
|
37248
37386
|
Refuses creation if any L1-L4 errors are found.
|
|
@@ -38613,7 +38751,7 @@ async function validateWorkflowObject(workflow, timeoutMs, label) {
|
|
|
38613
38751
|
}
|
|
38614
38752
|
async function runAutoFix(workflow, validationResult, timeoutMs, toolName) {
|
|
38615
38753
|
const problems = validationResult.issues.filter((i) => i.severity === "error").map(issueToValidationProblem2);
|
|
38616
|
-
const fixResult = await withTimeout(
|
|
38754
|
+
const fixResult = await withTimeout(getFixerRegistry().applyFixes(workflow, problems), timeoutMs, `${toolName} autofix`);
|
|
38617
38755
|
return { fixedWorkflow: fixResult.workflow, fixResult };
|
|
38618
38756
|
}
|
|
38619
38757
|
async function applyAutoFixIfNeeded(workflow, validationResult, hasErrors, shouldFix, timeoutMs, correlationId, toolName) {
|
|
@@ -39260,7 +39398,7 @@ function issueToValidationProblem3(issue) {
|
|
|
39260
39398
|
}
|
|
39261
39399
|
async function runFixStep(workflow, validation, timeoutMs) {
|
|
39262
39400
|
const problems = validation.issues.filter((i) => i.severity === "error").map(issueToValidationProblem3);
|
|
39263
|
-
const fixResult = await withTimeout(
|
|
39401
|
+
const fixResult = await withTimeout(getFixerRegistry().applyFixes(workflow, problems), timeoutMs, "server_autofix:fix");
|
|
39264
39402
|
return {
|
|
39265
39403
|
fixedWorkflow: fixResult.workflow,
|
|
39266
39404
|
fixes: extractAppliedFixes(fixResult)
|
|
@@ -41290,6 +41428,10 @@ and what service it connects to \u2014 don't attempt to build with a broken cred
|
|
|
41290
41428
|
Part of the generation lifecycle: plan_workflow \u2192 test_credential(s) \u2192 build_workflow.
|
|
41291
41429
|
NOT needed for editing or updating existing workflows (use update_workflow or partial_update_workflow).
|
|
41292
41430
|
|
|
41431
|
+
Note: plan_workflow works without n8n (catalog-only mode). To actually deploy
|
|
41432
|
+
workflows with build_workflow, N8N_API_KEY and N8N_API_URL must be configured.
|
|
41433
|
+
Without n8n, use plan_workflow for research and architecture planning only.
|
|
41434
|
+
|
|
41293
41435
|
Response modes:
|
|
41294
41436
|
- "full": All research data within token_budget (default 8,000)
|
|
41295
41437
|
- "summary" (default): Key fields within token_budget (default 4,000)
|
|
@@ -43096,7 +43238,12 @@ async function handleGetCredentialSchema(args) {
|
|
|
43096
43238
|
return buildSchemaResponse(credential_type, rows, nodes, correlationId, startTime);
|
|
43097
43239
|
} catch (error) {
|
|
43098
43240
|
import_logging57.logger.error("get_credential_schema: unexpected error", { correlationId, error });
|
|
43099
|
-
|
|
43241
|
+
const originalError = error instanceof Error ? error : new Error(String(error));
|
|
43242
|
+
if (isDbConfigError(originalError))
|
|
43243
|
+
return makeDbNotConfiguredResponse();
|
|
43244
|
+
if (isDbConnectionError(originalError))
|
|
43245
|
+
return makeDbConnectionErrorResponse();
|
|
43246
|
+
return toMCPResponse(createInternalError(correlationId, originalError));
|
|
43100
43247
|
}
|
|
43101
43248
|
}
|
|
43102
43249
|
async function handleUnknownType(credentialType, correlationId) {
|
|
@@ -44110,40 +44257,8 @@ When values are collected, marks matching factory.gaps entries as resolved for a
|
|
|
44110
44257
|
}
|
|
44111
44258
|
};
|
|
44112
44259
|
|
|
44113
|
-
// dist/mcp/tools/handlers/shared/n8n-guard.js
|
|
44114
|
-
var SETUP_GUIDE_URL = "https://github.com/tsvika58/n8n-workflow-validator/blob/main/docs/AGENT_INSTALL.md";
|
|
44115
|
-
var OFFLINE_TOOLS = /* @__PURE__ */ new Set([
|
|
44116
|
-
"validate_workflow",
|
|
44117
|
-
"get_operation_schema",
|
|
44118
|
-
"check_parameter",
|
|
44119
|
-
"suggest_fix",
|
|
44120
|
-
"list_operations",
|
|
44121
|
-
"list_nodes",
|
|
44122
|
-
"get_node_info",
|
|
44123
|
-
"find_similar_pattern",
|
|
44124
|
-
"get_session_metrics",
|
|
44125
|
-
"get_credential_schema",
|
|
44126
|
-
"setup_check"
|
|
44127
|
-
]);
|
|
44128
|
-
function requiresN8nApiKey(toolName) {
|
|
44129
|
-
return !OFFLINE_TOOLS.has(toolName);
|
|
44130
|
-
}
|
|
44131
|
-
function makeN8nNotConfiguredError() {
|
|
44132
|
-
return {
|
|
44133
|
-
content: [
|
|
44134
|
-
{
|
|
44135
|
-
type: "text",
|
|
44136
|
-
text: JSON.stringify({
|
|
44137
|
-
error: `This tool requires n8n connection. Set N8N_API_URL and N8N_API_KEY in your MCP config. See: ${SETUP_GUIDE_URL}`
|
|
44138
|
-
})
|
|
44139
|
-
}
|
|
44140
|
-
],
|
|
44141
|
-
isError: true
|
|
44142
|
-
};
|
|
44143
|
-
}
|
|
44144
|
-
|
|
44145
44260
|
// dist/mcp/tools/handlers/setup-check.js
|
|
44146
|
-
var SETUP_GUIDE_URL2 = "https://github.com/tsvika58/n8n
|
|
44261
|
+
var SETUP_GUIDE_URL2 = "https://github.com/tsvika58/p58-n8n/blob/main/docs/AGENT_INSTALL.md";
|
|
44147
44262
|
var N8N_PROBE_TIMEOUT_MS = 2e3;
|
|
44148
44263
|
var N8N_PROBE_PORTS = [5678, 5679];
|
|
44149
44264
|
async function probeN8nUrl(url2) {
|
|
@@ -44333,13 +44448,18 @@ async function dispatchToolCall(name, args) {
|
|
|
44333
44448
|
if (requiresN8nApiKey(name) && !process.env.N8N_API_KEY) {
|
|
44334
44449
|
return makeN8nNotConfiguredError();
|
|
44335
44450
|
}
|
|
44336
|
-
|
|
44337
|
-
|
|
44338
|
-
if (
|
|
44339
|
-
|
|
44340
|
-
|
|
44451
|
+
incrementInflight();
|
|
44452
|
+
try {
|
|
44453
|
+
if (tool.inputSchema && hasSchema(name)) {
|
|
44454
|
+
const validation = validateToolInput(name, args);
|
|
44455
|
+
if (!validation.success)
|
|
44456
|
+
return createValidationErrorResponse(validation.error);
|
|
44457
|
+
return await tool.handler(validation.data);
|
|
44458
|
+
}
|
|
44459
|
+
return await tool.handler(args);
|
|
44460
|
+
} finally {
|
|
44461
|
+
decrementInflight();
|
|
44341
44462
|
}
|
|
44342
|
-
return tool.handler(args);
|
|
44343
44463
|
}
|
|
44344
44464
|
async function handleToolCall(name, args, sessionId = "default") {
|
|
44345
44465
|
const startTime = Date.now();
|
|
@@ -44357,7 +44477,9 @@ function registerAllTools() {
|
|
|
44357
44477
|
registerTool({ ...entry, inputSchema: toolSchemas[entry.name] });
|
|
44358
44478
|
}
|
|
44359
44479
|
}
|
|
44360
|
-
|
|
44480
|
+
|
|
44481
|
+
// dist/mcp/server.js
|
|
44482
|
+
init_validatorPostgresClient();
|
|
44361
44483
|
|
|
44362
44484
|
// dist/mcp/middleware/credential-redaction.js
|
|
44363
44485
|
var MAX_DEPTH = 20;
|
|
@@ -44530,6 +44652,7 @@ var defaultDeps = {
|
|
|
44530
44652
|
};
|
|
44531
44653
|
async function runCleanup(serverName, deps) {
|
|
44532
44654
|
try {
|
|
44655
|
+
await waitForInflightRequests(5e3);
|
|
44533
44656
|
await deps.shutdownPool();
|
|
44534
44657
|
deps.clearCache();
|
|
44535
44658
|
deps.clearConfigCache?.();
|
|
@@ -44561,22 +44684,29 @@ function registerShutdownHandlers(serverName, deps) {
|
|
|
44561
44684
|
}
|
|
44562
44685
|
|
|
44563
44686
|
// dist/mcp/server.js
|
|
44564
|
-
var
|
|
44565
|
-
|
|
44566
|
-
|
|
44567
|
-
|
|
44568
|
-
|
|
44569
|
-
|
|
44570
|
-
|
|
44571
|
-
|
|
44572
|
-
|
|
44573
|
-
|
|
44574
|
-
|
|
44687
|
+
var SETUP_GUIDE_URL3 = "https://github.com/tsvika58/p58-n8n/blob/main/docs/AGENT_INSTALL.md";
|
|
44688
|
+
var _serverInitialized = false;
|
|
44689
|
+
function isServerInitialized() {
|
|
44690
|
+
return _serverInitialized;
|
|
44691
|
+
}
|
|
44692
|
+
function buildInitializingResponse() {
|
|
44693
|
+
return {
|
|
44694
|
+
content: [{
|
|
44695
|
+
type: "text",
|
|
44696
|
+
text: JSON.stringify({
|
|
44697
|
+
error: "SERVER_INITIALIZING",
|
|
44698
|
+
message: "Server is still loading. Please retry in a moment.",
|
|
44699
|
+
retryAfterMs: 2e3
|
|
44700
|
+
})
|
|
44701
|
+
}],
|
|
44702
|
+
isError: true
|
|
44703
|
+
};
|
|
44704
|
+
}
|
|
44575
44705
|
function logStartupSummary(n8nConnected) {
|
|
44576
44706
|
const apiKey = process.env.N8N_API_KEY;
|
|
44577
44707
|
const n8nUrl = process.env.N8N_API_URL ?? process.env.N8N_API_BASE_URL ?? "http://localhost:5678/api/v1";
|
|
44578
44708
|
const totalTools = getRegisteredTools().length;
|
|
44579
|
-
const tier1Count =
|
|
44709
|
+
const tier1Count = OFFLINE_TOOLS.size;
|
|
44580
44710
|
const tier27Count = totalTools - tier1Count;
|
|
44581
44711
|
let n8nStatus;
|
|
44582
44712
|
if (!apiKey) {
|
|
@@ -44616,6 +44746,9 @@ function toCallToolResult(response) {
|
|
|
44616
44746
|
server.setRequestHandler(import_types22.CallToolRequestSchema, async (request) => {
|
|
44617
44747
|
const { name, arguments: args } = request.params;
|
|
44618
44748
|
try {
|
|
44749
|
+
if (!_serverInitialized) {
|
|
44750
|
+
return toCallToolResult(buildInitializingResponse());
|
|
44751
|
+
}
|
|
44619
44752
|
const response = await handleToolCall(name, args ?? {});
|
|
44620
44753
|
return toCallToolResult(redactMCPResponse(response));
|
|
44621
44754
|
} catch (error) {
|
|
@@ -44625,13 +44758,25 @@ server.setRequestHandler(import_types22.CallToolRequestSchema, async (request) =
|
|
|
44625
44758
|
});
|
|
44626
44759
|
async function main() {
|
|
44627
44760
|
const transport = new import_stdio.StdioServerTransport();
|
|
44761
|
+
const startMs = Date.now();
|
|
44628
44762
|
await server.connect(transport);
|
|
44763
|
+
console.error(`[INIT] MCP handshake complete in ${Date.now() - startMs}ms`);
|
|
44764
|
+
registerAllTools();
|
|
44765
|
+
_serverInitialized = true;
|
|
44629
44766
|
const toolCount = getRegisteredTools().length;
|
|
44630
|
-
console.error(
|
|
44767
|
+
console.error(`[INIT] ${toolCount} tools registered in ${Date.now() - startMs}ms`);
|
|
44631
44768
|
logStartupSummary(Boolean(process.env.N8N_API_KEY));
|
|
44632
44769
|
registerShutdownHandlers(config.SERVER_NAME);
|
|
44633
44770
|
void warmCredentialCache().catch(() => {
|
|
44634
44771
|
});
|
|
44772
|
+
if (process.env.P58_DATABASE_URL || process.env.MCP_DATABASE_URL) {
|
|
44773
|
+
void warmValidatorPool().then(() => {
|
|
44774
|
+
console.error("catalog: connected \u2713");
|
|
44775
|
+
}).catch((err) => {
|
|
44776
|
+
console.error(`catalog: WARNING \u2014 connection failed: ${err.message}`);
|
|
44777
|
+
console.error("catalog: tools will retry on first use, but check P58_DATABASE_URL if errors persist");
|
|
44778
|
+
});
|
|
44779
|
+
}
|
|
44635
44780
|
}
|
|
44636
44781
|
main().catch((error) => {
|
|
44637
44782
|
console.error("Server failed to start:", error);
|
|
@@ -44639,7 +44784,7 @@ main().catch((error) => {
|
|
|
44639
44784
|
});
|
|
44640
44785
|
// Annotate the CommonJS export names for ESM import in node:
|
|
44641
44786
|
0 && (module.exports = {
|
|
44642
|
-
|
|
44787
|
+
isServerInitialized,
|
|
44643
44788
|
logStartupSummary
|
|
44644
44789
|
});
|
|
44645
44790
|
/*! Bundled license information:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@path58/p58-n8n",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "The smartest and fastest n8n MCP server — validate, fix, and discover workflows inside your LLM",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
],
|
|
14
14
|
"author": "Path58",
|
|
15
15
|
"license": "MIT",
|
|
16
|
-
"homepage": "https://github.com/tsvika58/n8n
|
|
16
|
+
"homepage": "https://github.com/tsvika58/p58-n8n#readme",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/tsvika58/n8n
|
|
19
|
+
"url": "git+https://github.com/tsvika58/p58-n8n.git"
|
|
20
20
|
},
|
|
21
21
|
"bin": {
|
|
22
22
|
"p58-n8n": "dist/mcp/server.bundle.cjs"
|