MCP Troubleshooting
Isolate where a failure lives: the management routes, the tool gateway, or the upstream service. Start with the caller's JSON-RPC code or HTTP status, then check the server test result and the policy state before touching credentials.
Symptom and action table#
| Symptom | Likely cause | Action |
|---|---|---|
501 MCP_MANAGEMENT_UNAVAILABLE on a management route |
The runtime did not wire the MCP management service | Confirm the deployment includes management service and the request targets the API origin |
403 API key missing capability |
The key lacks mcp:manage or mcp:invoke |
Grant mcp:manage to management keys and mcp:invoke to client keys; neither ships in the default key set |
tools/list lists only the five hosted tools |
No allow policy matches the principal, while federation tools were expected | Hosted tools are pre-approved; federation tools are default-deny. Create an allow policy and confirm the upstream tools are published |
tools/list returns an empty catalog |
An explicit deny matches, or every tool is draft / archived |
Remove the overriding deny; sync the server and publish eligible tools |
tools/call → -32001 permission denied |
Adjudication denied the call: explicit deny, default deny, or a request that widened the allowed scope | Check policy priority and that the tool sits inside an allow scope. This is an authorization decision, not a bad credential; hosted tools still run under default-deny unless a deny matches |
| Workbench shows no primary credential or a paused primary | Credentials exist but none is active, or the primary is paused | The catalog stays editable; only invocation is blocked. Add a backup credential, isolation-test it, promote it, or resume the paused primary |
tools/call → -32001 after a previously working call |
Native MCP upstream rejected the sealed credential (401 / 403), or a Node OpenAPI call received a non-2xx response |
Add a fresh backup credential, test it, and promote it; the outbound connection refreshes on the next call |
tools/call → -32601 method not found |
The tool is draft or archived, or the built-in target is not registered |
Publish the tool, or confirm the built-in target id (provon or duckduckgo) |
| Call rejected for a credential-shaped field | Arguments contain a blocked key such as authorization, token, or api-key |
The sealed outbound credential is the only auth channel; move secrets out of tool arguments |
| Call rejected for a byte budget | Arguments exceed 64 KiB, or tool output exceeds 256 KiB | Reduce argument size; oversized output is withheld rather than returned |
tools/call → -32002 rate limited |
A fixed-window call cap was exceeded in its bucket | Back off and retry after the window. Buckets differ by runtime; see Security rate limits |
tools/call → -32003 upstream failure |
Transport error, timeout, serialization failure, blocked host, or a non-2xx response on the hosted-edge OpenAPI path | Re-run the server test; verify the sealed credential and that the upstream host is public. Native MCP 401 / 403 maps to -32001 instead |
tools/call → -32000 session expired |
A Node OpenAPI call could not be completed due to a transport or timeout error | Retry once; persistently failing means inspect upstream reachability and the sealed credential |
Server connectionStatus is unreachable after a test |
Upstream unreachable, wrong base URL, or rejected credential | Re-run the server test and read its message; a probe 401 marks the credential invalid, so test and promote a fresh secret |
| Call blocked as a private-network target | Upstream host resolves to localhost, a private range, or a metadata address, or the URL carries embedded credentials | Point the server base URL at a permitted public address; tool-call redirects are not followed |
Reading the evidence#
Outbound calls emit a bounded MCP <method> span tagged with mcp.outcome and
mcp.rpcResponseStatusCode. Start from the outcome category:
capability_unavailable(-32601,-32004) — tool not published or invocable, or the project tool gateway is paused.permission_denied(-32001) — policy denied the call, the guardrail rejected arguments, or the upstream rejected the sealed credential on a native MCP call.session_expired(-32000) — Node OpenAPI transport could not complete the call; retry after checking reachability.rate_limited(-32002) — local call cap reached.upstream_errororinternal— upstream failure, serialization error, or an output guardrail rejection.
Tool arguments, content bodies, upstream URLs, and secrets are intentionally absent from spans. Use the server test result and the connection status field to inspect the exact upstream message, and strip prompts, credentials, and personal data before sharing a trace with a support channel.