Rate Limit
The MCP server spends the same limits as the REST API, counted per person in the organization — not per token —, plus a limit of its own for the protocol. Minting a new token, or re-authorizing the client, does not reset the budget.
| Budget | What counts | Limit (production) |
|---|---|---|
| MCP protocol | every request to / (initialize, tools/list, ping, tools/call) | 1000/hour per person in the organization |
| API reads | every tools/call of a read tool | the API's |
| API writes | every tools/call of a write or destructive tool | the API's |
| Money-moving actions | send_to_bank, cancel_dispatch, charge, charge_cancel | the API's |
A tool call is never cheaper than the endpoint it mirrors: it is counted against the protocol budget and, again, against the API budget the same REST call would spend — with the same budget size as the API, per person. An agent sweeping listings in a loop does not get around the limit the same sweep would pay over REST. There is also a per-IP ceiling, far above any legitimate use.
When the limit is reached
On the protocol, the server answers 429 and the JSON-RPC message is not processed at all:
HTTP/1.1 429 Too Many Requests
Retry-After: 37
Content-Type: application/json
{ "error": { "code": "RATE_LIMITED", "message": "MCP request rate limit exceeded for this person in this organization." } }
On the API budget, the tool returns an error result, for the model to read and wait:
{ "isError": true, "content": [{ "type": "text",
"text": "{ \"error\": { \"code\": \"RATE_LIMITED\", \"details\": { \"retry_after_seconds\": 37 } } }" }] }
Either way, wait the indicated seconds before trying again.
Spending less
An agent consumes the same budget as your backend — and, for reads, that budget is small. Three habits cover almost everything:
- Filter before paging.
finance_payables_list { filters: { status: "pending", due_date: { lte: "2026-11-30" } } }costs one call; fetching everything to filter in the model costs dozens. - Use the ready-made totals. "How much is due this month" is one call to
finance_payables_aggregates, not a sweep offinance_payables_list. - Ask only for the columns you need.
fieldsdoes not reduce the number of calls, but it greatly reduces the context spent — see Listing, filters and fields.