[BUG] DPoP is not used for a pre-registered MCP OAuth client

Status Open
Reported on v2.1.204
Maintainer reply None cached
Activity 0 comments · opened Sep 23, 2026

Preflight Checklist

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

What's Wrong?

When connecting Claude Code to a remote MCP server using OAuth with a pre-registered client, the Authorization Server requires DPoP-bound access tokens according to RFC 9449.
https://www.rfc-editor.org/info/rfc9449/
https://github.com/modelcontextprotocol/typescript-sdk/blob/60321700871029401a2e3bed8fdf4f02c9ec3331/.changeset/dpop-client-tokens.md?plain=1#L10

The Authorization Server advertises DPoP support in its metadata:

{
  "dpop_signing_alg_values_supported": ["ES256"]
}

The pre-registered OAuth client is configured on the Authorization Server to require DPoP-bound access tokens (dpop_bound_access_tokens = true).

However, Claude Code performs the token request without a DPoP proof.

Actual behavior

For a pre-registered MCP OAuth client, I cannot find a way to enable DPoP.

The Authorization Server advertises:

{
  "dpop_signing_alg_values_supported": ["ES256"]
}

but the initial /token request from Claude Code does not contain:

DPoP: <proof JWT>

As a result, an Authorization Server that enforces DPoP for this client_id must reject the token request.

MCP configuration

The MCP server uses a pre-registered OAuth client, approximately:

{
  "type": "http",
  "url": "https://mcp.example.com/mcp",
  "oauth": {
    "clientId": "<pre-registered-client-id>",
    "clientSecret": "<client-secret>"
  }
}

There does not appear to be an option such as:

{
  "oauth": {
    "clientId": "...",
    "clientSecret": "...",
    "dpop": true
  }
}

What Should Happen?

Claude Code should provide a way to enable DPoP for a pre-registered MCP OAuth client.

When DPoP is enabled, the authorization-code token request should contain a DPoP proof:

POST /token
DPoP: <proof JWT>
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=...&
client_id=...&
code_verifier=...

The resulting DPoP-bound access token should then be used for MCP requests as:

Authorization: DPoP <access_token>
DPoP: <proof JWT>

Error Messages/Logs

Steps to Reproduce

  1. Configure a remote HTTP MCP server requiring OAuth.
  2. Configure Claude Code to use a pre-registered client_id.
  3. Configure the Authorization Server to require DPoP-bound access tokens for that client.
  4. Publish DPoP support in the Authorization Server metadata:
{
  "dpop_signing_alg_values_supported": ["ES256"]
}
  1. Start the OAuth flow from Claude Code.
  2. Observe the request to the token endpoint.

The request does not contain a DPoP header, so the Authorization Server rejects it because the pre-registered client requires DPoP.

Claude Model

Not sure / Multiple models

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.204

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

The MCP TypeScript SDK has DPoP support through OAuthClientProvider.dpop() / DpopSession.

It is unclear whether Claude Code currently wires this capability into its MCP OAuth provider, particularly for pre-registered clients.

If DPoP is intentionally opt-in rather than automatically enabled based on dpop_signing_alg_values_supported, it would be useful to expose a Claude Code MCP configuration option for enabling it, for example:

{
  "oauth": {
    "clientId": "...",
    "clientSecret": "...",
    "dpop": true
  }
}

This would allow Claude Code to interoperate with Authorization Servers that require sender-constrained access tokens using RFC 9449.

View original on GitHub ↗