MCP OAuth Token Not Used After Successful Authentication

,

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Using our plugin, after successfully completing OAuth authentication, Cursor saves the access token but does not use it for subsequent MCP requests. Instead, it immediately starts a new OAuth flow.

Steps to Reproduce

  1. Configure MCP server with OAuth authentication (remote SSH, remote ~.cursor/mcp.json used.
{
  "mcpServers": {
    "my-server": {
      "url": "https://example.com/mcp/",
      "auth": {
        "type": "oauth",  (note: tried specifying this and removing this parameter)
        "CLIENT_ID": "...",
        "scopes": ["read", "write"]
      }
    }
  }
}

We also tried specifying an audience (e.g. https://example.com/mcp ) to no avail.

(note: We have a public, native app that doesn’t require a CLIENT_SECRET to be specified, however we do define a client secret in Auth0, and this unrelated token exchange succeeds later in the process).

  1. Enable the MCP server in Cursor
  2. Click “Connect” to start OAuth flow
  3. Complete authentication (Auth0 passwordless in our case)
  4. Observe: OAuth completes, tokens saved, but server immediately shows “Needs authentication” again

Expected Behavior

After OAuth completes, Cursor should send POST requests to the MCP endpoint with Authorization: Bearer header.

Actual behavior:
After OAuth completes:

  1. Cursor logs: Saving tokens and OAuth authorization completed
  2. Cursor reloads the client
  3. Cursor immediately starts a NEW OAuth flow (logs show Saving PKCE code verifier)
  4. Server receives NO POST requests with Bearer token (confirmed via server logs)
  5. MCP status returns to “needsAuth”

Operating System

Linux

Version Information

Version: 2.6.20
VSCode Version: 1.105.1
Commit: b29eb4ee5f9f6d1cb2afbc09070198d3ea6ad760
Date: 2026-03-17T01:50:02.404Z
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Linux x64 6.8.0-106-generic

For AI issues: which model did you use?

N/A

For AI issues: add Request ID with privacy disabled

N/A

Additional Information

MCP Client Logs (Truncated):

23:42:48.650 [info] Saving tokens
23:42:48.783 [info] OAuth authorization completed
23:42:48.959 [info] Handling ReloadClient action
23:42:49.137 [info] Connecting to streamableHttp server
23:42:49.901 [info] Saving PKCE code verifier        <-- NEW OAuth flow starting!
23:42:50.108 [info] Redirect to authorization requested
23:42:50.243 [warning] UnauthorizedError: Unauthorized

Server Logs:
Only OAuth discovery requests received - NO POST /mcp/ with Bearer token:

GET /.well-known/oauth-protected-resource/mcp  200

No mcp_auth_attempting_oauth or mcp_auth_no_credentials_provided logs, confirming no POST requests made.

Additional Context

  • All required callback URIs set in Auth0
  • Auth0 API is suitably permissioned for Auth0 application access (user access: all permissions)
  • Server correctly returns WWW-Authenticate header on 401
  • OAuth discovery endpoints work correctly
  • Auth0 token exchange completes successfully
  • curl POST requests to /mcp/ with Bearer token work fine
  • API key authentication works as expected

Guidance at Model Context Protocol (MCP) | Cursor Docs was followed. For now, we plan to return to specifying our MCP API key as an environment variable in order to submit our plugin (inconvenient but workable)

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the detailed bug report. The logs are really helpful.

This is a known issue with MCP OAuth over Remote SSH. What happens is the OAuth callback finishes on the local side, but the MCP extension runs on the remote host. When you reconnect, the saved tokens don’t make it to the remote extension host, so right after ReloadClient it starts a new OAuth flow instead of using the token you already got.

The team is aware of this. I don’t have a specific timeline yet, but your report helps us prioritize it.

For now, your workaround using an API key via an env var is the most reliable option for Remote SSH. A couple of similar threads for context:

Let me know if you need anything else.

1 Like