Remote MCP OAuth: prompt=consent hardcoded on every authorize request breaks Entra tenants with user-consent disabled
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
- Set up a .NET MCP server with Entra JWT Bearer auth +
ModelContextProtocol.AspNetCoreMCP authentication scheme (RFC 9728 protected resource metadata) - Create a public client Entra app registration with PKCE,
access_as_userscope, admin consent granted tenant-wide - 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)
- 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
/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:
- 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.
- Manually edit the auth URL — strip
&prompt=consentfrom the URL Claude opens in the browser, then paste the modified URL. Per-sign-in manual step; not scalable. - 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=consentat 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=consentonly on the first sign-in for a given server (when no cached tokens exist), not on reconnections or token refreshes. - C) Make
prompt=consentconfigurable — e.g. a--no-prompt-consentflag onclaude 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
- Microsoft docs on
prompt=consent: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#request-an-authorization-code
Showing cached comments. Read the full discussion on GitHub ↗
8 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
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 theprompt=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.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, andscope, nothing else. The--client-idskips dynamic client registration (Entra doesn't advertise a registration endpoint), and--oauth-scopepasses theaccess_as_user+offline_accessscopes Entra expects.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.
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.
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.
I am also blocked on this. Our current workaround is routing the requests through a proxy, which manually strips the
prompt=consent.We are also blocked by this, our users can't use the MCP right now
@localden ,
would you be able to please prioritize this auth issue?
Thanks!