docs(mcp): Step-1 inventory for the SPARK wiring audit + two corrections - #2503
Conversation
MCP_WIRING_AUDIT_SPARK_2026-08-09.md hands SPARK a fleet-wide audit whose Step 1 is the inventory. This is that step, done ahead of pickup so SPARK starts from a matrix with blockers named rather than a blank page. Not a claim on the lane. TWO CORRECTIONS, both to things I had also repeated: 1. PMOVES-jcodemunch-mcp is NOT an n8n MCP. Verified against upstream jgravelle/jcodemunch-mcp: it is a CODE-EXPLORATION server — tree-sitter AST indexing, symbol-level retrieval, 90+ tools (search_symbols, get_symbol_source, find_importers, get_blast_radius, get_call_hierarchy, check_edit_safe), 70+ languages, ~96% claimed token reduction. `pip install jcodemunch-mcp`, local-first index, NO API KEY for core functionality. So it is not blocked on the n8n owner-password reset — that story is real but belongs to a different surface. It moves from "operator-gated" to one of the three cheapest wires available. 2. flute-gateway/mcp_bridge.py is mounted AND authenticated. An earlier pass called it dead code. main.py:617-625 imports create_mcp_router, mounts it, and passes dependencies=[Depends(verify_api_key)]. The auth arrived via #2491's fix commit. Worth noting the gating only works because create_mcp_router returns a real APIRouter — include_router(dependencies=...) does NOT apply to a Starlette Mount, so this was a plausible silent no-op that happens to be correct. It is live-but-unregistered, not dead. THE STRUCTURAL FINDING: there are THREE registration surfaces and they disagree. .claude/mcp.json (13 entries, and Claude Code needs --mcp-config to read it at all), pmoves/config/mcp_inventory.json (the canonical generator source, and the one actually out of sync — hirag/e2b/jcodemunch/flute-bridge/gradio-tts are absent from it too), and pmoves/config/mcp/*.yaml (descriptors, one of which says "todo"). Recommendation: generate .claude/mcp.json FROM mcp_inventory.json. Two hand-maintained lists of the same thing is the exact drift this repo has been paying for all week. Also documents that three unrelated things are called "MCP" here — real servers, consumer-side clients (pipecat MCPClient, Archon per-node config), and the "GRADIO MCP" TAC rail which is a gradio_client test harness and not the protocol. Ranked cheapest-first: hirag-mcp (zero code, zero secrets, README ships the JSON), Gradio-TTS (already live, MCP on by default), jcodemunch (no secrets). Those three are one sitting and need nothing from the operator. The n8n lane has TWO independent blockers, one operator-gated and one needing a compose service written. Verified: make -C pmoves validate-command-anchors passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe handoff adds a corrected MCP wiring audit. It inventories server and client surfaces, documents registration layers, ranks wiring work, and records unresolved deployment and authentication questions. ChangesMCP wiring audit
Estimated code review effort: 1 (Trivial) | ~5 minutes Suggested labels: ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2d32cca80
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ) | ||
| ``` | ||
|
|
||
| Mounted **and** gated by `verify_api_key`. The auth arrived via PR #2491's fix commit. Note the gating only works because `create_mcp_router` returns a real `APIRouter` — `include_router(dependencies=…)` does **not** apply to a Starlette `Mount`, so this was a plausible silent no-op that happens to be correct. |
There was a problem hiding this comment.
Mark Flute authentication as conditional
When FLUTE_API_KEY is unset—the documented default and the Compose fallback—verify_api_key() returns successfully without requiring X-API-Key, so the bridge is not unconditionally authenticated. Calling it gated here and “authed” in the ranking could lead SPARK to register a control surface without first provisioning a key; document the condition and require the key through the canonical secrets funnel before registration.
AGENTS.md reference: AGENTS.md:L175-L177
Useful? React with 👍 / 👎.
| | `agent-zero` `:8080/mcp` | http | none noted | both ✔ | **wired** | | ||
| | `pmoves-nats-mcp` | stdio | `NATS_URL` today | both ✔ | **wired**; PR #2496 adds CORE `.creds` + CHIT-signed publish | | ||
| | `pmoves-hirag-mcp` | stdio | none (proxies HIRAG_URL) | **absent from both** | **UNWIRED — cheapest fix in the audit** | | ||
| | Ultimate-TTS Gradio MCP | Gradio built-in SSE | none | absent | **UNWIRED but ALREADY LIVE** — `GRADIO_MCP_SERVER` defaults `"true"` | |
There was a problem hiding this comment.
Enable Gradio MCP before registering it
In the canonical media/full Compose configuration inspected, pmoves/docker-compose.media.yml:322 explicitly sets GRADIO_MCP_SERVER=false because the image still needs the gradio[mcp] extra and a rebuild. Therefore this surface is not already live, and adding the recommended SSE entry alone will fail; the inventory should retain the image rebuild and enablement as prerequisites.
Useful? React with 👍 / 👎.
| | Surface | Transport | Auth | Registered | Status | | ||
| |---|---|---|---|---| | ||
| | `pmoves-cipher` `:8105` | SSE `/mcp/sse` | Bearer `CIPHER_API_TOKEN` | `.claude/mcp.json` ✔ · `mcp_inventory.json` ✔ | **wired + working** | | ||
| | `agent-zero` `:8080/mcp` | http | none noted | both ✔ | **wired** | |
There was a problem hiding this comment.
Reconcile the two Agent Zero registrations
The two registrations are not equivalent: .claude/mcp.json uses unauthenticated HTTP at localhost:8080/mcp, while mcp_inventory.json declares token-authenticated SSE at localhost:8081/mcp/t-${AGENT_ZERO_MCP_TOKEN}/sse. Marking this as “both ✔” hides exactly the drift the audit is intended to find, and generating the Claude config from the inventory would silently change its port, transport, and authentication requirements; identify the authoritative endpoint before recommending generation.
Useful? React with 👍 / 👎.
|
|
||
| | Surface | Transport | Auth | Registered | Status | | ||
| |---|---|---|---|---| | ||
| | `pmoves-cipher` `:8105` | SSE `/mcp/sse` | Bearer `CIPHER_API_TOKEN` | `.claude/mcp.json` ✔ · `mcp_inventory.json` ✔ | **wired + working** | |
There was a problem hiding this comment.
Both registration files point Cipher at /api/mcp/sse, not /mcp/sse as recorded in this matrix. Anyone using this inventory to reconstruct or validate the registration would probe the wrong endpoint, so the transport cell should retain the /api prefix.
Useful? React with 👍 / 👎.
What
MCP_WIRING_AUDIT_SPARK_2026-08-09.mdhands SPARK a fleet-wide audit whose Step 1 is the inventory. This is that step, done ahead of pickup so SPARK starts from a matrix with blockers named. Not a claim on the lane — SPARK still CLAIMs it.Two corrections, both to things I had repeated
1.
PMOVES-jcodemunch-mcpis not an n8n MCP. Verified against upstreamjgravelle/jcodemunch-mcp: it's a code-exploration server — tree-sitter AST indexing, symbol-level retrieval, 90+ tools (search_symbols,get_symbol_source,find_importers,get_blast_radius,get_call_hierarchy,check_edit_safe), 70+ languages, ~96% claimed token reduction.pip install jcodemunch-mcp, local-first, no API key for core functionality.So it isn't blocked on the n8n owner-password reset — that story is real but belongs to a different surface. It moves from operator-gated to one of the three cheapest wires available.
Worth noting what it actually pairs with: jcodemunch plus a consumer-side MCP client is symbol-level retrieval without loading files. That's capability-in-the-field applied to code reading — a small model asks for a symbol instead of ingesting a repo.
2.
flute-gateway/mcp_bridge.pyis mounted, and authenticated. An earlier pass called it dead code.main.py:617-625importscreate_mcp_router, mounts it, and passesdependencies=[Depends(verify_api_key)]— the auth arrived via #2491's fix commit.The gating only works because
create_mcp_routerreturns a realAPIRouter;include_router(dependencies=…)does not apply to a StarletteMount. Plausible silent no-op that happens to be correct. It's live but unregistered, not dead.The structural finding
Three registration surfaces, and they disagree:
.claude/mcp.json— 13 entries, and Claude Code needs--mcp-configto read it at all, so presence ≠ callablepmoves/config/mcp_inventory.json— the canonical generator source, and the one actually out of sync (hirag, e2b, jcodemunch, flute-bridge, gradio-tts absent from it too)pmoves/config/mcp/*.yaml— descriptors, one of which literally says "Install the pmoves n8n MCP adaptor (todo)"Recommendation: generate
.claude/mcp.jsonfrommcp_inventory.json. Two hand-maintained lists of the same thing is the exact drift this repo has been paying for all week — four copies of cleanup logic, twoclaude-pmoves.sh, a deny-list duplicatingpatterns.yaml.Ranked cheapest-first
pmoves-hirag-mcp— populated, tests, README ships copy-paste JSON, defaults already correct. Zero code, zero secrets.GRADIO_MCP_SERVERdefaults"true". One SSE entry.PMOVES-jcodemunch-mcp—uvx+ one entry, no secrets.Those three are one sitting and need nothing from the operator.
The n8n lane has two independent blockers:
n8n-bootstrapis operator-gated on an owner password reset, andn8n-agent.yamldescribes a container that doesn't exist in any compose file.Also documented
Three unrelated things are called "MCP" here — real servers, consumer-side clients (pipecat
MCPClient, Archon per-node config), and the "GRADIO MCP" TAC rail which is agradio_clienttest harness and not the protocol. Anyone asked to "wire the MCP" has three wrong answers available.Verification
Open questions for SPARK are listed in the doc, along with what wasn't verified this pass.
🤖 Generated with Claude Code
Summary by CodeRabbit