MCP errors

The HTTP statuses and JSON-RPC codes the server returns, and what to do about each.

Protocol errors

A malformed or refused request is an HTTP error with a JSON-RPC error object. The code is a JSON-RPC code (negative) or, for authentication and limits, the HTTP status.

HTTPCodeNameWhenWhat to do
400-32700Parse errorThe body is not UTF-8 JSON.Send one JSON object with Content-Type: application/json.
400-32600Invalid requestA batch (a JSON list), a message with no method, a method that is not text, or an id that is not a string or a whole number.Send one JSON-RPC 2.0 object per POST, with "jsonrpc": "2.0".
400-32602Invalid paramsparams is not an object; the 2026-07-28 _meta fields are missing; the tool or prompt is unknown; arguments are not an object; a prompt argument is wrong.Read the message: it names the problem. List the names with tools/list and prompts/list.
400-32022Unsupported protocol versionThe version in the request is not one the server speaks. data.supported lists the ones it does.Use one of the supported versions (see the changelog).
400-32020Header mismatchMCP-Protocol-Version, Mcp-Method or Mcp-Name disagrees with the body.Make the headers match the body, or leave the optional headers out.
401401UnauthorizedNo Authorization header, a key that is not valid, a revoked key, or an expired key. The reply carries WWW-Authenticate: Bearer realm="harnesslab".Send Authorization: Bearer <key>. Use Test my key in the app to see which it is.
403403Account not approvedThe account that owns the key is not approved.Ask the owner of the service to approve the account.
403-32600Origin not allowedThe request has an Origin header that is not the server's own address (a web page calling the server).Call from a server, a CLI or an IDE, not from a web page.
404-32601Method not foundA method the server does not answer. It answers initialize, ping, server/discover, tools/list, tools/call, prompts/list and prompts/get.Check the method name.
405-32600Method not allowedGET, DELETE or another verb. The server has no event stream and no sessions.Use POST.
413-32600Request too largeThe body is over 64 KB.Send a smaller request. Shorten the context you pass to ask.
429429Too many requestsMore calls a minute than the key allows; the key's monthly calls or daily output tokens are used up; or too many failed key checks from your address. Every 429 carries Retry-After in seconds.Wait Retry-After seconds. The message says which limit and when it resets.
503503Switched offThe owner of the service has switched the MCP server off.Try again later.

A protocol error

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": 401,
    "message": "This API key is not valid. Create a key in the app: https://app.harnesslab.co/#/account (Account, Connect your agent)."
  }
}

Notifications and stray responses get 202 with no body. Everything else that worked is 200.

Tool errors

A tool that was called correctly but cannot answer replies with HTTP 200 and isError: true. The text says what is wrong and how to fix it, so an agent can retry by itself.

A tool error

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Unknown topic 'compact'. Valid topics: compaction, ... List them with list_catalog(kind=\"topics\")."
      }
    ],
    "isError": true
  }
}
The text startsWhat to do
Invalid arguments for search_knowledge: 'query' is required. Example: {...}Fix the arguments. The example is a valid call.
Unknown topic 'x'. Valid topics: ... Use list_catalog.Call list_catalog(kind="topics") and use one of those ids.
This key may only use the free tools. Make a key with scope free+ask ...Make a free+ask key in the app and use that one for ask.
No claim 'x'. Use the id from the Evidence footer ...Pass a claim id exactly as the Evidence footer of another reply shows it.
This key has used its daily ask budget ...Wait for 00:00 UTC, or ask the owner to raise the cap.
Something went wrong on the server. Try again later.Retry. If it keeps happening the owner has the details in the server log.

Retrying

  • Retry a 429 after the seconds in Retry-After, not before.
  • Do not retry a 401, 403 or 400 unchanged: they will fail again.
  • For ask, pass the same request_id on a retry: it returns the same job and never pays twice.