prompt=consent hardcoded on every MCP OAuth authorize request breaks Entra tenants with user consent disabled — affects Claude Code, claude.ai web connector and desktop alike (#49722 was closed without a fix)
Summary
#49722 was closed as completed on 2026-06-02, but the behaviour is unchanged. It affects every Claude MCP client — Claude Code CLI, the claude.ai web connector and the desktop app alike — because it lives in the shared MCP TypeScript SDK auth layer, not in any single client.
Every MCP OAuth authorize request that includes offline_access carries a hardcoded prompt=consent. In Microsoft Entra ID tenants where user consent is disabled (Microsoft's recommended enterprise default), every non-admin user is routed into the "admin approval required" workflow (AADSTS90095) on every connect, even though tenant-wide admin consent for the app is already granted. Approving the resulting admin consent requests changes nothing; the next connect triggers the next request. Admin users get the full consent dialog on every connect.
Reproduced on 2026-09-16 with the claude.ai web connector (Settings → Connectors → Connect). The authorize URL matches the pattern reported for Claude Code in #49722 and #64013 exactly.
Setup (generic — any OIDC authorization server in front of Entra will do)
- Client: claude.ai web connector; identical behaviour reported for Claude Code CLI in #49722 / #64013
- MCP server: FastMCP
RemoteAuthProvider— publishes protected-resource metadata only, has no authorize endpoint and cannot influence the parameter - Authorization server: OIDC-compliant IdP federating to Microsoft Entra ID (passes
promptthrough to the upstream IdP, as the spec allows) - Entra: user consent disabled; admin consent for the app granted tenant-wide
Reproduction (browser DevTools → Console → "Navigated to")
- Claude → authorization server:
https://<authorization-server>/oauth2/authorize
?response_type=code
&client_id=<client-id>
&redirect_uri=https%3A%2F%2Fclaude.ai%2Fapi%2Fmcp%2Fauth_callback
&code_challenge=…&code_challenge_method=S256&state=…
&scope=openid+email+profile+offline_access
&resource=https%3A%2F%2F<mcp-server>%2Fmcp
&prompt=consent
- Authorization server → upstream Entra (parameter forwarded 1:1):
https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorize
?client_id=<entra-app-id>&prompt=consent&scope=openid+profile+email&…
- Non-admin user → AADSTS90095 + justification form. Admin user → consent dialog. Every time.
The server's protected-resource metadata advertises only scopes_supported: ["openid","email","profile"]. Both offline_access and prompt=consent are added client-side. Removing offline_access from the authorization server's discovery document does not change the request either — verified.
Root cause — unchanged in SDK main today
packages/client/src/client/auth.ts (modelcontextprotocol/typescript-sdk, main, 2026-09-16):
- L1093–1103:
offline_accessis appended when the AS advertises it (SEP-2207) - L2114–2118:
``ts``
if (scope?.split(' ').includes('offline_access')) {
// ... set the prompt to "consent" to ensure the user is prompted to grant offline access
authorizationUrl.searchParams.append('prompt', 'consent');
}
Introduced by modelcontextprotocol/typescript-sdk#681 (July 2025). OIDC Core §11 requires the authorization server to ensure the user is prompted for offline access — it does not require the client to force prompt=consent. A compliant AS prompts when it needs to; forcing it client-side overrides the tenant's consent policy on every request.
Why the existing issues don't resolve this
| Issue | State | Note |
|---|---|---|
| #49722 | closed completed 2026-06-02 | no linked commit or PR; behaviour identical today |
| #64013 | closed not_planned | marked duplicate of #49722 → circular |
| modelcontextprotocol/typescript-sdk#1958 | open since 2026-04 | only de-duplicates the prompt parameter, does not remove it |
| #60152, #64482, #64636 | closed | same symptom family on the hosted M365 connector |
Impact
Every enterprise Entra tenant with user consent disabled is affected, on every Claude surface. The workarounds discussed in #49722 (editing the URL by hand, an interception proxy) are not viable for an org-wide rollout.
Expected
One of:
- do not send
prompt=consentunless explicitly requested by the user/organization, or - make it configurable per server (client metadata / connector settings), or
- omit
promptwhen the AS is OIDC-compliant and let it prompt when it actually needs to.
Please reopen #49722 or track here. Further captures (HAR, tokens redacted) available on request.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗