An MCP request is rate limited
Inspect the error code as well as the HTTP status. HTTP 429 can mean a per-minute quota or a temporary admission limit:
| Response | Meaning | Next step |
|---|---|---|
pom_ai_mcp_rate_limited, OAuth rate_limited, or JSON-RPC -32029 with data.status: 429 |
The caller reached a per-minute quota. | Follow Retry-After or data.retry_after, or wait for the next minute window. |
pom_ai_task_busy |
The background queue is full or busy. | Wait for existing work and retry after the returned delay. |
pom_ai_mcp_rate_unavailable with HTTP 503 or JSON-RPC data.status: 503; OAuth temporarily_unavailable |
Request limiting could not be completed. | Retry later; repeated failures need administrator investigation, not a higher quota. |
Quota and queue errors can appear inside a tool response. Check isError and the returned error data even when HTTP status is 200. A refused status request does not cancel an already accepted task.
Wait before retrying
Stop immediate retry loops and follow the delay for the specific refusal. The configured read limit defaults to 60 per minute for protocol and catalog requests. Task submission has a separate budget of the greater of 120 or twice that setting; pom_get_task has the greater of 600 or ten times that setting. MCP authentication attempts have an early per-IP limit of the greater of 1,200 or twenty times the setting. OAuth registration, token and revocation each retain their separate limit of 5 per minute per IP.
Submission and task status respond directly without waiting for cron. Polling does not consume the submission or catalog budget. Read and write submissions share the same submission budget, and execution in cron does not charge the accepted task again.
When a task is still waiting
A task receipt is not a rate-limit error. Follow its poll_after_seconds while terminal is false. phase: waiting_for_dispatch means the task is waiting to be scheduled; waiting_for_cron means its site's cron runner has not started it yet; executing means work has begun. created_at and started_at help distinguish time waiting from time executing.
Each site can have one task ready for cron, and the whole installation runs one heavy operation at a time. Other cron events running successfully do not prove that the selected destination's task has started. If waiting persists, ask the administrator to check the cron runner for that destination. Keep the task ID; submitting the operation again creates more work instead of checking the original.
Stop automatic polling when terminal is true. Read result for completed or failed, including nested network isError values. For uncertain, inspect the destination before another write. An expired task did not start; a missing or expired receipt alone does not establish whether its operation ran. Never automatically replay an uncertain write.
Reduce unnecessary calls
- Cache
tools/list,resources/list, andprompts/listfor the current connection. - Read only the resource needed for the task.
- Use bounded pagination.
- Avoid polling unchanged objects.
- For background tasks, follow
poll_after_secondsand keep polling the existing task until it is terminal instead of resubmitting it. - Serialize writes and verify each result.
If a write’s response was lost before the rate-limit error appeared, read current state before submitting it again. A duplicate post, coupon, media attachment, or menu item is more difficult to repair than waiting.
Administrators can adjust the main MCP rate, which also scales the larger submission and status budgets. This does not change the fixed OAuth budgets, queue capacity or single heavy worker. Rate limits are unrelated to AI credits.
Related guides: rate-limiting contract, read-only audit, and write confirmation.