Build MCP· MCP auth

Every customer as themselves.
Never a shared key.

The hard part of a customer-facing MCP server isn't the tools — it's identity. Command+K's gateway gives every customer their own credential, validated and encrypted, with OAuth 2.1 discovery, dynamic client registration and PKCE handled for you. Verified end to end with the production clients of Claude, Cursor and ChatGPT.

Per-customer identity

Own API key or own OAuth account per customer. Your API sees them exactly like normal API traffic — because it is.

OAuth 2.1 done for you

Protected-resource metadata, dynamic client registration, PKCE, refresh rotation, reuse detection — the whole authorization server, hosted.

Attribution & revocation

Every log line carries the customer. Revoke one customer in one click without touching the rest.

Why "just share an API key" fails in production

Most MCP demos hardcode one key. The moment paying customers arrive, that key is a liability: no per-customer limits, no attribution, no individual revocation — and one leak exposes every account. The fix isn't a better secret. It's identity per customer, enforced at a gateway in front of your API.

Five modes, one mental model

ModeBest forHow it works
Customer API keys (recommended)SaaS products whose customers already hold API keysCustomer pastes their own key once on your hosted connect page; it's validated against your API, encrypted, and forwarded per call.
Auto-connect (OAuth wrap)The smoothest onboarding on top of customer keysCustomer just adds your MCP URL to Claude — the connect screen opens automatically via OAuth discovery + Dynamic Client Registration.
Customer OAuth (proxy)Products with their own OAuth serverWe bridge Claude to your authorization server, store per-customer tokens encrypted, and refresh them silently.
Webhook verifyCustom approval logicWe call your HMAC-signed webhook with the customer's identity; you decide who gets in and with which tool scopes.
Shared token / openInternal team use or public read-only dataExplicitly labelled as such in the dashboard — never the default for customer-facing MCPs.

What the customer experiences

They paste your MCP URL into Claude. Claude hits the endpoint, reads the OAuth discovery metadata, registers itself, and opens this hosted screen — branded with your MCP's name and logo:

Command+K hosted connect page for the AnnounceKit MCP: the customer enters their email and their own AnnounceKit API key; the key is validated against the API, stored encrypted, and a personal MCP access token is issued.
The hosted connect page — what your customer sees. Opens automatically when they add your MCP URL to Claude.

From that moment, every single call carries their identity — visible in your request log, enforceable in your limits, billable if you choose:

commandplusk.com/dashboard — Logs · All MCPs
AtEventToolCustomerOutcome
9:20 PMtools/list—admin@commandplusk.comSuccess 363 ms
8:57 PMtools/callpostada@loopwork.ioSuccess 867 ms
8:45 PMtools/calllabelsada@loopwork.ioSuccess 295 ms
8:33 PMtools/callactivitiesfelix@brightpath.appSuccess 843 ms
8:21 PMtools/callget_latest_activitiesfelix@brightpath.appSuccess 891 ms
8:03 PMtools/callpostsada@loopwork.ioFailed 593 ms
7:48 PMtools/callmefelix@brightpath.appSuccess 488 ms

Per-request logs kept 30 days · daily aggregates forever · system events filterable

Security posture

  • Credentials encrypted at rest (AES-GCM); decrypted only inside the gateway at call time.
  • Gateway tokens stored as hashes — a database read never yields a usable token.
  • Refresh-token rotation with reuse detection — a replayed refresh token burns the whole session family.
  • Per-customer + per-deployment rate limits, monthly caps, origin/IP allowlists — enforced before your API is touched.
  • Full request log incl. auth failures, client IP and user agent — 30-day retention, CSV export.

Battle-tested against real clients

OAuth discovery, DCR, PKCE and the transport edge cases (SSE probes, CORS preflights) are verified against the production clients of Claude, Cursor and ChatGPT — not just the spec document. Your endpoint inherits those fixes automatically.

Publish an authenticated MCP →