Skip to main content

Errors

Failures surface at three layers: the HTTP status (did the request reach the server and authenticate?), the JSON-RPC envelope (did the call itself succeed?), and the tool payload (did the tool run and then refuse?). Check all three — the third is the one a shared response handler usually misses.

HTTP status codes​

StatusMeaning
200The request was processed — but the body may still carry a JSON-RPC error (below)
400The body wasn't parseable JSON, wasn't a JSON-RPC envelope at all, or was a batch array over the 64-envelope cap — the error code is -32700 or -32600
401Missing x-api-key, or the key isn't enabled for MCP — see Authentication & access
5xxTransient server-side failure — safe to retry with backoff

JSON-RPC errors​

A failed call returns an error envelope instead of a result:

{
"jsonrpc": "2.0",
"id": 1,
"error": { "code": -32602, "message": "Invalid request parameters" }
}
CodeMeaningUsual cause
-32700Parse errorThe body isn't valid JSON — arrives at HTTP 400
-32600Invalid requestThe envelope wasn't usable. At HTTP 400, the body is valid JSON but not a JSON-RPC object or batch array — or a batch over the 64-envelope cap. At HTTP 200, a tools/call arrived with no usable name — either omitted outright, or because params was sent positionally and a non-object params is read as empty. Not caused by a missing MCP-Protocol-Version header — see Versioning
-32601Method not foundWrong method name — e.g. tool/call for tools/call
-32602Invalid paramsMalformed params: a non-object arguments, or a tool name whose namespace prefix we don't serve (mdmcp-search_brands, not search_brands) — check the Reference. Arguments that merely don't match a tool's input schema do not land here; that call succeeds at HTTP 200 and carries the refusal in its payload — see below
-32603Internal errorServer-side failure while executing — safe to retry
-32002Resource not foundUnknown resource URI — check the Reference for the ones this server publishes
-32003Not authorisedYour key is valid, but your subscription doesn't include that backend — see below
-32004Backend unavailableThat backend is being shed after repeated failures. Back off substantially longer than for -32603 — retrying quickly only extends it
-32099Rate limitedToo many requests — see Rate limits

Most tool refusals arrive in the payload, not on isError​

When a tool runs and then refuses, the call succeeds at the protocol level and the refusal is in the payload — note isError is false:

{
"isError": false,
"structuredContent": {
"error": {
"code": "invalid_input",
"message": "topic: Input should be 'filter_fields', 'metrics', …",
"field": "topic"
}
}
}
codeMeaningRetry?
invalid_inputArguments refused. Often with field naming the one to change — the market-data tools set it consistently, research and messaging only sometimes.No — fix the request
not_entitledThe backend refused your subscription's access to this data.No
upstream_unavailableA dependency is failing or slow.Yes, with backoff
internalOur side is wrong: a malformed record, or a guard we can't satisfy. A retry returns the identical error, which is why it isn't worth one. Distinct from -32603 above, which is the gateway failing rather than a tool.No

A client branching only on isError reads an in-band refusal as a success, and then finds no data where it expected some. A client branching only on the payload crashes on the isError cases, where structuredContent is null. Check isError first — when it is true the text is prose, not JSON — then check the payload for error. See Concepts → Response shape for which refusals use which channel, and a ready-made unwrapper.

"Not provisioned" has three different shapes​

Worth separating, because they arrive at three different layers and only the last one is a not_entitled payload:

What is wrongHow it arrives
The key is unrecognised, or not enabled for MCPHTTP 401 — nothing reaches a tool
The key is valid, but your subscription does not include that backendJSON-RPC -32003 at HTTP 200
The key reaches the backend, which refuses the specific dataIn-band not_entitled, isError: false

Empty results aren't errors​

A search that returns an empty list succeeded — no match cleared the relevance threshold. Rephrase the query, make it more specific, or batch several phrasings in one call (see Concepts → Tools).

This is distinct from a refusal: an empty answer arrives on the result branch with no error at all.

Retrying​

Every EDITED MCP tool is a read-only search with no side-effects, so retries are always safe. Retry 5xx, -32603 and -32099 with exponential backoff; on -32004 back off substantially longer, since that backend is already being shed and quick retries prolong it. Don't retry 401, -32700, -32600 or -32602 — those need a fix (key, request shape, or tool-name prefix), not patience.

An isError: true result is worth exactly one retry. It carries no code to branch on, and the channel mixes two unlike things: a genuine bug, and a transient failure raised below the tool's own error handling. Retry once with backoff; if it comes back identically, treat it as a bug and report it.

Among the in-band codes, only upstream_unavailable is worth retrying. internal is not — it means a retry returns the same error, not that we are having a bad minute.

Getting help​

If you're stuck — whether a call failed outright or the surface just doesn't look the way you expect — email support@edited.com with:

  • the tool name and arguments you called,
  • the full error envelope you got back, if there was one — plenty of problems arrive without an error at all,
  • serverInfo.version and the surface fingerprint from your initialize response — between them they identify exactly which build and which tool surface you were talking to, which is usually the difference between a same-day answer and a long conversation (see Versioning),
  • your session ID — read the mdmcp+data://session_id resource right after the failing call so EDITED can find your requests in the logs.