mcp

MCP auth checklist (PKCE, PRM, redirects)

Remote MCP Connect fails for boring reasons more often than exotic ones: a stripped challenge header, a one-character redirect mismatch, or a static CLIENT_ID you never documented. This is the skim companion to the full remote OAuth recipe—PKCE, Protected Resource Metadata, redirects, and the first checks when Cursor or Claude won’t finish auth. Keep it next to your runbook. Soft path: the free desk on /free, then the Cheat Sheet for this checklist mindset, or the MCP Starter Kit ($27) when you want the kit-backed layout.

Who this is for

You already have (or are building) a remote MCP URL. You need a pocket checklist before you burn another hour in client settings. For the end-to-end server recipe, use the pillar post; this page is the skim.

PKCE + Authorization Code

  • [ ] Remote Connect uses Authorization Code + PKCE—not a long-lived API key in a header labeled “OAuth.”
  • [ ] Browser login completes; the client receives tokens via the OAuth redirect.
  • [ ] You are not treating Postman-with-API-key success as proof MCP OAuth works.

API keys can demo a private URL. They are not the same as MCP OAuth PKCE for Connect.

PRM / `WWW-Authenticate`

  • [ ] Unauthenticated probe of the remote MCP URL returns 401.
  • [ ] Response includes `WWW-Authenticate` with `resource_metadata` pointing at your Protected Resource Metadata (PRM).
  • [ ] Middleware, CDN, or HTML error pages do not strip that challenge.
  • [ ] PRM resource identifier matches what the authorization server mints (audience / resource binding).

If step one fails, stop. Fix the challenge before Cursor vs Claude UI quirks.

Redirect URI table

ClientWhat to registerFailure mode
CursorDocumented callback (commonly `cursor://…/oauth/callback`)Login succeeds, Connect never finishes
ClaudeDocumented `/mcp` OAuth / callback-port path for your buildCursor works, Claude fails (or reverse)
BothExact string match on the ASOne-character mismatch fails after login

Register each client’s URI. Cursor success is not Claude proof.

Where `CLIENT_ID` lives

  • Server-side env / secret store / AS admin—never chat, never published client `mcp.json`, never `AGENTS.md`.
  • If the AS lacks Dynamic Client Registration (DCR), ship a static `CLIENT_ID` path and document it for both clients. See also Do I need DCR?.

Failure skim (check this order)

  1. MCP Inspector against the remote URL.
  2. Confirm 401 + `WWW-Authenticate` + `resource_metadata`.
  3. Then client-specific Connect / redirect / static-client settings.
  4. If only one client fails, diff redirects and DCR vs static—Why Claude fails when Cursor works.

Full narrative and failure card: Build a remote MCP server with OAuth….

Cheat Sheet + MCP kit

The Cheat Sheet is the skim home for this checklist. The MCP Starter Kit ($27) is the kit-backed remote auth layout when you’re done stitching docs. Soft start: /free.

Soft next step

Confirm the challenge (401 + `WWW-Authenticate` + `resource_metadata`), register both redirect URIs, and keep secrets out of client configs. Soft path: /free, then Cheat Sheet for the pocket checklist, or the MCP Starter Kit ($27) for the end-to-end remote layout. Full recipe stays on the OAuth pillar.

FAQ

PKCE vs API-key headers for MCP?+

API keys prove the request knows a secret. PKCE is part of the browser OAuth grant remote Connect flows expect — different job than a static header on every call.

What is PRM / resource_metadata?+

Protected Resource Metadata tells the client where your authorization server lives and which resource the token must cover. Without a clean 401 + WWW-Authenticate that exposes it, Connect never starts.

Which redirect URIs for Cursor vs Claude?+

Register each client’s documented callback exactly (Cursor often uses a cursor://…/oauth/callback form; Claude uses its own callback-port / documented path). A one-character mismatch fails after login.

Where does CLIENT_ID live?+

Server-side env or secret store — never in chat, never in a published client mcp.json, never in AGENTS.md.

When is static auth required?+

When your authorization server doesn’t support Dynamic Client Registration. Ship a documented static CLIENT_ID path and test both Cursor and Claude.

What do I check first when Connect breaks?+

MCP Inspector on the remote URL → confirm 401 + WWW-Authenticate + resource_metadata before client UI settings. Full recipe: the remote OAuth pillar post.

Soft next step?+

Skim this checklist, try /free, then Cheat Sheet or /products/mcp-starter-kit ($27) when you want the kit-backed layout.

Get the free starter

Value first, then a kit when you are ready. No fake urgency. Start with Harness Desk Starter at /free.