For remote MCP Connect in Cursor, the OAuth redirect URI must match your authorization server (AS) allowlist character-for-character—commonly a cursor://…/oauth/callback form (plus any port/path variants Cursor documents for your build). One trailing slash, scheme drift, or env/prod mismatch fails the bounce after browser login and looks like “auth almost worked.” Connect opening login, the browser succeeding, then the bounce failing is usually an allowlist mismatch: scheme, host, path, or trailing slash. Cursor and Claude need different documented callbacks—register each client separately. Prove the shared 401 + WWW-Authenticate + resource_metadata challenge before chasing redirect trivia. This page is redirect registration only—not the full OAuth recipe.
Symptom card
| Symptom | Likely redirect cause | What to check first |
|---|---|---|
| Connect opens login → browser succeeds → bounce fails | AS allowlist ≠ Cursor’s documented callback | Exact string: scheme, host/path, trailing slash |
| “Needs authentication” loops after a successful login | Callback registered for another env (staging vs prod AS) | Which AS the challenge / PRM pointed at |
| Cursor Connect fails; Claude works (or reverse) | Different clients need different callbacks | Register each client’s documented URI separately |
| Static `CLIENT_ID` path still fails post-login | Static clients skip DCR—they don’t skip redirects | See mcp.json CLIENT_ID when DCR is missing |
Full happy path (401 + `WWW-Authenticate` + `resource_metadata` → Auth Code + PKCE → tools): Build a remote MCP server with OAuth that Cursor and Claude can both Connect to. Prove the shared challenge before you chase redirect trivia.
Register the documented Cursor callback
- Copy the redirect URI from Cursor’s MCP OAuth docs for the build you ship—don’t invent a `https://` callback if Cursor expects `cursor://…/oauth/callback`.
- Paste that exact string into the AS client allowlist (admin UI or IaC)—no “helpful” normalization.
- If you use Dynamic Client Registration, confirm the registered client still carries that same redirect; if you use a static client, put the redirect on that static client record.
- Re-Connect from Cursor and watch the bounce land on the same string the AS logged.
Copy/paste discipline beats memory. A one-character mismatch is enough.
Common mismatches
- Trailing slash — `/oauth/callback` vs `/oauth/callback/`
- Scheme — `cursor://` vs `https://` (or a custom scheme Cursor doesn’t use)
- Path / port variants — documented port or path differs across Cursor builds; follow *your* version’s docs
- Env vs prod AS — redirect registered on staging; Connect hits prod (or reverse)
- Claude’s callback reused for Cursor — each client gets its own documented URI; Cursor’s string does not satisfy Claude’s callback-port / path
Confirm with Inspector, then the AS log
Use MCP Inspector to confirm the remote challenge is clean first. Then, on a failing Connect attempt, check the AS authorize / redirect log for the exact `redirect_uri` the client sent—compare byte-for-byte to the allowlist entry. If they differ, fix the AS registration (or the client config), not the MCP tool handlers.
Static `CLIENT_ID` when DCR is missing: mcp.json CLIENT_ID when DCR is missing. You still register the Cursor callback exactly.
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—including exact dual-client redirect registration when DCR isn’t available. Soft path: /free for the starter desk; Cheat Sheet for the pocket checklist mindset; kit when you want the auth-ready layout instead of stitching vendor posts.
Soft next step
Copy Cursor’s documented callback into the AS once, prove Connect, then register Claude’s callback separately. Soft ladder: /free for the starter desk, Cheat Sheet for the skim checklist, or the MCP Starter Kit ($27) for the dual-client recipe. Full sequence: OAuth pillar; static client: mcp.json CLIENT_ID; debug loop: MCP Inspector.