[BUG] MCP server reports hasTools: true on connect and a reference client confirms tools exist, but Claude Code's session gets zero — intermittently

Status Fixed / completed
Reported on v2.1.220
Maintainer reply None cached
Activity 1 comment · opened Aug 20, 2026 · closed Aug 21, 2026

Summary

An MCP server connects successfully and its connection-response capabilities correctly report "hasTools": true, but none of that server's tools ever become available to the model in the resulting Claude Code session — as if the server had never advertised any tools at all. This has happened intermittently but repeatedly, across multiple days and multiple independent CLI invocations, against the same MCP server and the same --mcp-config/--allowedTools setup that works correctly the rest of the time. Critically, at the exact moment one of these failures was occurring, a separate MCP client (the official @modelcontextprotocol/inspector reference implementation) connected to the identical server and reliably returned a full, correct tool list — see the cross-check at the end of the "ruled out" section below. That result points at Claude Code's own client-side handling, not at the server.

Environment
Claude Code CLI version: 2.1.220
Node version (per debug log): v26.3.0
Platform: linux (Amazon Linux 2023, running as a Jenkins CI agent)
Invocation mode: claude -p --bare (print/non-interactive), --output-format json
MCP servers configured: one remote HTTP server (https://mcp.newrelic.com/mcp, New Relic's official MCP server, reported version 3.4.1), one local stdio server (a small custom Python MCP server)
Steps to reproduce (as observed in production; not yet isolated to a minimal repro)
Configure --mcp-config with two servers: one HTTP transport, one stdio transport.
Run claude -p --bare --mcp-config ./mcp-config.json --allowedTools "mcp__<http-server>__<tool-name>" --output-format json, prompting the model to call exactly one tool from the HTTP server.
Most runs succeed. Intermittently (observed twice, on different days, affecting multiple independent invocations each time — see "Frequency" below), the model reports the tool is not available, e.g.:

"I don't have access to any MCP tools in this session — the only tools I have access to are Bash, Edit, and Read. There is no mcp__newrelic__get_entity tool registered."

Re-running the identical command, sometimes seconds later, sometimes on a later scheduled run, succeeds normally.
Expected behavior

If an MCP server's connection handshake reports hasTools: true, that server's tools (matching whatever's in --allowedTools) should be available to the model in that session, or the CLI should surface a clear error/warning if tool registration failed after a successful connection.

Actual behavior

The connection debug log shows a fully successful connection, including hasTools: true, with no error, warning, or timeout logged anywhere in the session — and the tool is still unavailable to the model. There is no log line between "connection established" and the model's own realization that it doesn't have the tool, meaning whatever fails happens silently, in a step the current debug output doesn't surface.

Evidence

Reproduced with -d/--debug --debug-file <path> enabled. Three consecutive, independent invocations (each a fresh claude -p process, no shared state) against the same MCP config, all showing the identical pattern:

Attempt 1 (mcp_debug_attempt1.log):

[DEBUG] MCP server "newrelic": Initializing HTTP transport to https://mcp.newrelic.com/mcp
[DEBUG] MCP server "newrelic": HTTP transport options: {"url":"https://mcp.newrelic.com/mcp","headers":{"User-Agent":"claude-code/2.1.220 (sdk-cli)", ...},"hasAuthProvider":true,"timeoutMs":60000}
[DEBUG] MCP server "newrelic": Testing basic HTTP connectivity to https://mcp.newrelic.com/mcp
[DEBUG] MCP server "newrelic": No token data found
[DEBUG] MCP server "newrelic": Successfully connected (transport: http) in 702ms
[DEBUG] MCP server "newrelic": Connection established with capabilities: {"hasTools":true,"hasPrompts":true,"hasResources":true,"hasResourceSubscribe":false,"serverVersion":{"name":"NewRelic Server","version":"3.4.1"}}
[DEBUG] [MCP] Server "newrelic" connected with subscribe=false

Result: mcp__newrelic__get_entity not available in the resulting session.

Attempt 2 (mcp_debug_attempt2.log, ~20 seconds later, fresh process): identical pattern — connects in 357ms, same hasTools: true, same subsequent unavailability.

Attempt 3 (mcp_debug_attempt3.log, ~20 seconds after that, fresh process): identical pattern — connects in 439ms, same hasTools: true, same subsequent unavailability.

All three sessions also loaded a second MCP server over stdio transport in the same --mcp-config, which connected and had its tools available normally in every session, including all three above. This isolates the issue to something specific to the HTTP-transport server's post-connection tool registration, not a general MCP subsystem failure, session startup problem, or anything affecting the CLI as a whole.

What we've ruled out, with evidence
Not an auth/credential problem with the MCP server itself. A direct curl against the same URL with the same API key, issuing a raw initialize JSON-RPC request, succeeds instantly and returns a normal, correct response, including at times overlapping with the failure window.
Not a server-side outage. The MCP server's own status page showed no reported incidents during either failure window.
Not a client-side timing/timeout race. All three logged connection attempts above completed in under a second. There is no slow attempt among them, and no evidence anywhere of the client giving up waiting on a handshake.
Not local resource exhaustion (file descriptors, sockets). Checked directly on the host during/after a failure window: ulimit -n = 65535, ss -s showed 38 total sockets (24 harmless TIME-WAIT, 0 orphaned) — nowhere near any limit.
Not specific to the original host's environment (network path, corporate security tooling, TLS certificate configuration). The original host's debug logs showed an unusually large system CA certificate count (861), raising a reasonable concern about TLS-inspecting security software interfering with the connection. This was directly tested by reproducing the failure on a completely unrelated machine — a different physical location, a different ISP, no corporate network or security tooling in common, and a minimal, standard certificate store (5 system CA certificates). The failure still occurred there (see the discovery-mismatch error below), which rules out both the original host's specific network path and its certificate configuration as the cause.
Not the --allowedTools allowlist itself being wrong. The exact same tool name works correctly in the large majority of runs, including runs immediately before and after a failure window, with byte-identical configuration.
Not a general incompatibility between this server and the current MCP spec. Ruled out directly and decisively: with claude -p actively failing this exact check (mid-retry, same moment, same host, same API key), we connected to the identical server (https://mcp.newrelic.com/mcp) using @modelcontextprotocol/inspector — a simpler, more spec-literal reference MCP client — and it returned a complete, well-formed tools/list response on the first try, listing all tools including every one this pipeline depends on (get_entity, execute_nrql_query, analyze_golden_metrics, analyze_transactions, list_entity_error_groups, analyze_entity_logs, list_change_events, list_recent_issues, search_incident, convert_time_period_to_epoch_ms). Repeated this several more times over a few minutes; Inspector succeeded every single time. This is the most direct evidence in this report: at the same moment, against the same server, one client succeeded reliably and the other failed intermittently. That points at something in Claude Code's own client-side handling of this server's response — either in parsing the returned tool list, or in some other client-specific aspect of the exchange — not at the server producing an inconsistent or non-compliant response. (New Relic's own support suggested this might be a case of their server predating the MCP specification's 2026-07-28 revision, and that Claude Code's client "sometimes parses successfully and sometimes doesn't" a non-current response format. The Inspector result above doesn't rule that out entirely, since Inspector could in principle be more tolerant of whatever the server returns — but if the server's response were genuinely malformed or spec-incompatible, a stricter reference client succeeding consistently, every time, while Claude Code fails intermittently, is a strange result for that theory to produce. At minimum, the burden of evidence right now sits with the client, not the server.)
A second, distinct symptom just captured, pointing at the same root cause

While reproducing this on a separate machine entirely (a personal laptop, macOS, different network, different ISP, no relationship to the original host beyond running the same Claude Code version and the same --mcp-config), a different, explicit failure occurred on the first genuine connection attempt:

[DEBUG] MCP server "newrelic": Saving discovery state (authServer: https://mcp.newrelic.com)
[DEBUG] MCP server "newrelic": HTTP Connection failed after 1020ms: Protected resource https://mcp.newrelic.com/mcp/ does not match expected https://mcp.newrelic.com/mcp (or origin) (code: none, errno: none)
[ERROR] MCP server "newrelic" Connection failed: Protected resource https://mcp.newrelic.com/mcp/ does not match expected https://mcp.newrelic.com/mcp (or origin)

The very next attempt, roughly four minutes later, connected and completed a tool call normally with no code or configuration change in between.

This is the first specific, named error this investigation has captured, as opposed to the silent "connects, reports tools available, then none materialize" pattern described above. Two details stand out:

This server is configured for API-key authentication in our setup (Api-Key header), not OAuth. Yet every debug log we've collected, on every host, shows the client reporting "hasAuthProvider": true and initiating an OAuth-style protected-resource discovery step (Saving discovery state (authServer: ...)) regardless. This suggests the client always attempts this discovery step for HTTP-transport MCP servers, independent of the auth method actually configured.
The mismatch is a single trailing slash: https://mcp.newrelic.com/mcp/ versus the expected https://mcp.newrelic.com/mcp. These are almost certainly the same resource from the server's perspective; something in this discovery step's comparison appears to be a strict string match that doesn't normalize a trailing slash, and it does not fail consistently — the identical client, server, and configuration succeeded on the very next attempt.

This looks like a strong candidate for the actual underlying mechanism behind both symptoms in this report: an intermittent inconsistency in the resource-discovery/connection-establishment step of Claude Code's MCP client, which can either surface as this explicit error or, in other observed cases, as a connection that reports success and hasTools: true while never actually exposing any tools to the model. Both would share the same root location in the client, and both are consistent with everything ruled out above (server health, credentials, network environment, and host resources all check out identically across every instance where this has been observed, including two unrelated hosts on two unrelated networks).

Frequency and pattern

Observed twice so far, each time affecting several independent, sequential claude -p invocations in a row (different processes, different working directories, same host, same MCP config) over a span of roughly 5–15 minutes, then resolving on its own. Not observed to affect isolated single invocations outside of these windows. This clustering pattern — several consecutive processes over a sustained window, rather than one-off failures scattered randomly — may be a useful clue, though we don't have a hypothesis for the mechanism.

Impact

Because the session otherwise completes normally ("subtype": "success" in --output-format json) and the model can still respond in prose, a caller that doesn't explicitly verify the specific tool it needed actually got called would have no way to detect this failure — the session looks entirely successful from the outside. We've mitigated this on our end with an explicit pre-flight tool-call verification step before doing any real work, but it seems worth flagging that a silent hasTools: true → tool-never-registered gap could affect anyone relying on a remote HTTP MCP server without that kind of extra verification.

Additional info available on request

Full debug logs for all three attempts (redacted of the API key, which the CLI already redacts automatically in the log output).

Related issues in this repository

Several other issues in this repository describe the same core symptom — an MCP server connecting successfully and reporting tools available, with those tools never actually becoming callable in the session — against unrelated MCP servers and integrations. Listed roughly in order of relevance:

#44290 — "MCP tools never loaded — Haiku title-generation model check blocks all custom MCP tool loading regardless of transport, proxy, or ENABLE_TOOL_SEARCH setting" (closed, filed against v2.1.92). This one is worth reading closely: it identifies a specific mechanism — the background Haiku call Claude Code fires for session title generation (source=generate_session_title) is checked for tool_reference block support, and when that check fails, it appears to gate MCP tool loading session-wide, even though the actual conversation model supports tool_reference fine. Our own debug logs show this identical generate_session_title Haiku call firing on every session, successful and failed alike. The reported behavior there was fully deterministic (100% reproduction across every transport/model/proxy combination tested) and was apparently fixed by the time of that closure, well before the 2.1.220–2.1.238 versions this report is filed against — so this is unlikely to be the identical live bug, but it's concrete prior art that this exact subsystem (the title-generation model check interacting with MCP tool loading) has broken in exactly this shape before. Worth checking whether that fix was complete, or whether a narrower, timing-dependent variant of the same interaction could explain why this now only fails intermittently rather than always.
#12164 — MCP servers (tested with Notion, stdio transport) connect successfully and report tools available, but the tools never become available to the assistant. Same core symptom, different server.
#69422 — claude.ai connectors report hasTools: true and connect via the claude.ai proxy transport, but contribute zero usable tools to interactive sessions.
#57315 — MCP tools (tested with Lark, 22 tools, shown as connected in the UI) disappeared entirely between CLI versions 2.1.132 and 2.1.133, deterministically, with no configuration change.
#11448 — the Claude Code VSCode extension shows MCP servers as connected with hasTools: true in debug logs, but tools are never exposed to the assistant, while the identical configuration works correctly in the CLI.
Closing context: ruled out by New Relic's own support

New Relic's support was consulted independently and initially suggested this could be a case of their MCP server predating the MCP specification's 2026-07-28 revision. When presented with the evidence above — specifically that the same client, server, and configuration fails intermittently rather than consistently, and that a reference client succeeds reliably at the exact moment Claude Code fails on the identical server — their support agreed this explanation doesn't hold up, since a static format-compatibility gap should fail consistently, not intermittently with no change on either side. Their assessment: "this does look more like a race condition or transient state issue in Claude Code's HTTP MCP client than a format-compatibility problem... the available docs don't cover this specific failure mode."

What Should Happen?

MCP communication with New Relic should work each time

Error Messages/Logs

Steps to Reproduce

echo "Call mcp__newrelic__get_entity once, searching for any entity of type APPLICATION. Reply with MCP_CHECK: OK if it works, or MCP_CHECK: FAILED if not." | claude -p --bare --add-dir . --mcp-config ./mcp-config.json --allowedTools "mcp__newrelic__get_entity" --output-format json --debug

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.238 (Claude Code)

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗