claude-code - 💡(How to fix) Fix MCP OAuth: portless redirect_uris in client-metadata document fail against Notion MCP (RFC 8252 loopback port matching not honored) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#52896Fetched 2026-04-25 06:17:59
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
0
Author
Timeline (top)
labeled ×5closed ×1commented ×1

Authenticating the hosted Notion MCP server (https://mcp.notion.com/mcp) in Claude Code fails at Notion's consent step with "Invalid redirect_uri for OAuth client". The failure is structural: Claude Code's OAuth client-metadata document declares portless loopback redirect URIs, but the authorize request sends a runtime ephemeral port. Notion's OAuth validator does strict string matching and rejects the mismatch.

Per RFC 8252 §7.3, OAuth servers MUST ignore the port component when matching loopback redirect URIs (localhost, 127.0.0.1, [::1]) precisely to support ephemeral ports for native public clients. Notion doesn't appear to honor this, so the current Claude Code metadata shape is effectively incompatible with Notion's MCP OAuth.

Error Message

Browser lands on a Notion error page: "Invalid redirect_uri for OAuth client". Attempting the manual fallback — pasting that URL into mcp__notion__complete_authentication — fails with "OAuth state mismatch - possible CSRF attack", because the URL is Notion's error page, not a /callback?... URL.

  • Fresh mcp__notion__authenticate call produced a new ephemeral port (65175 in this run) → same "Invalid redirect_uri" error.
  1. Detect servers that don't honor RFC 8252 loopback port matching and either DCR there or degrade to a user-visible error explaining the interop gap, rather than a silent failure at the consent step.

Root Cause

The client-metadata document at https://claude.ai/oauth/claude-code-client-metadata declares:

{
  "client_id": "https://claude.ai/oauth/claude-code-client-metadata",
  "client_name": "Claude Code",
  "client_uri": "https://claude.ai",
  "redirect_uris": [
    "http://localhost/callback",
    "http://127.0.0.1/callback"
  ],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

The actual authorize request sends:

redirect_uri=http://localhost:<ephemeral-port>/callback

Notion's OAuth server rejects because the strings differ. RFC 8252 §7.3 requires port-agnostic matching for loopback redirect URIs, but Notion isn't doing it, and Claude Code isn't compensating.

Fix Action

Fix / Workaround

Workaround for other users

Code Example

{
  "client_id": "https://claude.ai/oauth/claude-code-client-metadata",
  "client_name": "Claude Code",
  "client_uri": "https://claude.ai",
  "redirect_uris": [
    "http://localhost/callback",
    "http://127.0.0.1/callback"
  ],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

---

redirect_uri=http://localhost:<ephemeral-port>/callback
RAW_BUFFERClick to expand / collapse

Summary

Authenticating the hosted Notion MCP server (https://mcp.notion.com/mcp) in Claude Code fails at Notion's consent step with "Invalid redirect_uri for OAuth client". The failure is structural: Claude Code's OAuth client-metadata document declares portless loopback redirect URIs, but the authorize request sends a runtime ephemeral port. Notion's OAuth validator does strict string matching and rejects the mismatch.

Per RFC 8252 §7.3, OAuth servers MUST ignore the port component when matching loopback redirect URIs (localhost, 127.0.0.1, [::1]) precisely to support ephemeral ports for native public clients. Notion doesn't appear to honor this, so the current Claude Code metadata shape is effectively incompatible with Notion's MCP OAuth.

Environment

  • Claude Code: 2.1.119
  • OS: macOS (Darwin 25.4.0)
  • Local session (not remote/SSH)
  • Target MCP: https://mcp.notion.com/mcp

Reproduction

  1. Install Notion MCP in Claude Code (pointing at https://mcp.notion.com/mcp).
  2. Invoke mcp__notion__authenticate.
  3. Open the returned authorize URL, sign in, approve workspace access.
  4. Click "Authenticate" on Notion's consent page.

Expected

Browser redirects to http://localhost:<port>/callback?code=…&state=…; Claude Code's in-process listener completes the exchange; Notion tools become available.

Actual

Browser lands on a Notion error page: "Invalid redirect_uri for OAuth client".

Attempting the manual fallback — pasting that URL into mcp__notion__complete_authentication — fails with "OAuth state mismatch - possible CSRF attack", because the URL is Notion's error page, not a /callback?... URL.

Root cause

The client-metadata document at https://claude.ai/oauth/claude-code-client-metadata declares:

{
  "client_id": "https://claude.ai/oauth/claude-code-client-metadata",
  "client_name": "Claude Code",
  "client_uri": "https://claude.ai",
  "redirect_uris": [
    "http://localhost/callback",
    "http://127.0.0.1/callback"
  ],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

The actual authorize request sends:

redirect_uri=http://localhost:<ephemeral-port>/callback

Notion's OAuth server rejects because the strings differ. RFC 8252 §7.3 requires port-agnostic matching for loopback redirect URIs, but Notion isn't doing it, and Claude Code isn't compensating.

Evidence this isn't client-side state

Reproduced on a fully clean slate:

  • All prior localhost Custom entries revoked on the Notion side (Settings → MCP connections).
  • All Claude Code integrations removed workspace-wide.
  • Keychain Access searched for notion / claude code — no matching MCP entries.
  • ~/.claude/mcp-needs-auth-cache.json cleared.
  • Fresh mcp__notion__authenticate call produced a new ephemeral port (65175 in this run) → same "Invalid redirect_uri" error.

Suggested fixes (Claude Code side)

Options, roughly by cost:

  1. Fall back to classic Dynamic Client Registration (RFC 7591) when the target server advertises a registration_endpoint in its OAuth metadata. DCR lets Claude Code register the concrete http://localhost:<port>/callback each flow, sidestepping strict-matching servers. Notion's MCP OAuth server does appear to support DCR (it accepted it for the client that produced three stale localhost:<port> entries previously seen in this workspace's history).
  2. Detect servers that don't honor RFC 8252 loopback port matching and either DCR there or degrade to a user-visible error explaining the interop gap, rather than a silent failure at the consent step.
  3. Coordinate with Notion to implement RFC 8252 §7.3 loopback matching in their MCP OAuth validator.

Related

  • makenotion/notion-mcp-server#268 (Notion MCP OAuth state issues)
  • anthropics/claude-code#10439 (MCP OAuth redirect_uri issues for remote MCP)
  • anthropics/claude-code#3273 (Claude Code requires DCR support from MCP servers)

Workaround for other users

Use the self-hosted @notionhq/notion-mcp-server stdio MCP with a Notion internal integration token — bypasses OAuth entirely.

extent analysis

TL;DR

The most likely fix is to implement Dynamic Client Registration (DCR) as a fallback when the target server does not honor RFC 8252 loopback port matching.

Guidance

  • Check if the target OAuth server supports Dynamic Client Registration (DCR) by looking for a registration_endpoint in its OAuth metadata.
  • If DCR is supported, implement it as a fallback to register the concrete http://localhost:<port>/callback for each flow, sidestepping strict-matching servers.
  • Consider detecting servers that don't honor RFC 8252 loopback port matching and degrading to a user-visible error explaining the interop gap.
  • Coordinate with the Notion team to implement RFC 8252 §7.3 loopback matching in their MCP OAuth validator as a long-term solution.

Example

No code example is provided as it would require more specific implementation details.

Notes

The provided information suggests that Notion's MCP OAuth server does not honor RFC 8252 §7.3 loopback port matching, causing the "Invalid redirect_uri for OAuth client" error. Implementing DCR as a fallback seems to be a viable workaround.

Recommendation

Apply the workaround by implementing Dynamic Client Registration (DCR) as a fallback when the target server does not honor RFC 8252 loopback port matching, as it allows for more flexibility and compatibility with different OAuth servers.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING