mcp

Build a remote MCP server with OAuth that Cursor and Claude can both Connect to

A local MCP server that talks over stdio is a different animal from a remote MCP server that Cursor or Claude has to Connect to. Remote Connect almost always means OAuth: Protected Resource Metadata, an authorization code flow with PKCE, and a challenge header that survives your reverse proxy. This guide is the end-to-end recipe for that path—what to implement, where Cursor and Claude diverge, and the failure modes that waste a day. When you want a kit-backed pattern instead of stitching blogs together, start with the free desk on /free or go straight to the MCP Starter Kit ($27).

The problem you’ll actually hit

You ship a remote URL. In Cursor, the MCP entry sits on “Needs authentication.” In Claude, `/mcp` OAuth fails after login, or never opens a browser. Both clients can see the same host and still disagree about redirect URIs, Dynamic Client Registration (DCR), and how they send audience / resource parameters. Official Cursor and Claude MCP auth docs cover the pieces. What’s missing in most writeups is one working sequence that survives both clients—and a clear failure card when middleware eats the challenge.

Spec pieces in plain language (no fake scores)

You don’t need to memorize RFCs to ship this, but you do need the names:

  • Protected Resource Metadata (PRM, RFC 9728) — your MCP resource publishes metadata (often under a `.well-known` path) so the client knows which authorization server protects it.
  • Authorization Server Metadata — the AS advertises token and authorization endpoints.
  • Authorization Code + PKCE — the browser login dance remote clients expect; don’t swap this for a long-lived API key in a header and call it “OAuth.”
  • Dynamic Client Registration (DCR, RFC 7591) — optional. If your AS supports it, clients can register at runtime. If not, you ship a static `CLIENT_ID` (and careful secret handling) and document that path for both Cursor and Claude.
  • Audience / resource binding — tokens must be minted for the right resource. Wrong audience looks like “login succeeded, tools never appear.”

API key headers on a remote URL can work for a private demo. They are not the same as MCP OAuth PKCE for Connect.

Minimal happy path

Aim for this sequence before you chase client-specific settings:

  1. Client probes the remote MCP URL without credentials.
  2. Server returns 401 with a `WWW-Authenticate` challenge that includes `resource_metadata` (pointing at your PRM).
  3. Client opens a browser against your authorization server.
  4. User completes login; client receives tokens via the OAuth redirect.
  5. Client retries MCP; tools appear.

If step 2 never happens cleanly, stop. Fix the challenge before you debug Cursor vs Claude UI quirks.

Cursor: remote URL, Connect, redirect URIs

In Cursor, configure a remote MCP server with a `url` (not only a local command). Use the Connect control when the server needs authentication. Register the Cursor redirect URI your build documents—commonly a `cursor://…/oauth/callback` style URI. When DCR is unavailable, set a static `auth.CLIENT_ID` (and related fields) in the way Cursor’s MCP auth docs describe for your version—don’t invent keys in chat or commit secrets into a shared `mcp.json` you publish.

Test Connect on the real remote URL, not only on localhost tunnels that strip headers.

Claude: `/mcp` OAuth and the static-client path

Claude’s MCP OAuth path (including `/mcp` flows and callback-port behavior) is close but not identical. If DCR is missing, plan on pre-configured credentials and document the static-client setup explicitly. A setup that “works in Cursor” is not proof Claude will finish the same dance—run both.

Point readers at Claude’s MCP auth docs and Cursor’s MCP docs as authorities for client UI details; this article owns the server-side recipe and the dual-client checklist.

Failure card (fix this first when Connect breaks)

SymptomLikely causeWhat to check
Connect never opens a login UIMiddleware or CDN stripping `WWW-Authenticate`Raw 401 response includes `resource_metadata`; bypass HTML error pages
Login works, tools never loadWrong audience / resource on the tokenPRM resource identifier matches what the AS mints
Cursor works, Claude fails (or reverse)Redirect URI, DCR, or client auth differencesTest both clients; don’t assume parity
DCR errors on every ConnectAS doesn’t support DCRShip static `CLIENT_ID` path and document it
Intermittent 401 after successClock skew, cookie/proxy caching, or token refresh pathInspector + server logs around refresh
“Works in Postman” but not in CursorYou’re sending API keys, not completing MCP OAuthHappy path must start from the 401 challenge

Debug order: MCP Inspector against the remote URL → confirm 401 + `WWW-Authenticate` + `resource_metadata` → then client-specific Connect settings.

What the MCP Starter Kit is for

The MCP Starter Kit ($27) is aimed at shipping remote MCP with Cursor and Claude Connect in mind—not only a local stdio hello-world. Use it when you want a kit-backed layout and examples instead of assembling half a dozen vendor posts. Pair it with a skimmable auth checklist (Cheat Sheet) when you want the failure card in your pocket. Soft path if you’re not ready to buy: grab the free starter desk at /free, then come back to the kit when you’re wiring production Connect.

If you’re also wiring coding agents that *consume* MCP tools, see the Agent Starter Kit—different job, same agent-ops shelf.

Soft next step

Get the challenge right (401 + `WWW-Authenticate` + `resource_metadata`), then prove Connect in both Cursor and Claude. When you want the pattern packaged, use /free for the starter desk, or the MCP Starter Kit ($27) for the auth-ready layout. No rush—ship the failure card into your own runbook either way.

FAQ

Do I need OAuth for local stdio MCP?+

No. Local stdio MCP often uses simpler auth (or none in dev). Remote MCP that a client “Connects” to over the network is where OAuth, Protected Resource Metadata, and PKCE matter.

What’s Dynamic Client Registration (DCR) and when can I skip it?+

DCR (RFC 7591) lets the client register itself with your authorization server at runtime. If your AS doesn’t support DCR, ship a pre-configured CLIENT_ID (and secret handling) and document the static-client path for Cursor and Claude.

Why does Cursor connect but Claude doesn’t (or vice versa)?+

Clients differ on redirect URIs, DCR support, and how they send audience/resource parameters. Test both: Cursor remote url + Connect button, and Claude /mcp OAuth—don’t assume one success means both work.

Where do I put CLIENT_ID / CLIENT_SECRET safely?+

In server-side env / secret store—never in chat, never in committed mcp.json that ships to clients, never in AGENTS.md. Document required env vars in the kit README.

How do I debug with MCP Inspector?+

Use MCP Inspector against the remote URL; confirm the 401 + WWW-Authenticate challenge exposes resource_metadata before you chase client-specific bugs.

What does a minimal happy path look like?+

Unprotected probe → 401 with WWW-Authenticate + resource_metadata → browser login → tools appear in the client. If the middleware strips WWW-Authenticate, Connect fails before OAuth UI even opens.

What’s the difference between API key headers and MCP OAuth PKCE?+

API keys in headers prove “this request knows a secret.” MCP OAuth PKCE is a browser login + token grant bound to your resource metadata—what remote Connect flows expect when the client manages auth for you.

Where do I register the Cursor OAuth redirect URI?+

With your authorization server, using the redirect URI Cursor documents for MCP OAuth (commonly a cursor://…/oauth/callback form). Match it exactly; a one-character mismatch fails after login.

What’s the ShipKits MCP Starter Kit for?+

A kit-backed end-to-end recipe and examples for shipping remote MCP (not only local demos), with Cursor and Claude Connect in mind—see the MCP Starter Kit ($27) at /products/mcp-starter-kit. Soft path: try free resources on /free first if you want the checklist mindset before buying.

Get the free starter

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