@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 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 34 tools organized in tiers:
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
- | **Windsurf** | `~/.codeium/windsurf/mcp_config.json` | All |
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 / Windsurf / VS Code (JSON config)
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
- | **Windsurf** | Restart Windsurf |
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.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.2]: https://github.com/tsvika58/n8n-workflow-validator/releases/tag/v0.2.2
102
- [0.2.1]: https://github.com/tsvika58/n8n-workflow-validator/releases/tag/v0.2.1
103
- [0.2.0]: https://github.com/tsvika58/n8n-workflow-validator/releases/tag/v0.2.0
104
- [0.1.1]: https://github.com/tsvika58/n8n-workflow-validator/releases/tag/v0.1.1
105
- [0.1.0]: https://github.com/tsvika58/n8n-workflow-validator/releases/tag/v0.1.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
  [![npm](https://img.shields.io/npm/v/@path58/p58-n8n)](https://www.npmjs.com/package/@path58/p58-n8n)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
- [![Tests](https://github.com/tsvika58/n8n-workflow-validator/actions/workflows/ci.yml/badge.svg)](https://github.com/tsvika58/n8n-workflow-validator/actions/workflows/ci.yml)
7
+ [![Tests](https://github.com/tsvika58/p58-n8n/actions/workflows/ci.yml/badge.svg)](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-workflow-validator/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.
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 / Windsurf** — see [docs/INSTALLATION.md](docs/INSTALLATION.md) for full multi-client setup.
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-workflow-validator/blob/main/AGENT_INSTALL.md) for the autonomous installation guide.
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
- ## 34 Tools in 7 Tiers
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 [docs/INSTALLATION.md](docs/INSTALLATION.md) for full setup instructions:
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 Windsurf
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-workflow-validator/issues)
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 / Windsurf)
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
- max: getEnvNumber("VALIDATOR_DB_POOL_MAX", 10),
3024
- min: getEnvNumber("VALIDATOR_DB_POOL_MIN", 1),
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
- idleTimeoutMillis: 6e4,
3027
- connectionTimeoutMillis: 15e3,
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: true,
3032
- keepAliveInitialDelayMillis: 1e4
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
- TIER_1_TOOLS: () => TIER_1_TOOLS,
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.3",
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 fixerRegistry = new AutoFixerRegistry();
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 fixerRegistry.applyFixes(workflow, problems);
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,982 nodes)
35286
- - L3: Credential types valid (654 credentials) \u2014 includes available_credentials lookup
35287
- - L4: Connection patterns exist (6,900 rules)
35288
- - L5: Required parameters configured (35,143 params)
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 35,143 parameter catalog.
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
- const errorResponse = createInternalError(correlationId, originalError);
36697
- return toMCPResponse(errorResponse);
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
- const errorResponse = createInternalError(correlationId, originalError);
36795
- return toMCPResponse(errorResponse);
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,982 total) with filtering and pagination.
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
- const errorResponse = createInternalError(correlationId, originalError);
36958
- return toMCPResponse(errorResponse);
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
- const errorResponse = createInternalError(correlationId, originalError);
37047
- return toMCPResponse(errorResponse);
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,982 nodes)
37245
- - L3: Credential types are valid (654 credentials)
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(fixerRegistry.applyFixes(workflow, problems), timeoutMs, `${toolName} autofix`);
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(fixerRegistry.applyFixes(workflow, problems), timeoutMs, "server_autofix:fix");
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
- return toMCPResponse(createInternalError(correlationId, error instanceof Error ? error : new Error(String(error))));
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-workflow-validator/blob/main/docs/AGENT_INSTALL.md";
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
- if (tool.inputSchema && hasSchema(name)) {
44337
- const validation = validateToolInput(name, args);
44338
- if (!validation.success)
44339
- return createValidationErrorResponse(validation.error);
44340
- return tool.handler(validation.data);
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
- registerAllTools();
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 TIER_1_TOOLS = /* @__PURE__ */ new Set([
44565
- "validate_workflow",
44566
- "get_operation_schema",
44567
- "check_parameter",
44568
- "suggest_fix",
44569
- "list_operations",
44570
- "list_nodes",
44571
- "get_node_info",
44572
- "find_similar_pattern"
44573
- ]);
44574
- var SETUP_GUIDE_URL3 = "https://github.com/tsvika58/n8n-workflow-validator/blob/main/docs/AGENT_INSTALL.md";
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 = TIER_1_TOOLS.size;
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(`${config.SERVER_NAME} v${config.SERVER_VERSION} running on stdio (${toolCount} tools registered)`);
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
- TIER_1_TOOLS,
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",
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-workflow-validator#readme",
16
+ "homepage": "https://github.com/tsvika58/p58-n8n#readme",
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "git+https://github.com/tsvika58/n8n-workflow-validator.git"
19
+ "url": "git+https://github.com/tsvika58/p58-n8n.git"
20
20
  },
21
21
  "bin": {
22
22
  "p58-n8n": "dist/mcp/server.bundle.cjs"