[BUG] Claude Code does not work with MCP servers that does not implement Dynamic Client Registration

Resolved 💬 22 comments Opened Jul 10, 2025 by dhawalkp Closed May 23, 2026
💡 Likely answer: A maintainer (localden, collaborator) responded on this thread — see the highlighted reply below.

Environment

  • Platform (select one):
  • [x] Anthropic API
  • [ ] AWS Bedrock
  • [ ] Google Vertex AI
  • [ ] Other: <!-- specify -->
  • Claude CLI version: 1.0.41
  • Operating System: macOS 14.3

Bug Description

Claude Code fails connecting to MCP server that does not have Dynamic Client Registration implemented. MCP server in this case is behaving as a resource server with a separate OAuth server serving as an Authorization server. As per the latest MCP Auth RFC, the MCP server acting as pure resource server should only implement and publish /.well-known/oauth-protected-resource and this file is not supposed to bear the client_id details. The Client_id and redirect_uri should be part of /.well-known/oauth-authorization-server which is the responsibility of Authorization server (and not MCP servers). The Claude Code should follow below protocol and ideally should succeed.

Steps to Reproduce

  1. Configure mcp.json with MCP servers acting only as a resource server. Have a seperate Auth server (i.e.Auth0)
  2. Connection fails

Expected Behavior

As per the latest MCP auth spec - https://modelcontextprotocol.io/specification/draft/basic/authorization#authorization-server-discovery

Any authorization servers that do not support Dynamic Client Registration need to provide alternative ways to obtain a client ID (and, if applicable, client credentials). For one of these authorization servers, MCP clients will have to either:

Hardcode a client ID (and, if applicable, client credentials) specifically for the MCP client to use when interacting with that authorization server, or
Present a UI to users that allows them to enter these details, after registering an OAuth client themselves (e.g., through a configuration interface hosted by the server).
Based on above, Claude Code should work with MCP servers that are purely acting as resource servers and not auth servers. The Auth server in my case is Auth0.

Actual Behavior

Based on above, Claude Code should work with MCP servers that are purely acting as resource servers and not auth servers. The Auth server in my case is Auth0.

Additional Context

Logs
[DEBUG] MCP server "custom-mcpserver": No token data found

[DEBUG] MCP server "custom-mcpserver": Using redirect port: 63105

[DEBUG] MCP server "custom-mcpserver": Generated new OAuth state

[DEBUG] MCP server "custom-mcpserver": Starting SDK auth

[DEBUG] MCP server "custom-mcpserver": Server URL: https:///mcp

[DEBUG] MCP server "custom-mcpserve": No client info found

[DEBUG] MCP server "custom-mcpserve": SDK auth error: Error: Dynamic client registration failed: HTTP 403

View original on GitHub ↗

22 Comments

lamberttraccard · 7 months ago

Did you find a workaround to this problem? I am facing the same thing.

mbuotidem · 7 months ago

Depending on what mcp server you're using, you may be able to use mcp-remote's static oauth client info feature as a workaround.

DigitalEntelechy · 6 months ago

Seems this is low pri... but it take away the easy path on some large MCP's like Github.

niebloomj · 6 months ago

Facing the same issue with the official slack plugin

kerim · 6 months ago

Getting this error with the github MCP

lukens · 6 months ago

Why do Anthropic even provide an official Slack plugin if it doesn't work because of this issue?

maxsloef-goodfire · 6 months ago
DigitalEntelechy · 6 months ago
Why do Anthropic even provide an official Slack plugin if it doesn't work because of this issue?

<img width="1756" height="437" alt="Image" src="https://github.com/user-attachments/assets/7d81376d-cc57-49c9-858d-989456b5355e" />

That's why.

lukens · 6 months ago

@DigitalEntelechy - not sure if that's so much a cause or a symptom

JoshuaRamirez · 6 months ago

Workaround: PAT-based authentication for GitHub MCP

For those hitting this issue with the GitHub MCP server specifically, here's a working workaround that bypasses the broken OAuth/dynamic client registration flow:

claude mcp add-json github '{"type":"http","url":"https://api.githubcopilot.com/mcp","headers":{"Authorization":"Bearer YOUR_GITHUB_PAT"}}'

Steps:

  1. Generate a GitHub PAT at https://github.com/settings/personal-access-tokens/new with repo scope
  2. Run the command above with your PAT substituted
  3. Restart Claude Code
  4. Verify with claude mcp list — should show github: ✓ Connected

This stores the config in ~/.claude.json under mcpServers.github.

The official github@claude-plugins-official plugin remains broken (OAuth flow), but this manual config provides identical functionality via direct PAT auth.

JoshuaRamirez · 6 months ago

Detailed Reproduction Steps (Windows, Claude Code 2.1.5+)

Environment

  • OS: Windows 11
  • Claude Code: 2.1.5+
  • Built-in plugin: github@claude-plugins-official (enabled by default)

Steps to Reproduce

  1. Fresh Claude Code install with github@claude-plugins-official enabled (default)
  2. Run /mcp command
  3. Observe: plugin:github:github: https://api.githubcopilot.com/mcp/ (HTTP) - ✗ Failed to connect
  4. Select "Authenticate" option
  5. Error: "Incompatible auth server: does not support dynamic client registration"

Root Cause Analysis

The built-in plugin attempts OAuth with https://api.githubcopilot.com/mcp/, but:

  • Claude Code's MCP client requires the server to support OAuth 2.0 Dynamic Client Registration (RFC 7591)
  • GitHub's MCP server does not implement dynamic client registration
  • VS Code handles this differently (supports the endpoint without requiring DCR)

Working Workaround

Bypass OAuth entirely with PAT-based authentication:

claude mcp add-json github '{"type":"http","url":"https://api.githubcopilot.com/mcp","headers":{"Authorization":"Bearer YOUR_GITHUB_PAT"}}' --scope user

This stores the config in ~/.claude.json under mcpServers.github and connects successfully.

Suggested Fix

The MCP client should:

  1. Not require dynamic client registration for HTTP MCP servers
  2. Fall back to PAT/Bearer token auth when DCR is unavailable
  3. Or detect servers that don't support DCR and prompt for manual token entry

Related PRs/Issues

  • github/github-mcp-server#1404 (same error on VS Code)
  • github/github-mcp-server#1649 (OAuth device flow - alternative auth)
  • #2831 (HTTP transport bypasses Authorization header)
  • Docs PR submitted: github/github-mcp-server#1833
kerim · 5 months ago
## Workaround: PAT-based authentication for GitHub MCP

Thanks @JoshuaRamirez

I've made a Claude Code Skill that automates this approach. Feedback welcome.

https://github.com/kerim/github-mcp-skill

CaptainCodeAU · 4 months ago

Workaround: GitHub Plugin Auth (macOS)

Problem

Install the GitHub plugin via /plugin, run /mcp, get:

Error: Incompatible auth server: does not support dynamic client registration

The plugin's .mcp.json reads GITHUB_PERSONAL_ACCESS_TOKEN from your environment. But the UI shows an "Authenticate" button that tries OAuth, which GitHub's endpoint doesn't support. Setting the env var is the actual fix.

Fix

1. Create a fine-grained PAT at [github.com/settings/tokens](https://github.com/settings/tokens?type=beta) with the scopes you need.

2. Store it in macOS Keychain:

security add-generic-password -a "$USER" -s "github-pat" -w "ghp_your_token_here"

3. Add this to your shell profile (~/.zshrc, ~/.bashrc, etc.):

export GITHUB_PERSONAL_ACCESS_TOKEN="$(security find-generic-password -a $USER -s github-pat -w 2>/dev/null)"

4. Restart your terminal, open Claude Code, run /mcp. It should connect. Ignore the "Authenticate" button.

Why Keychain

Most suggestions say to drop the token in ~/.zshrc, .env, settings.json, or .mcp.json. That's plaintext on disk. If you sync dotfiles or share your machine, that's not ideal. Keychain keeps the secret encrypted and the shell profile only contains the retrieval command, not the token.

Other platforms

This uses the macOS security CLI so it won't work on Linux or Windows. The underlying fix is the same though: get GITHUB_PERSONAL_ACCESS_TOKEN into your environment. Linux users could use secret-tool (GNOME Keyring), Windows users could pull from Credential Manager via PowerShell.

rayshan · 4 months ago

Official Slack plugin works out of the box now with this ticket closing https://github.com/anthropics/claude-plugins-official/pull/406

psmith39 · 4 months ago

Running into this with the snowflake hosted MCP as well

rajivpant · 3 months ago

VS Code MCP panel shows false "Needs Auth" error for Slack despite working connection (v2.1.81)

Slack MCP tools work correctly in both the CLI and VS Code. However, the VS Code MCP servers panel displays:

Incompatible auth server: does not support dynamic client registration

…and shows a "Needs Auth" badge for Slack, even though the tools execute successfully.

Inspecting macOS Keychain (Claude Code-credentials) explains why: the mcpOAuth entry for Slack is a stub (accessToken len=0, expiresAt: 0). The real auth is handled server-side — the CLI/extension authenticates to Anthropic via claudeAiOauth, and Anthropic's MCP proxy handles the Slack OAuth. The VS Code MCP panel appears to check auth status by attempting a direct OAuth handshake with Slack (which fails at DCR), rather than checking whether the proxy path actually works.

This is a UI bug — the status display is misleading and could cause users to think Slack isn't connected when it is.

Environment: Claude Code v2.1.81, macOS Sequoia

shivarammysore · 2 months ago

Adding a Cognito-specific repro from #38102 (closed as duplicate of this issue), per the
triage request — hopefully useful for keeping AWS Cognito explicitly in scope when the
fix lands.

Setup

  • IdP: AWS Cognito user pool, app client configured with code grant + PKCE
  • MCP server: HTTPS endpoint behind Cognito-issued JWT bearer
  • Client: Claude Code (current 2.x), .mcp.json declares clientId for the server
{
  "mcpServers": {
    "<server>": {
      "url": "https://<host>/mcp/",
      "oauth": {
        "clientId": "<cognito-app-client-id>",
        "scope": "openid profile"
      }
    }
  }
}

Observed behaviour

  1. Claude Code ignores the clientId field in .mcp.json.
  2. It then attempts dynamic client registration (RFC 7591) against the IdP's

registration_endpoint — but Cognito does not implement RFC 7591 and does
not advertise that endpoint in its OIDC discovery document
(/.well-known/openid-configuration). There is no Cognito API to register OAuth
clients dynamically; clients are pre-provisioned in the user pool.

  1. Dynamic registration request fails (404 / no endpoint), OAuth flow aborts, MCP

server is unreachable from Claude Code.

Expected behaviour

When oauth.clientId is present in .mcp.json, skip the dynamic-registration step
entirely and proceed straight to the auth-code-with-PKCE flow against the IdP's
authorization_endpoint using the configured clientId. RFC 7591 isn't required
when the operator has already provisioned a client and provided the ID in config.

Severity for Cognito users

This blocks Cognito-fronted MCP servers from working with Claude Code at all on
the OAuth path. AWS-hosted teams hit it the moment they try to put any auth in
front of an MCP server.

Workarounds that work today

  • Env-var injection of a pre-fetched token (get-token.sh style) — bypasses

the OAuth flow inside Claude Code entirely; works but loses Claude Code's
built-in token refresh.

relay — handles OAuth itself with --client-id (skips dynamic registration,
does auth-code + PKCE), Claude Code talks stdio to the relay. Untested by me
but fits the gap.

Happy to share more env details if useful.

shivarammysore · 2 months ago

Production repro: AWS Cognito as MCP OAuth provider — clientId in .mcp.json ignored, fall-through to DCR returns 4xx

Adding our scenario per the triage request carried over from #38102.

Setup

  • Self-hosted MCP server at https://example.com/mcp/ (HTTP transport).
  • OAuth provider: AWS Cognito user pool. Cognito does not implement RFC 7591 (Dynamic Client Registration) — there is no registration_endpoint in the metadata response, and the DCR call returns 4xx.

.mcp.json with clientId explicitly set:

{
  "mcpServers": {
    "mymcp": {
      "url": "https://example.com/mcp/",
      "type": "http",
      "auth": {
        "type": "oauth",
        "clientId": "<cognito-app-client-id>",
        "scope": "openid profile"
      }
    }
  }
}

Observed

  1. Claude Code fetches /.well-known/oauth-authorization-server from the MCP server.
  2. Metadata is RFC 8414-compliant but has no registration_endpoint (Cognito does not issue one).
  3. Claude Code attempts DCR anyway → 4xx → flow aborts before any authorization-code call.
  4. The clientId configured in .mcp.json is never used.

Expected
When clientId is set in .mcp.json, skip the DCR attempt entirely and proceed straight to authorization code + PKCE with the configured client. (This is the feature flavor tracked in #26675; from a bug perspective, ignoring the configured value is the issue here.)

Workarounds in production today

  • get-token.sh env-var injection — operational but manual.
  • mcp-stdio — Python stdio-to-HTTP relay that honors --client-id directly (auth code + PKCE, skips DCR). Standby fallback.

Logs / HTTP traces available if useful.

dustin-flow · 2 months ago

Adding Cowork-side observations per the consolidation note on #38102 — full analysis at anthropics/claude-plugins-official#283 (comment).

Same DCR-only failure also surfaces in Cowork (Claude desktop, knowledge-work-plugins marketplace) against the bundled engineering plugin's GitHub MCP. Key wrinkle vs. the Claude Code reports already here: the plugin's .mcp.json declares only the server URL, with no clientId field at all — so it's not even the "DCR despite clientId" case from #38102; the SDK has nothing to fall back to and goes straight to DCR.

Things I confirmed on the affected machine in case they help narrow the failure mode:

  • Cowork's "Connect" button completes claude.ai-side OAuth successfully and reports the connector as authenticated — but no local credential is ever written. Post-auth Keychain shows gh:github.com (gh CLI) and Claude Safe Storage / Claude Code-credentials*, but nothing for the Cowork-side GitHub MCP. The OAuth state lives entirely on the claude.ai backend with no plumbing to the local MCP subprocess, which keeps serving authenticate / complete_authentication stub tools to every new session.
  • mcp-needs-auth-cache.json does not contain a plugin:engineering:github entry — the stubs aren't driven by a "needs auth" flag; they're created at server-init time when the DCR probe fails. Cache deletion is not a workaround.
  • Disconnect/Connect, plugin toggle, full Cmd-Q + relaunch, Keychain clear of Claude Code-credentials* — all leave the stub state unchanged.
  • No escape hatch from Cowork's UI. The Claude Code claude mcp add --header "Authorization: Bearer ..." workaround isn't reachable; the Connectors panel has no custom-header surface and the plugin's .mcp.json lives at an app-managed path that may be overwritten on update.

If the fix here is going to be "support pre-registered client credentials" (per #26675), please plumb a config path through the plugin marketplace surface too — otherwise Cowork users will be stuck even after Claude Code is unblocked. Alternatively, hosting a Cowork-side proxy for GitHub like *.mcp.claude.com does for Google would unblock both clients at once.

BenArunski · 1 month ago

This is currently happening to me in claude code, trying to access GitHub remote MCP on the command-line on Windows->WSL->Ubuntu

Workaround

  1. generate a github personal access token (PAT) at github.com/settings/tokens:
  • Token name: anything descriptive
  • Expiration: your preference
  • Repository access: All repositories (or select specific ones)
  • Contents: Read
  • Issues: Read and write
  • Pull requests: Read and write
  • Metadata: Read (auto-selected)
  • Actions: Read
  1. store the PAT in your favorite password manager. I used pass, and called it github/pat. The retrieval command for me happens to be pass show github/pat 2>/dev/null
  2. Put this wherever you would normally put the mcp config (.mcp.json, .claude.json, etc), but replace "YOUR COMMAND" with whatever your password retrieval command is.
    "GitHub": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp",
      "headersHelper": "bash -c 'printf \"{\\\"Authorization\\\": \\\"Bearer %s\\\"}\" \"$(YOUR COMMAND)\"'"
    }
localden collaborator · 1 month ago

Thanks for the report. As of 2.1.30 you can pass an explicit client ID when adding an MCP server (--client-id), which covers servers that do not support dynamic client registration. Please update and retry. If you still see the connection stall after providing a client ID, please open a new issue.

github-actions[bot] · 3 days ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.