MCP OAuth callback returns ERR_EMPTY_RESPONSE — localhost callback handler sends no data

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

When connecting to a remote MCP server that requires OAuth authentication, Cursor’s built-in OAuth callback handler on localhost accepts the TCP connection but sends no HTTP response. The
browser shows ERR_EMPTY_RESPONSE and authentication never completes.

The server-side OAuth flow completes successfully — Cloud Run logs confirm the full chain: POST /mcp (401) → GET /authorize (302) → Google auth → GET /oauth/callback (302 back to localhost). The
server exchanges the Google auth code for tokens (HTTP 200 from Google) and redirects back to http://localhost:22389/oauth/callback?code=...&state=… But Cursor’s callback handler at that
address sends zero bytes.

Diagnostic findings:

  • lsof -i :22389 shows Cursor’s extension host process listening on port 22389 — not a separate mcp-remote child process
  • ps aux | grep mcp-remote shows no mcp-remote process for this server
  • ~/.mcp-auth/ contains client_info.json and code_verifier.txt but no tokens.json — the client-side token exchange never happens
  • The same server authenticates correctly when connected via mcp-remote from other MCP clients

Related forum threads (all closed without resolution):

  • MCP Server OAuth Flow Stuck After Authorization
  • OAuth MCP login fails
  • MCP OAuth callback loses authorization server URL
  • Cursor CLI MCP Callback Port

Steps to Reproduce

Configure a remote MCP server with OAuth in .mcp.json:

  {                                                                                                                                                                                                 
    "mcpServers": {                                                                                                                                                                                 
      "my-server": {                                        
        "command": "npx",                                                                                                                                                                           
        "args": ["-y", "mcp-remote", "https://my-server.run.app/mcp"]                                                                                                                               
      }                                                                                                                                                                                             
    }                                                                                                                                                                                               
  }       
  1. The remote server uses FastMCP v3 with Google OAuth (GoogleProvider)
  2. Cursor initiates the MCP connection and starts the OAuth flow
  3. Browser opens, Google authentication succeeds
  4. Google redirects to the server’s /oauth/callback, server exchanges code for tokens (200 OK), server issues 302 redirect to http://localhost:22389/oauth/callback?code=...&state=
  5. Browser reaches localhost:22389 → ERR_EMPTY_RESPONSE

Expected Behavior

Cursor’s callback handler at localhost:22389/oauth/callback should receive the authorization code, complete the OAuth token exchange with the remote MCP server, store the tokens, and return an HTTP response to the browser (e.g., “Authorization successful, you may close this window”).

Operating System

MacOS

Version Information

Version: 2.6.14 (Universal)
VSCode Version: 1.105.1
Commit: eb1c4e0702d201d1226d2a7afb25c501c2e56080
Date: 2026-03-08T15:36:54.709Z
Build Type: Stable
Release Track: Default
Electron: 39.6.0
Chromium: 142.0.7444.265
Node.js: 22.22.0
V8: 14.2.231.22-electron.0
OS: Darwin arm64 25.1.0

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Hey, great bug report. The lsof and ps aux diagnostics really help.

The issue is clear: Cursor’s extension host is grabbing the callback port instead of mcp-remote, and it doesn’t serve an HTTP response on that port. Because of that, mcp-remote either won’t start, or it can’t bind its callback listener.

I’ve passed this to the team. There’s no ETA yet, but your detailed diagnostics help us prioritize it.

A couple possible workarounds:

  1. Try connecting the server directly as HTTP/streamableHttp instead of using the stdio bridge via mcp-remote:
{
  "mcpServers": {
    "my-server": {
      "url": "https://my-server.run.app/mcp"
    }
  }
}

Cursor natively supports OAuth for HTTP-based MCP servers (via the cursor:// protocol handler). If the auth URL doesn’t open automatically, click the “Needs authentication” text under the server name, or copy the auth URL from Output > MCP:[server name].

  1. If you specifically need the stdio bridge, run mcp-remote outside of Cursor to get the token manually, then connect it in Cursor.

Let me know if the first option worked.

1 Like

This topic was automatically closed 22 days after the last reply. New replies are no longer allowed.