mcp

Do I need Dynamic Client Registration for remote MCP?

No—you do not always need Dynamic Client Registration (DCR, RFC 7591) for remote MCP. DCR lets an OAuth client register itself with your authorization server at runtime and receive a CLIENT_ID. Use it when many unknown clients must Connect and your AS implements DCR cleanly. Skip it when the AS has no DCR: ship a documented static CLIENT_ID path and prove Connect in both Cursor and Claude. Either way you still need Protected Resource Metadata (PRM), Auth Code + PKCE, and a clean 401 + WWW-Authenticate + resource_metadata challenge. Soft path: /free. End-to-end remote auth layout: the MCP Starter Kit ($27).

What DCR is (plain English)

DCR is how a client says “here’s who I am” to your authorization server without you minting every client id by hand. The AS returns a client id (and related registration data). Remote MCP Connect flows sometimes expect that path when the IDE hasn’t been pre-provisioned.

DCR is not a substitute for OAuth itself. It does not replace PKCE, PRM, or the 401 challenge. It only answers: *how does this client get a `CLIENT_ID`?*

End-to-end remote MCP OAuth (shared by Cursor and Claude): Build a remote MCP server with OAuth that Cursor and Claude can both Connect to. Skim checklist for PKCE / PRM / redirects: `mcp-auth-checklist-pkce-prm`. When Cursor works and Claude doesn’t: `claude-vs-cursor-mcp-auth`.

Decision tree: DCR vs static CLIENT_ID

text
Does your authorization server support DCR (RFC 7591)?
├─ NO  → Static CLIENT_ID path
│         • Provision CLIENT_ID (and secret handling) in AS admin
│         • Document env / client auth fields for Cursor and Claude
│         • Never put secrets in chat, AGENTS.md, or published mcp.json
│         • Test Connect on both clients with the static client
│
└─ YES → Will many unknown clients Connect without hand-minted IDs?
          ├─ YES → Prefer DCR; still ship PRM + Auth Code + PKCE
          │         • Verify registration endpoint works under real Connect
          │         • Keep a static fallback doc for AS outages / clients that skip DCR
          └─ NO  → Static CLIENT_ID is enough (often simpler to operate)
                    • Same PKCE / PRM requirements as the DCR path
                    • Dual-client test still required

Still required on every branch: unprotected probe → 401 with `WWW-Authenticate` + `resource_metadata` → browser Auth Code + PKCE → tools appear. Skipping DCR does not let you swap that for API-key headers and call it MCP OAuth.

What breaks when DCR is expected but unsupported

SymptomLikely causeFix
Connect errors on every registration attemptClient expects DCR; AS has noneStop chasing “OAuth bugs”; switch to static `CLIENT_ID` and document it
Cursor registers, Claude fails (or reverse)Client DCR / static paths differDual-client test; see `claude-vs-cursor-mcp-auth`
Login works, tools never appearAudience / resource mismatch — not a DCR issueFix PRM resource binding first
Secrets leaked in client config`CLIENT_SECRET` committed or pasted in chatEnv / secret store only; scrub published `mcp.json`

Debug order: confirm AS DCR support (or admit it doesn’t) → choose static vs DCR from the tree → verify 401 + PRM + PKCE → then client-specific Connect. Inspector before IDE rabbit holes.

Static CLIENT_ID path (when you skip DCR)

  1. Create the OAuth client in your AS admin UI (or IaC).
  2. Store `CLIENT_ID` / secret in server-side env or a secret store—not in AGENTS.md, not in a committed public client config.
  3. Wire the client auth fields your IDE documents for remote MCP (Cursor and Claude each have their own shape).
  4. Register each client’s redirect URI exactly.
  5. Prove Connect in both Cursor and Claude.

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

What the MCP Starter Kit is for

The MCP Starter Kit ($27) packages a remote MCP layout with Cursor and Claude Connect in mind—including the static-client fallback when DCR isn’t on the table. Soft path: /free for the starter desk, then the kit when you’re wiring production auth. Use the checklist `mcp-auth-checklist-pkce-prm` when you want PKCE / PRM / redirects on one page.

Soft next step

Run the decision tree once: DCR if the AS supports it and you need unknown clients; otherwise static `CLIENT_ID` with dual-client proof. Keep PKCE and PRM either way. Soft path: /free. Kit path: MCP Starter Kit ($27). Cross-link the live MCP OAuth pillar, `mcp-auth-checklist-pkce-prm`, and `claude-vs-cursor-mcp-auth` when one client Connects and the other doesn’t.

FAQ

What is Dynamic Client Registration (DCR)?+

DCR (RFC 7591) lets the OAuth client register itself with your authorization server at runtime and receive a client id — useful when you can’t pre-provision every IDE/client.

Do I always need DCR for remote MCP?+

No. If your AS doesn’t support DCR, ship a documented static CLIENT_ID path and test Connect in both Cursor and Claude with that static client.

When is DCR the better path?+

When many unknown clients must Connect without you minting each CLIENT_ID by hand, and your authorization server actually implements DCR cleanly.

What breaks if DCR is expected but unsupported?+

Connect errors on every registration attempt. Stop chasing “OAuth bugs” and switch to the static-client fallback — document env vars and never put secrets in chat or published mcp.json.

Where does CLIENT_ID live in the static path?+

Server-side / AS admin config and client auth fields your IDE documents — never in AGENTS.md, never in a committed public client config that ships secrets.

Does skipping DCR change PKCE or PRM?+

No. You still need a clean 401 + WWW-Authenticate + resource_metadata and Auth Code + PKCE for remote Connect. DCR is only about how the client gets its client id.

Soft next step?+

Decide DCR vs static with a one-page tree, try /free, then /products/mcp-starter-kit ($27) when you want the end-to-end remote auth layout.

Get the free starter

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