Remote MCP OAuth: prompt=consent hardcoded on every authorize request breaks Entra tenants with user-consent disabled

Status Fixed / completed
Reported on v2.1.109
Maintainer reply None cached
Activity 9 comments · opened Apr 17, 2026 · closed Jun 2, 2026

Summary

Claude Code 2.1.109's remote HTTP MCP transport hardcodes prompt=consent on every OAuth authorize request. This forces Microsoft Entra ID to show the consent UI on every sign-in, regardless of whether admin consent has already been granted tenant-wide.

In Entra tenants where user consent is disabled (a common enterprise policy), non-admin users are routed into the admin consent request workflow ("This app requires your admin's approval" + "Enter justification") on every connection attempt — even after an admin has explicitly granted tenant-wide consent on the app registration. There is no "Accept" button; the user is blocked.

Reproduction

  1. Set up a .NET MCP server with Entra JWT Bearer auth + ModelContextProtocol.AspNetCore MCP authentication scheme (RFC 9728 protected resource metadata)
  2. Create a public client Entra app registration with PKCE, access_as_user scope, admin consent granted tenant-wide
  3. Ensure the Entra tenant has Enterprise applications → Consent and permissions → User consent settings set to "Do not allow user consent" (common in enterprise/MSP tenants)
  4. Add the MCP server to Claude Code:

``bash
claude mcp add --transport http --client-id <app-reg-id> --callback-port 6274 my-server https://my-server.example.com/mcp
``

  1. /mcp → Authenticate

Expected: Since admin consent is already granted, Entra should skip the consent prompt and issue tokens directly.

Actual: The authorize URL contains &prompt=consent, which forces Entra to show the consent UI. With user consent disabled at the tenant level, Entra shows the admin-approval-required form instead of an Accept button. Non-admin users are blocked indefinitely.

The authorize URL Claude generates

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
  ?response_type=code
  &client_id=<app-reg-id>
  &code_challenge=<pkce>
  &code_challenge_method=S256
  &redirect_uri=http://localhost:6274/callback
  &scope=https://my-server.example.com/mcp/access_as_user+offline_access
  &prompt=consent          ← this is the problem
  &resource=https://my-server.example.com/mcp

Impact

Any Entra tenant with user consent disabled (standard enterprise security posture) cannot use Claude Code's remote MCP transport without one of these workarounds:

  1. Change the tenant's consent policy — flip to "Allow user consent for apps". Works but requires a Global Admin to weaken the tenant-wide policy for all apps, not just this one.
  2. Manually edit the auth URL — strip &prompt=consent from the URL Claude opens in the browser, then paste the modified URL. Per-sign-in manual step; not scalable.
  3. Sign in as a Global Admin — admins see a "Consent on behalf of organization" checkbox. Works for the admin themselves but not for regular users.

Suggested fix

Either:

  • A) Don't send prompt=consent at all — let Entra decide whether to show the prompt based on the existing consent state. If consent hasn't been granted yet, Entra will prompt automatically on first sign-in.
  • B) Send prompt=consent only on the first sign-in for a given server (when no cached tokens exist), not on reconnections or token refreshes.
  • C) Make prompt=consent configurable — e.g. a --no-prompt-consent flag on claude mcp add, or an MCP server config option.

Option A is the simplest and matches the behavior of other OAuth clients (Azure CLI, VS Code, etc.) that work fine with Entra tenants that have user consent disabled.

Environment

  • Claude Code: v2.1.109
  • OS: Ubuntu 22.04 (WSL2)
  • Identity provider: Microsoft Entra ID (Azure AD), single-tenant
  • MCP SDK: ModelContextProtocol.AspNetCore 1.2.0
  • Server: ASP.NET Core .NET 10

References

View original on GitHub ↗

8 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/31089
  2. https://github.com/anthropics/claude-code/issues/41878
  3. https://github.com/anthropics/claude-code/issues/47374

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

shigechika · 4 months ago

For anyone blocked by this right now: if your workflow can reach the HTTP MCP server over stdio instead (Claude Desktop, claude mcp add --transport stdio, VS Code's stdio MCP, etc.), mcp-stdio is a local gateway that handles the OAuth flow itself and does not set the prompt= parameter on the authorize URL. Entra's consent state then governs whether the UI is shown, and tenants with admin consent already granted sign in without interaction — which is option A from the suggested fix.

{
  "mcpServers": {
    "my-server": {
      "command": "mcp-stdio",
      "args": [
        "--oauth",
        "--client-id", "<your-entra-app-reg-id>",
        "--oauth-scope", "https://my-server.example.com/mcp/access_as_user offline_access",
        "https://my-server.example.com/mcp"
      ]
    }
  }
}

Verified on the released 0.5.1 — the authorize URL only carries client_id, response_type, redirect_uri, state, code_challenge, code_challenge_method, resource, and scope, nothing else. The --client-id skips dynamic client registration (Entra doesn't advertise a registration endpoint), and --oauth-scope passes the access_as_user + offline_access scopes Entra expects.

KYOSIT · 4 months ago

For anyone else with this issue, my current work around is to just get the end user to manually edit the auth url link and remove the prompt query param. This allows them to successfully authenticate and connect to the MCP server.

gattimassimo · 4 months ago

The workarounds are involved and either require manipulating the request on the fly, or going via a proxy which adds one layer of indirection and more components for something which should be handled natively by Claude Code auth layer.

I'm also blocked on this issue.

ymathieupax8 · 4 months ago

I also have this issue.

It seems to be imposed by the mcp sdk https://github.com/modelcontextprotocol/typescript-sdk/blob/main/packages/client/src/client/auth.ts#L1419-L1423 but in that case how does Claude Partner Connectors like Office365 or Slack connectors handle this?

We are using a Chrome browser policies to automate the URL rewrite in the mean time.

fejbl2 · 3 months ago

I am also blocked on this. Our current workaround is routing the requests through a proxy, which manually strips the prompt=consent .

Roman-Ka · 3 months ago

We are also blocked by this, our users can't use the MCP right now

gattimassimo · 3 months ago

@localden ,
would you be able to please prioritize this auth issue?

Thanks!

Showing cached comments. Read the full discussion on GitHub ↗