Skip to content

fix(mcp-oauth): one-click connect — friendly success page + private-use URI schemes - #16

Merged
criptogus merged 1 commit into
mainfrom
claude/fix-mcp-oauth-callback-brZDc
May 21, 2026
Merged

criptogus merged 1 commit into
mainfrom
claude/fix-mcp-oauth-callback-brZDc

Conversation

@criptogus

Copy link
Copy Markdown
Owner

Problem

Users connecting MCP clients (Claude, Cursor, Codex, Lovable, OpenClaw, Hermes, …) were dropped on the browser's "site can't be reached" page after consent. Two root causes:

  1. After Authorize, we navigated the tab straight to http://localhost:XXXXX/callback?code=…. If the client's loopback listener had already closed (or wasn't up), the browser showed a broken URL with no recovery path — common-user dead end.
  2. Native clients that register a deep-link redirect (cursor://, vscode://, claude://, codex://, lovable://, hermes://, openclaw://) were rejected at DCR because both the HTTP handler and the SQL validator only accepted https:// or loopback http://.

Fix

  • New /oauth/success page confirms the connection visually ("Connected ✅ to {client}"), then:
    • For loopback redirects: fires a fetch(no-cors) to deliver the code to the CLI/desktop listener without navigating the tab (so a closed listener no longer breaks the page).
    • For private-use URI schemes: triggers the deep link to pop the user back into their client.
    • For https:// callbacks: just redirects.
    • Always shows a copy-pasteable auth code as a manual fallback, plus a "retry" link.
  • Auth code is handed off via sessionStorage so it never lands in URL bar / history of the consent tab.
  • Client registration (/api/public/oauth/register and the mcp_oauth_register_client RPC) now accepts private-use URI scheme redirects per RFC 8252 §7, while still rejecting non-loopback plain http://.
  • Docs at /docs/mcp updated to describe the new flow.

Files

  • src/routes/oauth.success.tsx (new)
  • src/routes/oauth.authorize.tsx — hands off via sessionStorage, navigates to /oauth/success
  • src/lib/oauth/mcp-oauth.functions.ts — also returns raw code for the fallback display
  • src/routes/api/public/oauth/register.ts — accept private-use URI schemes
  • supabase/migrations/20260521000000_mcp_oauth_allow_private_uri_schemes.sql — matching server-side change
  • src/routes/docs.mcp.tsx — describe the new success behavior

Test plan

  • Apply migration to staging.
  • Run npx -y super-agent connect --client claude-code and confirm the success page appears and the CLI completes.
  • Authorize from Cursor (deep-link scheme): browser shows success page, Cursor pops to foreground.
  • Manually close the CLI's loopback listener before clicking Authorize — verify the success page appears with the auth code visible to paste.
  • Authorize from Claude Desktop (loopback): confirm token shows up under /account/connections.
  • DCR with redirect_uris: ["http://evil.example/cb"] → still rejected.
  • DCR with redirect_uris: ["cursor://callback"] → accepted.

https://claude.ai/code/session_019gMoupKKTVydpNwiiACQRd


Generated by Claude Code

MCP clients (Claude, Cursor, Codex, Lovable, OpenClaw, Hermes, …)
were dropping users on the browser's "site can't be reached" screen
when the loopback listener had closed or the client used a deep-link
scheme that DCR rejected.

- New /oauth/success page confirms the connection visually, fires a
  no-cors fetch to the loopback listener (so the CLI still receives
  the code), triggers private-use URI schemes for desktop clients,
  and shows a copy-pasteable auth code as a manual fallback.
- Auth code is handed off via sessionStorage so it never lands in the
  URL bar or browser history.
- Client registration (HTTP + SQL) now accepts private-use URI scheme
  redirects per RFC 8252 §7, not just https / loopback http.
- Docs updated to describe the new flow.

https://claude.ai/code/session_019gMoupKKTVydpNwiiACQRd
@criptogus
criptogus marked this pull request as ready for review May 21, 2026 16:12
@criptogus
criptogus merged commit 5de64ef into main May 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants