HTTP MCP server health-check fails at project scope but succeeds at user scope (same URL/bearer/headers)
Summary
An HTTP MCP server registered at project scope (via .mcp.json) reportsStatus: ✗ Failed to connect even though the exact same URL + bearer token +
headers registered at user scope (via claude mcp add -s user) reportsStatus: ✓ 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
- Create
~/.mcp.jsondefining 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"
}
}
}
}
- From a CWD with no own
.mcp.json, runclaude mcp get example-mcp:
- Scope: Project config (shared via .mcp.json)
- Status: ✗ Failed to connect
- 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"
- Run
claude mcp get example-mcpagain:
- 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
authenticatestub 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.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗