MCP OAuth always sends prompt=consent, forcing 'Approval required' loops in enterprise tenants that block user consent (even with admin consent already granted)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

When Cursor initiates OAuth for a remote MCP server with static client credentials
(auth.CLIENT_ID in mcp.json), the authorize URL always includes prompt=consent.
Example (Microsoft Entra ID / Agent 365 MCP), authorize request includes parameters like:
response_type=code, client_id=…, redirect_uri=http://localhost:8787/callback,
scope=…, and prompt=consent
In tenants that disable user consent (common in enterprise/regulated orgs), this forces
an “Approval required” screen on every Connect attempt — even when:

  • Tenant admin consent has already been granted for the app
  • The exact same client ID + scopes work fine in other MCP clients (e.g. Claude Code,
    which does not send prompt=consent)
    Manually copying the authorize URL and removing prompt=consent before opening it in
    a browser allows sign-in to complete silently and the MCP server connects successfully —
    confirming this parameter is the root cause, not the Entra app config.
    Request: make prompt=consent optional/configurable in mcp.json’s auth block (e.g.
    auth.prompt or a boolean to suppress it), or drop it by default when the server
    reports admin consent is already satisfied.
    Environment:
  • Cursor Desktop, macOS
  • Remote MCP server, Streamable HTTP, static auth.CLIENT_ID
  • Microsoft Entra ID / Agent 365 Tools tenant with user consent disabled

Steps to Reproduce

  1. Register a public client app in Microsoft Entra ID with platform “Mobile and desktop
    applications” and redirect URI http://localhost:8787/callback
  2. Grant tenant admin consent for the required delegated API permissions/scopes on that app
  3. Add the MCP server to ~/.cursor/mcp.json using static OAuth credentials (auth.CLIENT_ID
    plus scopes)
  4. Reload Cursor, go to Settings, MCP, and click Connect on the server
  5. Observe the browser is redirected to Microsoft Entra ID’s OAuth2 v2.0 authorize endpoint
  6. Inspect the URL query parameters — it includes prompt=consent
  7. If the tenant has user consent disabled, this returns an “Approval required” screen
    requesting the user submit an admin approval request — every single time, regardless
    of prior admin consent
  8. As a manual test, copy the same authorize URL, remove only the prompt=consent parameter,
    and open the edited URL in the same browser tab/session
  9. Sign-in completes normally with no approval screen, and the MCP server connects
    successfully

Expected Behavior

Expected Behavior:

  • If the tenant admin has already granted consent for the app’s requested scopes, Cursor’s
    OAuth flow should not force an interactive consent screen on every Connect attempt
  • prompt=consent should either not be sent by default, or be configurable/optional in the
    mcp.json auth block (e.g. an auth.prompt field or boolean), so users/admins in enterprise
    tenants can suppress it
  • Other MCP clients (e.g. Claude Code) using the same Entra app, client ID, and scopes
    connect successfully without this forced prompt — indicating this is Cursor-specific
    behavior, not an issue with the Entra app or tenant configuration

Operating System

MacOS

Version Information

Version: 3.16.17
VS Code Extension API: 1.128.0
Commit: 6b2afae0257df2bb5e1835f15165dc2f0de056b0
Date: 2026-08-14T01:41:12.803Z
Layout: Agent Window
Build Type: Stable
Release Track: Default
Electron: 40.10.3
Chromium: 144.0.7559.236
Node.js: 24.15.0
V8: 14.4.258.32-electron.0
xterm.js: 6.1.0-beta.291
OS: Darwin arm64 25.6.0

Does this stop you from using Cursor

No - Cursor works, but with this issue

Thanks for the detailed report. You’ve got this right: the authorize URL includes prompt=consent, and in a tenant with user consent disabled that sends people to the approval request screen every time, even where admin consent is already granted. Nothing in your app registration or tenant setup is causing it.

The parameter gets added whenever offline_access is in the requested scope set, and with Entra backed servers that scope usually comes from the server’s advertised metadata rather than your mcp.json, so it shows up even if you never asked for it. Editing the authorize URL by hand is the reliable path for now.

This is an issue we’re tracking, and we will post here with any updates.

Confirming the same prompt=consent behavior on the new Grok Bot first-party Microsoft plugins, not only custom MCP in Cursor IDE.

Where: Grok Bot → Plugins

Plugins: Outlook, Outlook Calendar, and OneDrive (Cursor Marketplace / “Outlook for Grok Bot” and the matching Calendar + OneDrive plugins)

What happens:

Connecting any of those plugins opens the Microsoft authorize URL with prompt=consent. On an Entra tenant using Microsoft-managed user consent (user consent blocked for mail/calendar/files), that forces an “Approval required” / admin-consent-workflow interrupt on every connect.

This is after tenant-wide admin consent is already granted on the SpaceXAI enterprise app for the exact delegated scopes those plugins request:

Calendars.ReadWrite, Contacts.Read, Files.Read.All, Mail.Read, Mail.Send, offline_access, openid, profile, User.Read

Entra sign-in log for the failed attempt:

  • Status: Failure
  • Error code: 90095 (AdminConsentRequiredRequestAccess)

Assignment required is off. Admin consent request queue is empty. Only one Application ID for the app. Permissions blade shows Type = Delegated, Granted through = Admin consent.

Workaround that proves the cause:

On the account-picker URL, change prompt=consent → prompt=login (or delete &prompt=consent) and continue. Sign-in then completes against the existing grant. Same workaround Matthew described.

offline_access is in the requested scopes, which matches kevinn’s note about why prompt=consent gets appended.

Please treat Grok Bot’s Outlook / Calendar / OneDrive plugin OAuth as in-scope for this fix, not just Cursor IDE MCP. Until prompt=consent is omitted after an AllPrincipals grant exists, these plugins stay unusable in standard enterprise tenants without manually editing the authorize URL.

One extra Grok Bot-specific note on the workaround: I removed prompt=consent in the same Microsoft window Grok Bot opened (not a copied tab). That got past the Entra 90095 / “Approval required” wall, but Grok Bot still never marked the account as connected. Outlook / Calendar / OneDrive stayed unauthenticated.

So the URL edit is enough to prove prompt=consent is what triggers the enterprise consent loop. It is not a usable workaround for these Grok Bot plugins, because the client does not complete its own OAuth callback after that edit. The fix has to be on the authorize request Grok Bot sends: stop adding prompt=consent when tenant admin consent already covers the requested scopes (including offline_access).

Thanks Grok for helping me word this.. :saluting_face: My brain is fried from troubleshooting.

Confirming the same issue here, we have user consent disabled in our tenant and as a result nobody is able to sign in to the plugin with Grok Bot unless they happen to be an Entra admin. They just constantly get an Entra error AADSTS90094: Admin consent is required for the permissions requested by this application, despite an admin having already granted admin consent for the SpaceXAI app for our tenant.

FWIW my workaround was having my bot add in things manually for our other team folks that are using Grok Bot also and ignoring the plugin that is available. YMMV. I only had to do one approval for another team user in Entra and then no issues getting them connected (same with myself and with the bots own team m365 login). Replace “[email protected]” with what the actual email is supposed to be and replace (American/TIMEZONECITY) with whatever your country/timezone city actually is. Replace ADMIN in the 2nd to last paragraph if you want a specific person name in there. It’s just a formality of who does the approving in entra.

This was my setup before the plugin got announced and is now the workaround until the plugin is fixed. The bot couldn’t find much difference between this route and the plugin TBH.

Set up Microsoft 365 for me WITHOUT marketplace plugins. Do not install the Cursor marketplace Outlook, OneDrive, or Outlook Calendar plugins. Do not add Microsoft MCP Server for Enterprise, Entra admin, or any directory-wide Graph server.

I want Graph access to MY work mailbox, calendar, and OneDrive only.

Account to sign in as (must be this, never another mailbox):
[email protected]

Add a local stdio MCP connector with AddMcpServer (confirm with me first, then add):
- name: ms365
- command: npx
- args:
  -y
  @softeria/ms-365-mcp-server
  --org-mode
  --preset
  outlook,onedrive
  --allowed-scopes
  User.Read Mail.Read Mail.Send Calendars.ReadWrite Files.ReadWrite
  --expected-username
  [email protected]

Do NOT pass --read-only (I need send mail, calendar writes, and OneDrive uploads).
Do NOT use --auth-browser (that Softeria app has no reply URL and fails with AADSTS900971).
Do NOT request User.Read.All, Directory.Read.All, Group.Read.All, Sites.Read.All, Mail.Read.All, or RoleManagement/AuditLog.

After it is added:
1. Call the Graph `login` tool (device-code flow). Show me the user code and tell me to open https://microsoft.com/devicelogin on my phone or laptop. Do not open a bot-browser OAuth page. Do not ask me to paste my password or 2FA into chat.
2. After I complete device login, call `verify-login` and confirm the signed-in UPN is [email protected]. If it is any other account, log out and stop.
3. Smoke-test: list a few of my mail messages, a calendar view for the next 7 days (America/TIMEZONECITY), and my OneDrive drives/root. Then tell me it worked.

If device-code login is blocked by Conditional Access (AADSTS50005 / device code blocked, or compliant-device required), stop and tell me so ADMIN can exclude this account. Do not try workarounds, cookies, or marketplace plugins.

If send-mail later fails on a larger PDF attachment, use Outlook on the bot computer as a fallback. If a OneDrive upload fails in Graph, use the signed-in OneDrive web UI on the bot computer. Do not treat that as a reason to install the marketplace plugins.