DocSpace Docs

MCP errors

DocSpace errors carry a stable, namespaced error_code next to an English message. Match on the error_code; the message is for people and can change.

Errors come back in one of two shapes.

Transport errors reject the whole HTTP request before any tool runs. They are JSON-RPC errors with the code in error.data.error_code:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Invalid or revoked agent key",
    "data": { "error_code": "mcp.unauthorized" }
  }
}

Tool errors come from a tool that ran (or was denied). The HTTP status is 200, the MCP result has isError: true, and its text content is a JSON object:

{
  "error": "Agent key is not allowed to call 'create_page' (requires scope 'pages:write' and a sufficient role)",
  "error_code": "mcp.scope_denied"
}

mcp.* codes

error_code Shape HTTP JSON-RPC Meaning What to do
mcp.unauthorized transport 401 (WWW-Authenticate: Bearer) -32001 No Authorization header, a header that is not Bearer dsk_<id>_<secret>, an unknown or wrong key, or a revoked key. Applies to every request, initialize included. Check the header; create a new key if this one was revoked or lost.
mcp.scope_denied tool 200 (tool result) The key lacks the tool's scope, or its role is below the scope's minimum role. Do not retry. Tell the user which scope or role is missing (Scopes and roles).
mcp.rate_limited transport 429 (Retry-After: 60) -32000 The key made more than 120 tool calls in 60 s. None of the calls in the request ran. Wait 60 s, then retry with fewer calls.
mcp.method_not_allowed transport 405 (Allow: POST) -32000 GET or DELETE on /mcp. The server is stateless: no SSE stream, no session. Use POST.
mcp.forbidden_host transport 403 -32000 Self-hosted local endpoint only: the request did not come from a loopback address with a localhost Host (and Origin, if sent). Connect from the same machine via localhost.
mcp.service_role_missing transport 503 -32603 Self-hosted only: the server has no SUPABASE_SERVICE_ROLE_KEY, so it cannot check keys or run tools. Configure the server (Self-hosting).
mcp.internal_error transport 500 -32603 Unexpected server failure (for example the key lookup failed). Retry later; report it if it persists.
mcp.invalid_request audit only n/a n/a Recorded in the key's activity when the request was malformed (bad JSON-RPC shape, arguments, tool name or headers) and was rejected before dispatch. The client receives the standard JSON-RPC/MCP validation error. Fix the request.
mcp.dispatch_error audit only n/a n/a Recorded when the MCP SDK rejected the tool name or arguments before the tool ran. The client receives the SDK's error. Check the tool name and arguments against the tool reference.
mcp.client_closed audit only n/a n/a Recorded when the client disconnected before the response was sent. Calls that had not started never run. None; retry if the call is still needed.

The three audit only codes never appear in a response body: you see them in Settings → Knowledge → Agents and keys → Activity.

Tool error codes from other domains

Tools also return the codes of the domain they work on, in the tool-error shape:

error_code Returned by Meaning
page.not_found page tools The page does not exist, is in another space, or is restricted to a team you cannot see. These three cases are indistinguishable on purpose.
page.forbidden append_block The page's access list gives the key's creator less than Editor.
context.invalid_input get_context Not exactly one of query, page_id, work_item_id, or a value out of range.
context.not_found get_context The anchor page or work item is missing or not readable.
context.forbidden get_context A work_item_id anchor without planner:read.
context.failed get_context The context pack could not be built.
mentions.invalid_term get_mentions The term is not 2–64 characters.
mentions.invalid_range get_mentions from/to is not a valid ISO date range of at most 60 months.
mentions.unavailable_encrypted get_mentions The space uses the strict protection level.
mentions.failed get_mentions The count could not be computed.
artifact.invalid_upload publish_artifact, update_artifact Empty or malformed HTML.
artifact.unsupported_type publish_artifact, update_artifact The content is not HTML.
artifact.too_large publish_artifact, update_artifact The HTML is over 10 MB.
artifact.secrets_detected publish_artifact, update_artifact The HTML contains something that looks like a secret. Always refused over MCP.
artifact.rate_limited publish_artifact, update_artifact More than 10 uploads per minute for this user.
artifact.forbidden publish_artifact, update_artifact Editor role required.
artifact.invalid_parent publish_artifact parent_page_id is missing, hidden or in another space.
artifact.not_found update_artifact The page is missing, in another space, or not an artifact.
artifact.storage_unavailable publish_artifact, update_artifact Artifact storage is not configured on the server.
artifact.publish_failed publish_artifact, update_artifact Unexpected failure while publishing.
auth.invalid_token tools with _token (self-hosted stdio only) The legacy user token could not be verified.
auth.clerk_not_configured tools with _token (self-hosted stdio only) The server cannot verify user tokens.

Errors without an error_code

Some older board, catalog, sync and planner tools still answer with a plain { "error": "<message>" } body and no error_code (for example not found, a membership Forbidden: …, or the write limit Rate limited: …). Treat any body with an error field as a failed call. These are being migrated to namespaced codes; this page will list the codes as they land.