Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
Remote MCP servers protected by Microsoft Entra ID sign in fine, but token refresh always fails.
About 75 minutes after connecting, Cursor’s refresh is rejected with:
AADSTS90009: Application ‘’ is requesting a token for itself. This scenario is supported
only if resource is specified using the GUID based App Identifier.
Cursor retries about every 5 minutes, logs “Maximum reconnection attempts exceeded”, and the servers show
an error until the user clicks Connect again.
Steps to Reproduce
- Register one Entra app as both client and API: a public client with redirect
http://localhost/callback, an exposed scopeaccess_as_user, and the MCP server URL as an
Application ID URI. - Have the MCP server publish RFC 9728 and RFC 8414 metadata that point to Entra, plus a registration
endpoint that returns this app’s client ID. - Add the server to
mcp.jsonby URL and click Connect. Sign-in works and the tools load. - Wait for the access token to expire (60–90 minutes).
Expected Behavior
The token refreshes silently.
Operating System
MacOS
Version Information
3.23.12 (Universal)
Additional Information
Cause
The refresh request contains grant_type, refresh_token, client_id and resource, but no scope.
When one Entra app is both the client and the API, Entra needs the granted scope to issue the token.
With raw requests against the same refresh token, adding the granted scope makes the refresh succeed.
The cause is in the MCP TypeScript SDK and is tracked upstream:
- Issue: [v2] Incompatibility with refresh_tokens from Azure when client_id=resource_id · Issue #2718 · modelcontextprotocol/typescript-sdk · GitHub
- Fixes: #2720 (v2) and #2937 (v1.x backport)
Cursor’s bundled MCP client matches the v1.x code, and refreshes only through the SDK’sauth()path.
So shipping #2937, or passing the granted scope on refresh in Cursor’s OAuth provider, would fix it.
Cursor already stores the granted scope.
Workaround: click Connect again after each expiry. Sign-in is silent with SSO, but it’s one click per
server, every 60–90 minutes.
Does this stop you from using Cursor
No - Cursor works, but with this issue