[BUG] Remote MCP OAuth connector: "Connected · tools fetch failed" while the same server works via static-token HTTP registration

Open 💬 0 comments Opened Jul 4, 2026 by willihangga

Summary

A spec-compliant custom remote MCP server (Streamable HTTP) fails to expose tools only
through the claude.ai OAuth connector path. OAuth completes and the handshake starts, but
tool fetching fails. The exact same server URL works end-to-end when registered directly
with a static bearer token.

Environment

  • Claude Code v2.1.199 (also reproduced via claude.ai web + Claude Desktop custom connector)
  • Server: custom Streamable HTTP MCP, single endpoint at /, OAuth 2.1 (Authorization Code +

PKCE) per the MCP spec; also accepts a static bearer token.

Steps to reproduce

  1. Add the server as a claude.ai OAuth custom connector (via URL) and complete consent.
  2. Add the same URL in Claude Code with a static token:

claude mcp add --transport http mysrv https://mcp.example.com/ --header "Authorization: Bearer <redacted>"

  1. Run claude mcp list.

Observed

My OAuth Connector    https://mcp.example.com    - ! Connected · tools fetch failed
mysrv (static token)  https://mcp.example.com/   - ✔ Connected

Via /mcp, the OAuth connector reports:
Reconnected to <name>, but fetching tools failed: Not connected

What works (the server is spec-compliant)

The same server, hit directly (not via the OAuth connector), succeeds:

  • curl and the official Python MCP SDK (streamablehttp_client): initialize + tools/list
  • tools/call all succeed.
  • Static-token claude mcp add --transport http: ✔ Connected, tools usable.
  • The server returns a stable Mcp-Session-Id on the MCP endpoint, isError results for

tool-level failures (not JSON-RPC errors), 202 Accepted for notifications, and 200 for
HEAD / and DELETE /.

Server-side observation (OAuth-connector path only, from access logs)

Driven by the OAuth connector, the server receives:
initializenotifications/initializedtools/list, then repeated initialize calls
and never a tools/call
. Requests arrive from multiple distinct source IPs (a
distributed / load-balanced connector), which suggests the workers do not share MCP session
state, so each one re-initializes and the tool-call phase never completes.

Impact

Custom OAuth connectors are unusable for tool calls, while the identical server works fine via
static-token / direct connections. This blocks the standard end-user "add a custom connector via
URL + OAuth" flow.

Question

Does the OAuth-connector (cloud-proxy) path handle tools/list / session continuity differently
than a direct static-token HTTP registration? Is there a response the connector requires (e.g.
Mcp-Session-Id semantics, a protocol-version echo, or an SSE stream) that a direct client does
not, and which is being lost across the connector's distributed workers?

Related (not duplicates)

  • #5826 — Claude Desktop doesn't connect to custom MCPs at all (ours connects, but tool-fetch fails).
  • #9133 — stdio server, tools not exposed in session (closed).
  • #43397 — cloud scheduled tasks / routines can't access MCP connectors.

View original on GitHub ↗