stdio MCP server tools dropped when initialize exceeds probe timeout
Summary
When a stdio MCP server's initialize handshake takes longer than the Claude
Code session-init probe timeout, the server's tools are silently dropped from
the deferred-tool registry. The server is later marked ✓ Connected (sometimes
inconsistently between claude mcp list and claude mcp get), butToolSearch returns No matching deferred tools found for everymcp__<server>__* lookup for the rest of the session. Restarting the session
does not help — the same race fires on every fresh probe.
Reproduces deterministically with code-context-mcp v2.0.4
(PyPI) on Windows, where the
server's initialize legitimately takes ~16 s on a warm Hugging Face cache
(loading sentence-transformers/all-MiniLM-L6-v2). Likely affects any stdio
MCP server whose cold-start exceeds a few seconds.
Environment
- Claude Code CLI:
2.1.131 - OS: Windows 11 Pro 26200
- MCP server type:
stdio - Server cold-init: ~16 s (verified via
code-context doctor mcp) .mcp.jsonregistered at project scope
Steps to reproduce
- Install a slow-initializing stdio MCP server (e.g.,
pip install code-context-mcpthen add to.mcp.json). - Open a fresh Claude Code session in the project.
- Inspect the system-reminder at session start — the slow server appears in the "still connecting" list but its
mcp__<server>__*tools never make it to the deferred-tools list. - Run
ToolSearch(query="select:mcp__<server>__<tool>")— returnsNo matching deferred tools foundeven minutes later.
Expected
The 8 (or N) tools advertised by the server are eventually discoverable viaToolSearch once the server completes initialize and responds totools/list.
Actual
Tools are never registered. The server reports ✓ Connected perclaude mcp list, but ToolSearch and the deferred-tools registry remain
empty.
Evidence
In one fresh session (2026-05-18):
Five ToolSearch queries with different syntaxes all miss:
ToolSearch(query="select:mcp__code-context__search_repo,...") → No matching deferred tools found
ToolSearch(query="code-context search") → returns unrelated tools, no code-context entry
ToolSearch(query="+code-context") → returns unrelated tools, no code-context entry
ToolSearch(query="search_repo find_definition") → No matching deferred tools found
ToolSearch(query="recent_changes get_summary explain_diff") → No matching deferred tools found
Server is healthy server-side (code-context doctor mcp --timeout 30):
initialize (open stdio + handshake) ok (16.40s)
list_tools ok (0.00s)
Tools advertised: 8/8 expected
claude mcp list / claude mcp get flip between Connected and Failed
in back-to-back invocations in the same session, strongly suggesting the
host's probe has a timeout shorter than 16 s:
| Invocation | Command | Reported status |
|------------|-------------------------------|--------------------------------|
| 1 | claude mcp list | code-context: ✓ Connected |
| 2 | claude mcp get code-context | Status: ✗ Failed to connect |
| 3 | claude mcp list | code-context: ✗ Failed to connect |
| 4 (same shell call) | claude mcp get | Status: ✓ Connected |
Hypothesis
The deferred-tool registry is populated from the first session-init probe.
That probe's timeout is shorter than the server's cold initialize, so the
probe times out, and the registry is filled without this server's tools. The
server eventually completes initialize on a later probe and is markedConnected, but the registry is never repopulated.
Proposed fixes (any one would resolve this)
- Raise the session-init probe timeout to ≥ 60 s, or make it
configurable per-server in .mcp.json (e.g., an initTimeoutMs field).
- Re-poll
tools/listopportunistically when a stdio MCP server
transitions Failed → Connected in the registry, and update the
deferred-tools index.
- Surface the probe timeout failure to the user during session start
(visible in /mcp or the system-reminder), with a hint to restart or
wait. Today the failure is silent.
Workaround
Operators can confirm server-side health independently withcode-context doctor mcp (a v2.0.4 subcommand that drives the real MCP
handshake against the same binary and verifies all tools come back fromtools/list). When doctor mcp passes but Claude Code shows no tools, the
issue is host-side.
Related artefacts
- Full validation report available on request (lives in the
code-context-mcp repo at
docs/superpowers/plans/sprints/SESSION-PROMPT-v204-validation.md).
- Server's stdout/stderr at probe time emits
register: wiring 8 MCP tools on Server instance followed by
list_tools() called by host; returning 8 tool descriptors — log lines
added specifically to disambiguate host-side vs server-side bugs.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗