Skip to content

[BUG] claude mcp add --client-id writes clientId (camelCase) but SDK reads client_id (snake_case), causing pre-configured OAuth to fail #68853

Description

@whoisthatpanda

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Bug Report: claude mcp add --client-id writes clientId (camelCase) but SDK reads client_id (snake_case), causing pre-configured OAuth to fail

Summary

When adding an MCP server with pre-configured OAuth credentials using --client-id, Claude Code writes the client ID to ~/.claude.json as clientId (camelCase). However, the OAuth SDK reads client_id (snake_case). This mismatch causes the auth flow to ignore the provided credentials entirely and fall back to Dynamic Client Registration (DCR), which fails for servers that use pre-registered OAuth clients and do not support DCR.

Steps to Reproduce

  1. Add an MCP server with pre-configured OAuth credentials:
claude mcp add --transport http \
  --client-id YOUR_CLIENT_ID --client-secret --callback-port 3000 \
  myserver https://mcp-server.example.com/mcp
  1. Verify the config was written:
grep -A8 "myserver" ~/.claude.json
  1. Observe that the config contains "clientId" (camelCase), not "client_id" (snake_case)
  2. Launch Claude Code and run /mcp
  3. Observe the error: SDK auth failed: Incompatible auth server: does not support dynamic client registration

Expected Behavior

  • claude mcp add --client-id should write client_id (snake_case) to ~/.claude.json
  • The OAuth flow should use the provided client ID and secret instead of attempting DCR
  • The browser auth flow should complete successfully for servers that use pre-registered OAuth clients

Actual Behavior

  • claude mcp add --client-id writes clientId (camelCase) to ~/.claude.json
  • The OAuth SDK does not recognize clientId and treats the server as having no pre-configured credentials
  • Claude Code falls back to DCR, which fails for servers that don't support it
  • Manually fixing the config via sed does not resolve the issue because Claude Code re-reads config at startup before the auth flow begins and still does not pick up the credentials

Config Written (Incorrect)

"myserver": {
  "type": "http",
  "url": "https://mcp-server.example.com/mcp",
  "oauth": {
    "clientId": "YOUR_CLIENT_ID",
    "callbackPort": 3000
  }
}

Config Expected (Correct)

"myserver": {
  "type": "http",
  "url": "https://mcp-server.example.com/mcp",
  "oauth": {
    "client_id": "YOUR_CLIENT_ID",
    "callbackPort": 3000
  }
}

Environment

Additional Context

claude mcp get <name> correctly reports client_id configured, client_secret configured after adding the server, confirming the credentials were accepted by the CLI. However the runtime OAuth flow does not use them. This suggests the CLI and the OAuth SDK are using different field name conventions when reading the config.

What Should Happen?

Expected Behavior

  • claude mcp add --client-id should write client_id (snake_case) to ~/.claude.json
  • The OAuth flow should use the provided client ID and secret instead of attempting DCR
  • The browser auth flow should complete successfully for servers that use pre-registered OAuth clients

Error Messages/Logs

## Actual Behavior

- `claude mcp add --client-id` writes `clientId` (camelCase) to `~/.claude.json`
- The OAuth SDK does not recognize `clientId` and treats the server as having no pre-configured credentials
- Claude Code falls back to DCR, which fails for servers that don't support it
- Manually fixing the config via `sed` does not resolve the issue because Claude Code re-reads config at startup before the auth flow begins and still does not pick up the credentials

Steps to Reproduce

Steps to Reproduce

  1. Add an MCP server with pre-configured OAuth credentials:
claude mcp add --transport http \
  --client-id YOUR_CLIENT_ID --client-secret --callback-port 3000 \
  myserver https://mcp-server.example.com/mcp
  1. Verify the config was written:
grep -A8 "myserver" ~/.claude.json
  1. Observe that the config contains "clientId" (camelCase), not "client_id" (snake_case)
  2. Launch Claude Code and run /mcp
  3. Observe the error: SDK auth failed: Incompatible auth server: does not support dynamic client registration

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.178

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:autharea:mcpbugSomething isn't workingduplicateThis issue or pull request already existshas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions