Skip to main content
The MCP route follows the JSON-RPC spec for errors and maps a few categories onto HTTP statuses. This page is the reference for what each error means and what your agent (or client) should do about it.

Error codes

HTTP status mapping

The spec calls for tool errors to come back as 200 with the error inside the JSON-RPC envelope — clients that conflate HTTP status with “did the call succeed?” will misread these. The MCP SDKs all do the right thing.

Plan-gated tools

Some tools are Builder-only. On a Free workspace they return -32603 with a PRO_REQUIRED message that names the gated feature. The full list lives in the tool reference — look for the Builder plan required annotation in each tool’s description. Launch beta highlights:
  • blocks.create — AI block generator. Free path: hand-author in the in-app editor.
  • schedule.set, schedule.pause, schedule.resume, schedule.delete, schedule.preview, schedule.runNow — entire scheduled-run surface is Builder-only.
  • dataSources.add, dataSources.editRefreshPolicy, dataSources.introspect, dataSources.testConnection, dataSources.triggerRefresh, dataSources.listMcpTools — data connections are Builder beta. Free workspaces can still list, read, and delete existing data sources.
  • byokKeys.add — BYOK is Builder beta. Free workspaces can still list or delete existing BYOK key metadata.
  • stores.connect, stores.disconnect, stores.refreshProducts — stores are Builder beta.
Coding agents: tool descriptions ending in (Builder plan required.) are gated server-side. Skip these on Free workspaces — call workspace.get first to read plan and limits.

Rate limits

Per-key sliding-window via @convex-dev/rate-limiter. The cap is resolved from workspace.plan at request time: Different keys for the same workspace get independent budgets — minting a second key buys you another 60/600/6000 RPM. The platform doesn’t penalize per-workspace, just per-key. When you hit the cap, the next call returns -32002 with HTTP 429 and a hint that includes the resume-time. Back off by ~60 / RPM seconds and retry.

Periodic limits

Two limits are time-windowed rather than rate-limited: Builds count every call to blocks.build (success or failure). AI-generated blocks count every blocks.create invocation. When you hit either, the next call returns -32603 with a LIMIT_REACHED message. Both limits expose resetsAt on the workspace.get limits payload, so agents can preflight.

Per-resource count caps

Create-time caps for workspace-owned resources. Hitting any of these returns LIMIT_REACHED from the relevant tool: See Plans and limits for the full table.

Preflight via workspace.get

The cheapest way to avoid a 4xx is to read limits first. workspace.get returns:
  • max: null means Infinity (members on Builder/Enterprise).
  • used: null on periodic limits means the rate-limiter doesn’t expose current consumption — only the cap.
  • resetsAt: null on count-based limits means there’s no time-based reset.

What’s next

Setup

Per-client configs for connecting Claude / Codex / Cursor / Windsurf.

Tool reference

Auto-generated list of every tool, with arg shapes and plan gates.