MCP
Troubleshooting & gotchas
Source: orchestration/mcp-gateway/index.ts, auth-middleware.ts, server.ts, session-do.ts,
tools.ts, tool-exec.ts, tool-outcome.ts, execution.ts, leg-state.ts, resources.ts,
extras.ts, activity-log.ts, core/core-base/provider-ids.ts, core/agent-core/index.ts,
agents/agents/one-agent/call-config.ts, orchestration/api-gateway/routes/mcp.ts, live registry and
registry cards (2026-09-24), live /health, /v1/info, 401/405/413 responses (2026-09-24).
Most problems fall into one of three groups: the key, the transport, or which id you used. This
chapter starts with five checks that settle most of them, then maps symptoms to causes, then lists
the gotchas that come up in real use. Every row was checked against the code or a live response.
The endpoint is https://mcp.plungeai.com/v1; https://api.plungeai.com/v1/mcp is the same
server, and where it behaves differently the row says so.
15.1 Five first checks
Is the platform up? No key needed.
statusishealthy, ordegradedwith HTTP 503 when the database, key store or registry probe fails:curl -s "https://mcp.plungeai.com/health?cb=$(date +%s)"Which server and protocol version am I talking to? No key needed:
curl -s https://mcp.plungeai.com/v1/info(4.2).Does my key work, and whose is it? Ask "Who am I, what tier am I on, and how much of my rate limit have I used?", or call it directly:
curl -s https://mcp.plungeai.com/v1 \ -H "Authorization: Bearer $PLUNGE_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_whoami","arguments":{"user_request":"who am I"}}}' \ | sed -n 's/^data: //p'What did my client actually send? Your activity log shows every request with its arguments, your own words (
user_request), and the answer or error (13.10). It is the fastest way to see that a client sent{folder: "Finance"}when you asked something else.Is the tool list stale? Clients read
tools/listonce, when they connect, and this server never pushes a change notification. After a platform update, restart or reconnect your client to pick up new or changed tools.
15.2 Symptoms and fixes
| Symptom | Cause | Fix |
|---|---|---|
401 on every call | The key is wrong, replaced, revoked or expired, or the header is wrong. The message is the same for all of these: No valid authentication provided…. A Bearer token that does not start with ozk_ is never accepted. | Check the header (Authorization: Bearer ozk_… or X-API-Key). Mint a new key at Dashboard → One API → Keys (https://dashboard.plungeai.com) and revoke the old one. |
401 API key not permitted from <ip>, or 401 only from a new place | The key is restricted to certain network locations | Use it from an allowed network, or ask the account owner who issued it to update the fence. |
429 Rate limit exceeded: Rate limit: <n> requests/minute (or /day) with Retry-After | Your tier's limit (13.7) | Wait the Retry-After seconds. Ask "how much of my rate limit have I used?". |
429 Too many failed authentication attempts | Many failed logins from your IP, often a client retrying with a bad key | Fix the key in the client config, then wait for the window to reset. |
Tool not permitted for this key: <name> | Your key is limited to a subset of tools | Use a key that allows the tool, or ask the account owner. |
| Fewer tools than expected | A restricted key (fenced tools never appear in tools/list), or a stale client list | Check with tools/list. Reconnect the client. |
Tool not found: <name>, or your client doesn't know a tool | The client's tool list predates a platform update, or the name is misspelled | Reconnect to refresh the tool list. |
405 Method not allowed. on GET | Your client tried to open a standalone SSE stream. The server is stateless and offers none (4.5). | Nothing, for spec-compliant clients: they continue with POST. |
404 Session not found | The client sent an Mcp-Session-Id that is stale, expired (10 min idle) or from another key. Normal keys never get one. | Drop the header and re-initialize. |
400 Parse error | The body is not valid JSON, usually shell quoting | Check the quotes around -d '…'. Inside single quotes, write an apostrophe as '"'"'. |
413 Request body too large (1 MiB max) | Body over 1,048,576 bytes | Shrink it: save a long workflow first and run it by id, or split the work. |
403 Invalid Host header | A proxy between you and the server rewrote the Host header | Call https://mcp.plungeai.com/v1 directly. |
curl prints event: message and data: {…} lines | tools/call answers as Server-Sent Events | Keep the data: lines: … | sed -n 's/^data: //p' (4.6). |
| A long run returns an id instead of a result | Background mode: mode:"async", or plungeai_run_mission / plungeai_learn, which default to it | Normal. Ask "is that still running?" and then "show me the result" (Runs, results & follow-ups). |
This run failed: … | The run genuinely failed, and that is the reason | Fix the input and rerun. Don't keep polling. |
A background run shows Interrupted (run did not complete) | The run stopped sending a heartbeat for 16 minutes and was marked failed (4.7) | Rerun it, run it in the foreground, or split it into smaller steps. |
Run was killed 3 times in a row without yielding a checkpoint… | One step ran longer than a 10-minute leg, crashed repeatedly, or kept getting interrupted by deploys | Split the work or shorten the step, then rerun. |
…is not status:active / No such agent: <id> (🚫 UNAVAILABLE) | The agent is not in the live catalog, or the id was guessed | Pick a listed alternative, or search: "which agent should I use to …". |
That is a scheduler run id, which this tool cannot resolve… | An exec_… id from the scheduler | Ask for the job's run history (plungeai_schedule runs) and use its Execution ID column. |
No result found for <id>, or it is not one of your executions. | A workflow id where an execution id belongs, or another account's id | Ask "show me my recent executions" and use an id from there (15.3). |
Execution not found. from a status check or plungeai_executions | No run of yours has that id: it is unknown, belongs to another account, or is a workflow id where an execution id belongs | Ask "show me my recent executions" and use an id from there. |
Execution is completed, not running — nothing to cancel. | Cancel only applies to running executions | Nothing to do. |
| Your client shortens or paraphrases a long result | The client's own behaviour. The server's instructions ask it to relay results verbatim. | Add "show it verbatim, don't summarize". |
/health answers 503 with "status":"degraded" | A platform dependency probe failed | Platform-side. Retry later. |
Need a new key? Self-serve one at Dashboard → One API → Keys (https://dashboard.plungeai.com).
For a shared team key, or anything else, ask the account owner.
15.3 Gotchas worth knowing
These come from real failures.
"Category" and "folder" are different things. Your folders (Finance, Personal, …) hold
your workflows. Categories are the global agent taxonomy, and the finance one is called
financials, not finance. On 2026-09-24 the registry answered category=finance with 0 results
and category=financials with sec-agent (live-verified). Say "agents for financial analysis"
and let the semantic search work. Or read plungeai://agents/categories for the real names
(Prompts & resources).
Results need the execution id, not the workflow id. A workflow id identifies the recipe, and each run gets its own execution id. Every run result ends with its execution id. If a result lookup comes back empty, ask "show me my recent executions" first and use that id. When you refer to a row by number ("show me #2"), the server tells clients to resolve it against the list you were shown, not a fresh one, because new runs keep shifting a newest-first list.
Don't ask for "all agents". An unfiltered listing is large: about 150 KB for the 92 active
agents on 2026-09-24 (live-verified), in one go into your context. plungeai://agents/list is the
same listing. Filter by search term, category or kind instead. Everything the catalog lists is live
and callable. Names from outside it (memory, another platform, a guess) are refused with
🚫 UNAVAILABLE before anything runs, so when in doubt, search first.
Some agents are forms, not chats. Agents such as markitdown, weather-agent or
google-gmail take specific fields (a URL, a place, a message id), not a sentence. Your client
handles this itself: it fetches the agent's contract (every field typed, with a worked example)
and fills it in before running (Tools). If something is still missing, the answer names
the exact fields and shows the form. It never comes back as a bare error, so "do what it
suggests" is always enough. A prose prompt sent to an agent with several operations and no
operation runs its default operation, and the answer says so with a ⚠️ structured agent: …
warning.
Writing workflow YAML by hand? Quote your colons. A value like prompt: DD: memo breaks YAML.
Write prompt: "DD: memo", or put long text in a block (prompt: |). Never hard-wrap a value
across lines. On invalid YAML, plungeai_execute_workflow adds exactly this tip to its answer.
The top-level workflow: wrapper is optional: bare name: + tasks: at the top level is accepted
and wrapped for you. Easier still, describe the goal and let "build me a workflow that…" write the
YAML (Workflows). On a one-agent task you can leave provider out to get the
default (gemini, model gemini-3.1-flash-lite). The provider resolver maps google to gemini
(core/core-base/provider-ids.ts). Any other unknown provider is refused: Unsupported provider: <x>,
or provider "<x>" is not available on llm-agent (call mode keeps the legacy wording) when the
provider exists but the agent has no binding for it.
"Needs a connected account" means exactly that. Google, Microsoft and similar agents act as
you, so they need your account connected once in Studio → Connectors. The platform checks this
before running anything. If the connection is missing or expired, you are told exactly which
service to connect and where (🔌 NEEDS CONNECTION): no run is started, and nothing half-happens.
The same goes for bring-your-own-key agents (wallets, private APIs, 🔑 NEEDS API KEY): save your
key once in Studio and every surface can use it. Ask "what does this agent need, and am I
connected?" and the contract's Credentials section shows the live status: ✅ connected as you@…, ⚠️ NOT connected, ⚠️ expired — reconnect, or 🔐 platform-managed.
Broad questions about the platform's own structure can be slow. A question like "what are all
the categories and how many agents in each?" can make a client fetch agent cards one at a time.
The plungeai://agents/categories resource answers it in one read. Otherwise ask a narrower
question.
Background runs return immediately. A long workflow answers with an execution id, not a result. That is normal. Ask for the result once it has finished (4.7).
A quiet client is not a stalled run. If you see no live status while something takes a while,
the run is still fine. Some clients do not display the progress channel at all. Two ways to tell:
the result arrives normally when the call ends, and the run is in your execution history as
running the whole time ("is that still running?", or Studio's results sidebar).
Results are already formatted, so ask for them "in full". Everything the server returns is finished Markdown (tables, headings, links), including a step index for multi-step runs and the whole conversation thread for runs you have followed up on. Chat clients sometimes summarize long answers anyway. Adding "show it verbatim, don't summarize" stops that.
Give financial agents a company name, ticker or CIK. sec-agent resolves the company from what
you pass, in the order CIK → ticker → name → prompt (its registry card, 2026-09-24). A bare
fragment inside a long sentence resolves worst. "Latest annual revenue for ticker CRCL" or
"Apple insider trading Form 4" work.
Data providers run out. An agent whose upstream plan hit its quota reports that itself. You
get 🚫 UNAVAILABLE with the agent's own reason, not a broken-looking error (13.2).
Retry later, or use another agent that reads the same data (for company figures, filings via
sec-agent).
Claude Desktop caps a single tool call at about 4 minutes. For anything longer, ask for it to run "in the background". You get an execution id at once, and you can ask for its status or result at any time. The server sends a keepalive line every 15 seconds, but that does not extend a client's own cap.
Always let your client pass your words. Every tool takes user_request, the sentence you
actually typed. It shows up at the top of each entry in your activity log (> **Asked:** …), which
turns a puzzling call into an obvious one when you debug.