Rate limits in an MCP trading setup
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.
Rate limits are a boring operational topic right up to the moment one fires on an order submission, at which point they become a correctness problem. That transition is what this covers.
Why a model hits limits faster than you would
A person checking a position makes one request. A model answering “how is my portfolio doing” may fetch balances, then positions, then tickers for each symbol, then recent fills, then re-fetch something it already had because the conversation moved on. Each step is reasonable; the aggregate is bursty in a way hand-written clients are not.
Two properties make it worse. Models re-fetch rather than cache, because the context is the cache and it is not obvious to the model what is stale. And retries look free — a failed call is just a tool result to reason about, so the natural next move is to try again.
The specification puts this on the server
MCP is explicit about where the obligation sits:
Servers MUST:
- Validate all tool inputs
- Implement proper access controls
- Rate limit tool invocations
- Sanitize tool outputs
So a well-built exchange MCP server should be throttling before your requests reach the venue. Whether the one you installed does is a different question, and worth checking rather than assuming.
What the venues actually enforce
The shapes differ enough that you cannot reason about one from another.
Binance uses request weight, not request count — endpoints cost
different amounts. Exceeding it returns -1003 TOO_MANY_REQUESTS, with messages
about weight used against the current limit, and severe violations escalate to
an IP ban signalled by HTTP 418. HTTP 429 is the ordinary rate-limit
response.
Bybit distinguishes two things that need different fixes:
| Code | Meaning | Fix |
|---|---|---|
10006 (UTA) | “Too many visits. Exceeded the API Rate Limit.” | Slow down |
10018 (UTA) | “Exceeded the IP Rate Limit.” | Stop sharing the IP across accounts |
429 (HTTP) | System-level frequency protection | Retry |
20003 (WebSocket) | “Too frequent requests under the same session” | Fewer messages per session |
Bybit also documents HTTP 403 for IP rate limit breaches — and, separately, for
requests from US IPs, which is a different problem wearing the same status code.
OKX returns 50011: “Rate limit reached. Please refer to API documentation
and throttle requests accordingly.”
Hyperliquid has the most unusual model, and it catches new accounts. There is an IP limit — 1200 REST requests per minute, weighted — and separately an address-based allowance earned by trading: one request per 1 USDC of cumulative volume since the address existed, with an initial buffer of 10,000 requests. Open orders are capped at 1,000 by default, rising by one per 5M USDC of volume to a maximum of 5,000.
The consequence is counterintuitive: a brand-new Hyperliquid account has a small request budget regardless of how generous the IP limit looks. A model exploring your account can burn the initial buffer without placing a single trade.
Per-endpoint quotas for all of these are volatile and live in each venue’s own documentation. Check there rather than trusting a number in an article.
The part that is not merely operational
CCXT classifies RateLimitExceeded under NetworkError, which sits under
OperationFailed — the branch meaning the outcome is unknown. The other
branch, ExchangeError, means the exchange understood and refused.
That placement is correct and it has a consequence people miss. A rate-limit
response on a read is a nuisance: retry, get your data. A rate-limit response on
createOrder is ambiguous. Did the request get rejected at the gate, or did
it reach the matching engine before the limiter caught up?
Most of the time it is the former. “Most of the time” is not a property you want governing whether a retry doubles your position.
So: never blind-retry an order on a rate-limit error. Reconcile first — query open orders and positions, establish what exists, then decide. This is the same discipline that timeouts require, for the same reason.
Relatedly, MCP’s idempotentHint defaults to false, described in the schema as
whether “calling the tool repeatedly with the same arguments will have no
additional effect on the its environment”. For an order tool that default is
correct. Any client or wrapper that retries tool calls automatically should be
respecting it.
What to do
Separate read traffic from order traffic. Reads are the bulk of the volume and the thing that exhausts the budget. If the same limiter governs both, an exploratory question can leave you unable to place or cancel an order — which is the worst possible moment to be rate limited.
Reserve headroom for cancels. Whatever your budget, some of it should be unavailable to routine polling. Getting out matters more than getting data.
Throttle at the server, not in the prompt. Asking the model to make fewer calls is a limit expressed as a suggestion. The specification puts rate limiting on the server for a reason.
Watch for the escalation. Binance’s 418 IP ban is a different state from
429, and it outlasts the burst that caused it. Backing off on 429 is what
keeps you out of it.
Check the address-based limit on Hyperliquid. If an automated client on a new account behaves oddly, this is a strong first suspect and not one most people think of.
FAQ
Whose job is rate limiting — the server or the client?
The MCP specification puts it on the server: servers MUST “rate limit tool invocations”. In practice you should verify your server does it rather than assume, since the consequences land on your account. Client-side throttling is a reasonable belt-and-braces addition, and asking the model to self-limit is not a substitute for either.
Is it safe to retry an order that failed with a rate-limit error?
Not without checking first. CCXT classifies RateLimitExceeded under
NetworkError and OperationFailed, the branch that means the outcome is
unknown. The order was probably rejected before reaching the engine, but
“probably” is doing too much work when the downside is a doubled position. Query
open orders and positions, then decide.
Why does a new Hyperliquid account run out of requests so quickly?
Because request allowance is earned by volume: one request per 1 USDC traded cumulatively since the address existed, on top of an initial 10,000-request buffer. A new address has only the buffer, so an automated client doing exploratory reads can exhaust it without trading. The IP limit being generous does not help.
Does a rate limit error mean I have been banned?
Usually not — 429 is ordinary throttling. Binance escalates severe or repeated
violations to an IP ban signalled by HTTP 418, which is a distinct state and
persists beyond the burst. Treat 429 as the warning it is.