skip to content
ainoya.dev

Fixing "Invalid OAuth error response" When Connecting Cursor to a Custom MCP Server

/ 3 min read

Table of Contents

I recently encountered a cryptic error while building a custom Model Context Protocol (MCP) server and attempting to connect it to the Cursor editor.

Even though I intended to use simple API Key authentication, Cursor threw an unhandledRejection immediately upon connection. The error message was confusing, seemingly pointing to a syntax issue in a JSON response that I hadn’t explicitly sent.

Here is what happened, how I debugged it, and why adhering strictly to the MCP authorization specification fixed the issue.

The Error

When attempting to add my local MCP server to Cursor, the connection failed with the following error output:

Error (unhandledRejection): HTTP 404: Invalid OAuth error response: SyntaxError: Unexpected non-whitespace character after JSON at position 4 (line 1 column 5). Raw body: 404 Not Found
ServerError: HTTP 404: Invalid OAuth error response: SyntaxError: Unexpected non-whitespace character after JSON at position 4 (line 1 column 5). Raw body: 404 Not Found

At first glance, the SyntaxError suggests a malformed JSON response. The specifically mentioned “position 4” is a hint: if the raw body is 404 Not Found, the parser reads 404 (a valid number in JSON) but chokes on the space and subsequent text that follows.

This meant Cursor was receiving a plain text 404 Not Found response but was expecting a JSON object.

The Investigation

To understand where this 404 was coming from, I checked the access logs of my custom MCP server. I noticed that immediately upon connection, Cursor was making a GET request to a specific path:

GET /.well-known/oauth-authorization-server

My server returned a 404 Not Found status code because I hadn’t implemented any OAuth endpoints. I was relying solely on API keys passed via headers or environment variables.

However, Cursor’s MCP client implementation appears to proactively check for OAuth support by probing this standardized endpoint. When it received a 404 text response, its internal logic—likely trying to parse an OAuth error configuration—crashed.

The Solution: Return 401, Not 404

I consulted the MCP Authorization Specification to see how authentication challenges should be handled.

The specification states:

MCP clients MUST be able to parse WWW-Authenticate headers and respond appropriately to HTTP 401 Unauthorized responses from the MCP server.

Although returning 404 for a missing endpoint is standard HTTP, Cursor’s client implementation failed to parse the text response. However, the MCP specification strictly mandates how clients must handle 401 responses. By returning 401, I forced Cursor to enter its spec-compliant error handling flow, effectively bypassing the crash.

The Fix

I modified my server’s middleware. Instead of letting the request fall through to a generic 404 handler for the .well-known path, I ensured it returned a 401 Unauthorized status code.

Once I deployed this change:

  1. Cursor probed /.well-known/oauth-authorization-server.
  2. My server returned 401 Unauthorized.
  3. Cursor correctly interpreted this as “OAuth not available” or “Authorization required” without crashing on JSON parsing.
  4. It successfully fell back to using the configured API Key method.

Conclusion

If you see an “Invalid OAuth error response” in Cursor, check your access logs. You might be returning a 404 where a 401 is expected.