Errors
The Precursor Intelligence MCP server uses standard JSON-RPC 2.0 error envelopes with extension codes for authentication and credit failures. Tool-level failures (a query that errored or timed out) come back as a successful JSON-RPC response with result.isError: true; they are not JSON-RPC errors.
JSON-RPC error envelope
When a protocol-level error occurs, the response has a top-level error object instead of a result:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "invalid_params: cve_id: pattern",
"data": {}
}
}Code reference
| Code | HTTP status | Message | When |
|---|---|---|---|
-32700 | 400 | parse_error | Request body was not valid JSON. |
-32600 | 400 | invalid_request | Body was not a JSON object. |
-32600 | 400 | invalid_request: jsonrpc != 2.0 | Missing or incorrect jsonrpc field. |
-32600 | 400 | invalid_request: missing method | method field was absent or not a string. |
-32600 | 400 | batch_not_supported | Body was a JSON array (batch requests are not supported). |
-32600 | 400 | request_too_large | Body exceeded 64 KiB. data.max_bytes is 65536. |
-32600 | 400 | request_too_deep | JSON nesting exceeded 16 levels. |
-32601 | 200 | method_not_found | Method is not initialize, tools/list, ping, or tools/call. |
-32602 | 200 | invalid_params: unknown tool | tools/call named an unregistered tool. |
-32602 | 200 | invalid_params: <field>: <reason> | Tool argument validation failed. See Argument validation reasons below. |
-32001 | 401 | unauthorized | Missing, malformed, revoked, or expired key; or source IP not on the key's allowlist. All cases return the same code. |
-32002 | 402 | insufficient_credits | Organisation credit balance is below 1. Top up from the dashboard. |
-32603 | 500 | internal | Unexpected server exception. |
Argument validation reasons
When a tool argument fails validation, the message takes the form invalid_params: <field>: <reason>. The possible reasons are:
required_string: a required string argument was missing.required_integer: a required integer argument was missing.integer/number: the value was the wrong type.length:<min>..<max>: a string was outside the allowed length range.min:<n>/max:<n>: a number was outside the allowed range.pattern: a string did not match the expected regular expression.control_chars: a string contained ASCII control characters.
Validation runs before authentication or charging, so invalid arguments never consume credits.
Non-JSON-RPC error responses
A small number of failures occur before the JSON-RPC layer is reached and return a plain JSON body instead:
| HTTP status | Body | When |
|---|---|---|
| 405 | {"error": "method_not_allowed"} | HTTP method was not POST or OPTIONS. Response includes Allow: POST, OPTIONS. |
| 401 | {"error": "unauthorized"} | Request was rejected before reaching the JSON-RPC layer. |
| 400 | {"error": "missing_client_ip"} | Required client IP header was absent. |
All responses, including these, carry an x-request-id header.
Tool-level errors (not JSON-RPC errors)
If the underlying service call fails or exceeds the 15-second execution timeout, the server returns a successful JSON-RPC response, but the inner CallToolResult is marked as failed via isError: true. The credit is refunded automatically.
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [ { "type": "text", "text": "{\"error\":\"rpc_timeout\"}" } ],
"isError": true,
"_meta": {
"precursor": {
"request_id": "8b16efb8-9a6c-4ace-b817-11cbee626d08",
"tool_name": "search_iocs",
"generated_at": "2026-05-18T10:24:31.118Z",
"credits": { "charged": 1, "remaining": 9998, "refunded": true },
"response_truncated": false
}
}
}
}Possible error values in content[0].text:
rpc_error: the underlying service call failed.rpc_timeout: the call exceeded 15 seconds.
In both cases, _meta.precursor.credits.refunded is true and no credit is permanently deducted.
Recovery guidance
| Situation | What to do |
|---|---|
unauthorized | Verify the bearer token is correct and has not been revoked. Check your key's IP allowlist in the dashboard. |
insufficient_credits | Top up your credit balance from the dashboard. The error persists until the balance is restored. |
request_too_large / request_too_deep | Reduce the size or nesting of the request body. Tool arguments are small; a large body usually indicates a misconfigured client. |
rpc_timeout | Lower limit, add narrower filters, or retry. Credits are refunded automatically. |
response_truncated | Add more selective filters or lower limit. There is no continuation cursor; responses are truncated at 1 MiB. |
Every tool is read-only, so retrying any call is safe. Each request receives a fresh request_id, so there is no risk of double-charging on retry.