MCP OAuth fails when protected resource URL has a trailing slash

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Cursor’s built-in (native type: http) MCP client normalizes the configured server
URL by stripping its trailing slash before performing the OAuth 2.0 protected-resource
validation. When a remote MCP server identifies its protected
resource with a trailing slash (e.g. https://…/mcp/), the comparison fails and the OAuth
flow is aborted with “Authorization session ended.” There is no way to work around it
from mcp.json, because Cursor strips the slash regardless of what the user configures.

Environment

  • Cursor version: 3.12.17
  • OS: macOS (Darwin 24.6.0)
  • Server under test: New Relic MCP server — https://mcp.newrelic.com/mcp/ (streamable HTTP, OAuth)
  • Loaded via a local plugin (~/.cursor/plugins/local/<plugin>/mcp.json), but the same
    failure occurs for a plain user-level MCP server entry.

Steps to Reproduce

  1. Configure a remote MCP server whose OAuth protected resource metadata advertises a
    resource identifier ending in a slash, e.g. New Relic:

    {
      "mcpServers": {
        "newrelic": {
          "type": "http",
          "url": "https://mcp.newrelic.com/mcp/"
        }
      }
    }
    
  2. Reload the window and start the OAuth login for the server.

  3. Complete the New Relic login in the browser.

Expected Behavior

OAuth completes; the server connects and exposes its tools.

Actual

The browser shows “Authorization session ended. Return to Cursor to try connecting again.”
and the server never authenticates. Cursor’s MCP logs show the resource-match failure:

[warning] OAuth callback exchange failed for plugin-newrelic-newrelic:
  Protected resource https://mcp.newrelic.com/mcp/ does not match expected https://mcp.newrelic.com/mcp

[warning] Transient error connecting to streamableHttp server:
  Protected resource https://mcp.newrelic.com/mcp/ does not match expected https://mcp.newrelic.com/mcp (or origin)
[warning] Connection failed: Protected resource https://mcp.newrelic.com/mcp/ does not match expected https://mcp.newrelic.com/mcp (or origin)
[V2 FSM] connection:connect_failure: conn=connecting,auth=unknown -> conn=failed,auth=unknown

Note:

  • “Protected resource …/mcp/ is the value the server advertises (correct, with slash).
  • “expected …/mcp is Cursor’s configured URL after it stripped the trailing slash.
  • The error is byte-for-byte identical whether url is set to .../mcp or .../mcp/,
    which proves Cursor normalizes the trailing slash away before the comparison — the user
    cannot influence the “expected” value from config.

Proof the server’s …/mcp/ is correct (not a New Relic bug)

Routing the identical server through mcp-remote authenticates successfully. With the trailing slash
preserved, the OAuth resource parameter matches the advertised protected resource and the
flow completes.

After completing login, the server connects and all tools load. The only difference
between the failing native path and the working mcp-remote path is that mcp-remote
does not strip the trailing slash.

Operating System

MacOS

Version Information

Version: 3.12.17 (Universal)
VS Code Extension API: 1.128.0
Commit: 0fb762053c34788bb7760d5673f8a6d4c8589d50
Date: 2026-07-17T02:53:53.006Z
Layout: Agent Window
Build Type: Stable
Release Track: Default
Electron: 40.10.3
Chromium: 144.0.7559.236
Node.js: 24.15.0
V8: 14.4.258.32-electron.0
xterm.js: 6.1.0-beta.256
OS: Darwin arm64 24.6.0

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the detailed report. Your diagnosis is spot on. The native MCP HTTP client really does normalize the URL and remove the trailing slash before it runs the protected resource check, so .../mcp/ from the server doesn’t match .../mcp in the expected value, and there’s no way to work around that via mcp.json.

This is an issue we’re already tracking. The same symptom was reported on Userback: MCP OAuth fails with "Protected resource … does not match expected". I passed your case to the team with the details. I can’t share a timeline yet, but I’ll reply here when there’s an update.

For now, your workaround using the mcp-remote proxy is really the only option. This can’t be fixed via config, so please stick with that until we ship a fix.

If you notice anything else or get new details, please post them in the thread.