This is a known issue that our team is actively tracking. While an earlier fix (shipped in 2.5) addressed some related problems, such as MCP servers incorrectly showing as connected after token expiry — the underlying refresh token behavior still has gaps.
When the access token expires, Cursor doesn’t reliably use the refresh token to silently obtain a new one, and instead falls back to requiring full re-authentication. You’re also right that the logs in recent versions provide less visibility into the refresh flow than older versions did (which used to show refreshPresent:true) — that reduced logging makes it harder to debug what’s happening.
Our team is aware and working on a more complete fix. Unfortunately, there’s no workaround at the moment other than re-authenticating when the connection drops.
Hey Mohit. I’m noticing now that Cursor is not timing out like it was previously. Before we go ahead and roll it out on our side / inform our customers, can you confirm this was fixed at your end?
Bharat, thanks for the update — glad to hear things are improving on your end.
I’ve checked and can’t confirm that a specific fix for this has shipped in the stable channel yet. There have been several improvements to MCP connection handling and OAuth resilience in recent builds, but they’re currently only available on the Nightly release track.
Before rolling this out to your customers, I’d recommend switching to Nightly ( Nightly Downloads | Cursor - The best way to code with AI ) and testing there for a few days to make sure the improvement holds. That way, you can validate against the latest fixes before committing to a broader rollout.
This is a separate issue from the original refresh token problem — a regression in a recent update broke the initial OAuth token exchange for MCP servers that use a separate authorization server.
A fix has been shipped. Could you update Cursor to the latest version (3.0.12 or later) and try the OAuth flow again? You can check your version in Help > About and trigger an update via the Command Palette > Attempt Update.
To answer your question about the redirect URL: the issue wasn’t the redirect URL itself, but that the token exchange request was being sent to the wrong server endpoint, which is why it returned a 404 from nginx. The fix corrects the endpoint resolution.
With the 3.0.12 version our OAuth flow stopped to working:
2026-04-07 17:26:41.187 [info] Persisting static OAuth client information for callback flow
2026-04-07 17:26:42.628 [info] Using enriched static OAuth client information from storage
2026-04-07 17:26:42.629 [info] Using redirect URL
2026-04-07 17:26:42.630 [info] Using redirect URL
2026-04-07 17:26:42.631 [info] Saving PKCE code verifier
2026-04-07 17:26:42.636 [info] MCP OAuth redirect to authorization
2026-04-07 17:26:42.641 [info] Stored server URL for OAuth flow
2026-04-07 17:26:42.641 [info] OAuth provider needs auth callback during connection
2026-04-07 17:26:42.641 [info] Connect failed after auth_required; returning needsAuth (streamableHttp)
2026-04-07 17:26:42.642 [info] MCP OAuth needsAuth (v2)
2026-04-07 17:26:42.643 [warning] [V2 FSM] connection:connect_failure: conn=connecting,auth=unknown -> conn=transient_failure,auth=unknown
2026-04-07 17:26:42.643 [info] ReloadClient completed, connected: false, statusType: needsAuth
2026-04-07 17:26:47.376 [info] Received OAuth callback with code
2026-04-07 17:26:48.854 [info] Using attempt-scoped OAuth client information for callback flow
2026-04-07 17:26:48.856 [info] Using redirect URL
2026-04-07 17:26:49.063 [error] Failed to complete OAuth exchange HTTP 404: Invalid OAuth error response: SyntaxError: Unexpected end of JSON input. Raw body:
The request is going to the root ‘/’ (at least we have this request in our logs), maybe it calls another url, we don’t know since the logs are ‘useful’ now.
In general, it would be helpful to have more useful information in the logs. For example, the log entry [info] Using redirect URL - is there a reason to not include the actual URL being used?
Similarly, in the last line - [error] Failed to complete OAuth exchange HTTP 404 - including the requested URL would significantly improve traceability.
Thank you.
This looks like the 3.0.12 fix didn’t fully resolve the token exchange issue for your OAuth server configuration. The fix addressed a specific regression, but the error pattern you’re showing (token exchange POST hitting / and returning a 404 with empty body) suggests endpoint resolution is still wrong for your setup.
I’ve flagged this with our extensibility team with your logs and details.
While the team works on a fix, you can try wrapping your MCP server with mcp-remote as a workaround:
This handles the OAuth flow externally and bypasses Cursor’s token exchange logic.
One question that would help the team: is your OAuth authorization server on a different domain from your MCP server URL? That setup is where the endpoint resolution has been failing most consistently.
APIM serves the well-known metadata at our domain (our.domain.dev), but the authorization_endpoint and token_endpoint in the metadata point directly to Microsoft:
We also serve /.well-known/oauth-protected-resource with a reference to the authorization server.
Also, my assumption that the request to the root is executed during the exchange might be wrong. I retested without noisy logs, and there is only one 404 request, which I believe is unrelated to the issue:
GET /.well-known/oauth-protected-resource/ai/mcp
Also, I’ve just rechecked Cursor version 2.6.21 - the OAuth flow works correctly there.
Here is the logs from Cursor 2.6.21 (if it can help):
2026-04-08 10:17:06.988 [info] Received OAuth callback with code
2026-04-08 10:17:08.046 [info] Using redirect URL
2026-04-08 10:17:08.046 [info] Using redirect URL
2026-04-08 10:17:08.046 [info] Using redirect URL
2026-04-08 10:17:08.047 [info] Using redirect URL
2026-04-08 10:17:08.370 [info] Saving tokens
2026-04-08 10:17:08.372 [info] OAuth authorization completed
2026-04-08 10:17:08.378 [info] [V2] Handling ReloadClient action
2026-04-08 10:17:08.378 [info] [V2 FSM] connection:connect_start: conn=idle,auth=unknown -> conn=connecting,auth=unknown
2026-04-08 10:17:08.380 [info] No scopes in config, fetching from well-known endpoint
2026-04-08 10:17:08.720 [info] Using OAuth scopes: openid, profile, offline_access, https://our.domain.dev/ai/mcp/Mcp.Full
2026-04-08 10:17:08.721 [info] Using redirect URL
2026-04-08 10:17:08.721 [info] Persisting static OAuth client information for callback flow
2026-04-08 10:17:10.155 [info] Successfully connected to streamableHttp server
2026-04-08 10:17:10.155 [info] [V2 FSM] connection:connect_success: conn=connecting,auth=unknown -> conn=connected,auth=unknown
2026-04-08 10:17:10.156 [info] ReloadClient completed, connected: true, statusType: connected
@Karlis_Melderis — Fair point on the logging. I’ve passed that feedback to the team. More actionable log output (including the actual URLs being used and the endpoints being called during token exchange) would make these issues much easier to debug from your side.
@Oleksandr_Reznichenk — Thank you for the detailed breakdown and especially the 2.6.21 comparison logs. This confirms the regression clearly.
Your setup (MCP server and OAuth authorization server on separate domains, with Microsoft Entra ID using a tenant-specific path like /common/v2.0) is the exact configuration that the recent fix didn’t fully cover. The fix corrected the issue for simpler setups, but in cross-domain configurations where the authorization server URL includes a path component, the endpoint resolution during the token exchange step remains incorrect.
I’ve flagged this specific variant — including your APIM + Entra ID details and the working 2.6.21 logs — with our extensibility team.
In the meantime, wrapping your MCP server with mcp-remote (as mentioned above) or staying on 2.6.21 are both viable workarounds while the fix is being developed.
@mohitjain
We’ve found a misconfiguration in our OAuth flow. After correcting it, both Cursor 2 and Cursor 3 now work well.
Sorry for the misleading information.