Enable rate limiting for the CloudBees CI MCP Router

3 minute read

The CloudBees CI MCP Router can cap how quickly a single caller reaches its /mcp endpoint, so that one misconfigured client or a runaway agent loop cannot flood the CloudBees CI MCP Router and overwhelm the controllers behind it. Rate limiting is disabled by default. Enable it when you are ready to protect a shared or public deployment.

How rate limiting works

Rate limiting gives each caller its own allowance of requests over a rolling window of time. Each request consumes one unit of the allowance, which refills steadily as the window progresses. If you know the pattern, this is a per-identity token bucket.

While a caller stays within its allowance, its requests pass straight through without being rate limited. Once the allowance runs out, further requests receive an HTTP 429 Too Many Requests response with a Retry-After header that tells the client how long to wait before trying again.

The check runs at the very front of the /mcp endpoint, before any message is parsed, so it applies to the whole MCP conversation, including initialize, tools/list, and tools/call.

The CloudBees CI MCP Router identifies each caller in one of two ways:

  • Authenticated callers are keyed by a hash of their Authorization header, so the raw credential is never stored, and each token or user gets its own allowance.

  • Callers with no Authorization header are keyed by their client IP address, so one anonymous flood cannot lock everyone else out.

Enable rate limiting

To turn on rate limiting, set MCP_RATE_LIMIT_ENABLED to true on the CloudBees CI MCP Router when you deploy it. The remaining variables are optional; they refine the limit and take the defaults shown below.

If you deploy the CloudBees CI MCP Router with the cloudbees-core Helm chart, set these variables using McpRouter.extraEnv instead.

Before you enable it, watch normal traffic for a while and pick a ceiling that leaves legitimate agents comfortable headroom. A good starting point is roughly twice your observed peak, which stops abuse without throttling healthy clients.

Rate limiting environment variables

Environment variable Possible values Description

MCP_RATE_LIMIT_ENABLED

true or false
(default: false)

The master switch. Set it to true to enforce rate limiting.

MCP_RATE_LIMIT_PERMITS

A positive whole number
(default: 120)

The maximum number of requests each caller can make within one window.

MCP_RATE_LIMIT_WINDOW

A number with the suffix H (hours), M (minutes), or S (seconds), such as 1M or 30S
(default: 1M)

The window over which each caller’s allowance refills.

MCP_RATE_LIMIT_MAX_BUCKETS

A positive whole number
(default: 100000)

The maximum number of distinct callers tracked at once. When this limit is reached, the limiter evicts the least recently seen caller, which caps how much memory it can use.

MCP_RATE_LIMIT_TRUST_FORWARDED_FOR

true or false
(default: false)

Whether to trust the X-Forwarded-For header when keying anonymous callers by IP address. Leave it disabled unless a trusted proxy sets the header. For more information, refer to Security considerations.

With the defaults, each caller is allowed 120 requests per minute.

Security considerations

Rate limiting is a protective control, so keep the following in mind when you configure it.

Enable MCP_RATE_LIMIT_TRUST_FORWARDED_FOR only when a trusted ingress or load balancer sets the X-Forwarded-For header. Clients can forge that header, so if the CloudBees CI MCP Router is directly reachable, a caller could dodge the limit by sending a different value on every request. When the setting is disabled (the default), anonymous callers are keyed by the IP address of their direct connection instead.

Rate limiting protects availability, not access. It limits how often a caller can reach the CloudBees CI MCP Router, but it does not authenticate or authorize anyone, so keep OAuth or another authentication method in place as well.

Authenticated callers are keyed by a hash of their Authorization header, so raw tokens and passwords are never stored. MCP_RATE_LIMIT_MAX_BUCKETS also caps how many callers are tracked at once and evicts the least recently seen when the cap is reached, so a flood of ever-changing identities cannot grow the limiter’s memory without bound.