[BUG] MCP server reports `hasTools: true` on connect and a reference client confirms tools exist, but Claude Code's session gets zero — intermittently
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
[BUG] MCP server reports hasTools: true on connect and a reference client confirms tools exist, but Claude Code's session gets zero — intermittently
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 version3.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-configwith 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
curlagainst the same URL with the same API key, issuing a rawinitializeJSON-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 -sshowed 38 total sockets (24 harmlessTIME-WAIT, 0 orphaned) — nowhere near any limit. - Not the
--allowedToolsallowlist 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 -pactively 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-formedtools/listresponse 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.)
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).
What Should Happen?
Well it should work every time
Error Messages/Logs
Steps to Reproduce
nah
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.220 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗