Skip to content

MCP: trusted client keys with a higher rate limit - #198

Open
JakeSCahill wants to merge 2 commits into
mainfrom
feature/mcp-trusted-client-keys
Open

MCP: trusted client keys with a higher rate limit#198
JakeSCahill wants to merge 2 commits into
mainfrom
feature/mcp-trusted-client-keys

Conversation

@JakeSCahill

@JakeSCahill JakeSCahill commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

The CS support bot (redleader-next) calls our docs MCP for every customer question and shares the public rate limit — 60 requests per 15 minutes per key. It gets throttled enough that it grew a local docs-index fallback, which is a lower-fidelity answer source for customers.

Two commits:

1. Trusted client keys with a higher local limit. Keys listed in MCP_TRUSTED_CLIENT_KEYS (comma-separated Netlify env var) presented via x-client-key get their own bucket with a higher limit (MCP_TRUSTED_CLIENT_LIMIT, default 600 per 15 min). Also fixes an existing limiter bypass: x-client-key used to key the bucket for any caller, so rotating the header minted a fresh bucket per request. Untrusted requests now always key by client IP; only trusted keys get key-based bucketing.

2. Dedicated upstream Kapa key for trusted clients. Our local tier can't stop public traffic from draining the single upstream KAPA_API_KEY budget, so trusted requests can optionally use KAPA_API_KEY_TRUSTED — a second Kapa key with its own upstream budget — for end-to-end isolation. The upstream client becomes a per-key connection pool. Tool handlers never see HTTP headers (the Netlify adapter leaves the MCP SDK's requestInfo empty — verified), so the limiter middleware records the trust decision in an AsyncLocalStorage that the tool handler reads back. With KAPA_API_KEY_TRUSTED unset, behavior is identical to a single key.

Tested: npx vitest run limiter-key.test.ts (5 passing), plus a local end-to-end run of the real handler under node:http with an invalid default key and a valid trusted key — untrusted and wrong-key requests fail upstream, the trusted client key returns a real docs answer.

Rollout: generate a client key (openssl rand -hex 24), set MCP_TRUSTED_CLIENT_KEYS in Netlify and share the key with the redleader-next config; ask Kapa for a second API key ([email protected]) and set it as KAPA_API_KEY_TRUSTED. Each piece works independently. Complements the retrieval filter in #197.

The CS support bot shares the public MCP rate limit (60 req / 15 min
per key) and gets throttled enough that it built a local docs-index
fallback. Add MCP_TRUSTED_CLIENT_KEYS: secret keys that get their own
bucket and a higher limit (MCP_TRUSTED_CLIENT_LIMIT, default 600 per
15 min).

Also closes an existing limiter bypass: x-client-key used to key the
bucket for ANY caller, so rotating the header minted fresh buckets.
Untrusted requests now always key by client IP (with the existing
proxy-header fallbacks); only keys in MCP_TRUSTED_CLIENT_KEYS get
key-based bucketing.
@JakeSCahill
JakeSCahill requested a review from a team as a code owner July 29, 2026 12:14
@netlify

netlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploy Preview for redpanda-documentation ready!

Name Link
🔨 Latest commit ea44c16
🔍 Latest deploy log https://app.netlify.com/projects/redpanda-documentation/deploys/6a69f2ce507d890008eede25
😎 Deploy Preview https://deploy-preview-198--redpanda-documentation.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 83 (🔴 down 2 from production)
Accessibility: 93 (🔴 down 1 from production)
Best Practices: 92 (no change from production)
SEO: 83 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

With one KAPA_API_KEY, the support bot and all public MCP traffic drain
the same upstream Kapa budget, so our own trusted tier can't stop
public 429s from starving the bot. Add optional KAPA_API_KEY_TRUSTED:
requests presenting a trusted x-client-key use it upstream, giving the
bot its own Kapa budget end to end.

The upstream client becomes a small per-key pool (client + transport
per key, reset scoped per key; the process-guard reset clears all).
Tool handlers can't see HTTP headers (the Netlify adapter doesn't
populate the MCP SDK's requestInfo — verified empty), so the limiter
middleware records the trust decision in an AsyncLocalStorage the
handler reads back.

Unset KAPA_API_KEY_TRUSTED = single-key behavior, unchanged.

Tested locally by running the handler under node:http with an invalid
default key and a valid trusted key: untrusted and wrong-key requests
fail upstream, the trusted client key gets a real answer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant