HTTP MCP server health-check fails at project scope but succeeds at user scope (same URL/bearer/headers)

Resolved 💬 2 comments Opened Apr 11, 2026 by tmttodd Closed Jun 25, 2026

Summary

An HTTP MCP server registered at project scope (via .mcp.json) reports
Status: ✗ Failed to connect even though the exact same URL + bearer token +
headers registered at user scope (via claude mcp add -s user) reports
Status: ✓ Connected. The interactive session for the project-scoped entry
only surfaces the generic authenticate OAuth stub tool instead of the real
tool list, while the user-scoped entry exposes all tools normally.

Environment

  • Claude Code: 2.1.92 (Claude Desktop bundled binary)
  • macOS: Darwin 25.4.0
  • Server: FastMCP-based streamable HTTP server with bearer auth (no OAuth support)

Reproduction

  1. Create ~/.mcp.json defining an HTTP MCP server with bearer auth:

``json
{
"mcpServers": {
"example-mcp": {
"type": "http",
"url": "https://example.tld/mcp/",
"headers": {
"Authorization": "Bearer <TOKEN>",
"Accept": "application/json, text/event-stream"
}
}
}
}
``

  1. From a CWD with no own .mcp.json, run claude mcp get example-mcp:
  • Scope: Project config (shared via .mcp.json)
  • Status: ✗ Failed to connect
  1. Register the same config at user scope:

``
claude mcp add --transport http --scope user example-mcp https://example.tld/mcp/ \
-H "Authorization: Bearer <TOKEN>" \
-H "Accept: application/json, text/event-stream"
``

  1. Run claude mcp get example-mcp again:
  • Scope: User config
  • Status: ✓ Connected

Interactively, the project-scoped entry only exposes the stock authenticate
OAuth stub; the user-scoped entry exposes the full tool list.

Verified working independently

Direct curl to the same endpoint with identical headers succeeds:

curl -X POST https://example.tld/mcp/ \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"diag","version":"1"}}}'
# → HTTP 200, initialize result returned

tools/list also returns the full tool catalog over the same connection.

Observations

  • claude mcp list (shallow check) sometimes reports the project-scoped entry

as ✓ Connected while claude mcp get (deeper check) on the same entry
reports ✗ Failed to connect, suggesting the two commands use different
health probes.

  • The server requires Accept: application/json, text/event-stream (returns

HTTP 406 otherwise). The Accept header is present in both project and user
configs but only user scope works.

  • Interactive session falls back to the OAuth authenticate stub whose

authorize URL (<server>/authorize?client_id=dummy_client&…) returns
{"detail":"MCP server not found"} because the server does not implement
OAuth — it uses bearer auth only. This stub appears whenever CC can't
connect to an HTTP MCP server; surfacing it when bearer is configured is
misleading.

Expected

Project-scope and user-scope HTTP MCP entries with identical URL, transport,
and headers should behave identically.

Workaround

Remove the project-scope .mcp.json entry and register at user scope instead.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗