Per-scope request-rate limits for MCP calls, expressed in requests per minute (rpm). A value
of means unlimited. Every limit except is counted separately for the admin and
shop endpoints. An over-limit request is refused with HTTP and a header,
except an over-limit tool call inside an open session, which returns an tool result
instead.
oauthIp429Retry-AfterisError{ rpm: number }{ rpm: 60 }Requests per minute allowed per MCP session. A signed-in caller is counted by their
Vendure session. An anonymous /mcp/shop caller is counted by client IP instead.
{ rpm: number }{ rpm: 120 }Requests per minute allowed per signed-in user, counted across every session and OAuth
client acting for that user. Authorizing again can start a new session and client record,
but the user bucket keeps counting through both, since the user's id does not change.
Anonymous callers have no user, so anonymousIp covers them instead.
{ rpm: number }{ rpm: 3000 }Requests per minute allowed per registered OAuth client, counted across every user of that
client. One client record can serve all of a store's shoppers, so the default is sized for a
whole application's traffic. perUser limits an individual instead. A client identified by
a metadata document URL (CIMD) gets one record per URL. Requests with no OAuth grant, such as
in-process or anonymous calls, have no client bucket.
Record<string, { rpm: number }>{ place_order: { rpm: 5 }, create_product: { rpm: 10 }, refund_order: { rpm: 5 }, cancel_order: { rpm: 5 } }Requests per minute allowed per tool, keyed by tool name. 0 means unlimited. Each caller
has its own bucket per tool: an OAuth caller is counted by client plus session, an anonymous
caller by client IP. A new authorization creates a new session, so its per-tool counters
start fresh. oauthIp bounds how often one address can re-authorize, while perUser keeps
counting across authorizations.
{ rpm: number } | false{ rpm: 60 }Requests per minute allowed per client IP for anonymous /mcp/shop calls. false
disables the limit. Behind a reverse proxy, enable Vendure's trustProxy so
req.ip reports the client address rather than the proxy's.
{ rpm: number } | false{ rpm: 60 }Requests per minute allowed per client IP across the whole OAuth HTTP surface. Every route
on the OAuth controller shares this one bucket, including the .well-known metadata
documents. The same limit also caps failed bearer-token authentications on the MCP
endpoints, in a separate per-IP bucket, so an address over its limit is refused before its
token costs a database lookup. false disables the limit. Behind a reverse proxy, enable
Vendure's trustProxy so req.ip reports the client address rather than the proxy's.
Architecture reviews, custom plugin work, migrations, ongoing support. Get a hand from the team that builds Vendure.
Talk to the team0