Claude Code reports the registered headroom MCP server as:
headroom: .../.venv/bin/headroom mcp serve - ✘ Failed to connect — -32000: MCP error -32000: Connection closed
Reproduced directly:
$ .venv/bin/headroom mcp serve
File "headroom/ccr/mcp_server.py", line 384, in __init__
raise ImportError("MCP SDK not installed. Install with: pip install mcp")
ImportError: MCP SDK not installed. Install with: pip install mcp
Three distinct defects stack up here.
1. Environment: the mcp extra was never installed.
pyproject.toml:227 declares mcp = ["mcp>=1.28.1", ...] as an optional extra. The repo .venv was built without it, so import mcp fails. This is the proximate cause of the Connection closed: the server process dies on stdio before completing the MCP handshake.
2. Code: the actionable error message is unreachable.
headroom/cli/mcp.py:351-356 wraps the import of create_ccr_mcp_server in try/except ImportError and prints the useful line Install with: pip install headroom-ai[mcp].
But headroom/ccr/mcp_server.py:52-59 deliberately swallows the SDK import failure and sets MCP_AVAILABLE = False. So the import at cli/mcp.py:352 succeeds, the guard never fires, and the ImportError is instead raised later at cli/mcp.py:381 during create_ccr_mcp_server(...) — outside the try. The operator gets a raw traceback and never sees the install instruction.
The guard is in the wrong place. It must cover construction, not just import.
3. Tests: the only coverage skips exactly when the bug is present.
tests/test_cli/test_mcp.py:302 is @pytest.mark.skipif(not MCP_AVAILABLE, reason="MCP SDK not installed"), and tests/_mcp_stub.py injects a fake SDK elsewhere. The suite is green (~9321 passed) because the real package is absent. This is a live instance of the warning already in FORK_CHARTER.md: "A passing test suite does not prove a module imports."
Fix
- Extend the
cli/mcp.py guard to cover create_ccr_mcp_server(...) so a missing SDK exits 1 with the install instruction and no traceback.
- Add a regression test that patches
MCP_AVAILABLE=False so it runs whether or not the SDK is present (i.e. it does not skip itself away).
- Install the
[mcp] extra into the venv and confirm claude mcp list reports connected.
Verification gate
Per FORK_CHARTER.md, not green-tests-alone: live claude mcp list must show the server connected, and a real MCP initialize handshake must return a result over stdio.
Claude Code reports the registered headroom MCP server as:
Reproduced directly:
Three distinct defects stack up here.
1. Environment: the
mcpextra was never installed.pyproject.toml:227declaresmcp = ["mcp>=1.28.1", ...]as an optional extra. The repo.venvwas built without it, soimport mcpfails. This is the proximate cause of theConnection closed: the server process dies on stdio before completing the MCP handshake.2. Code: the actionable error message is unreachable.
headroom/cli/mcp.py:351-356wraps the import ofcreate_ccr_mcp_serverintry/except ImportErrorand prints the useful lineInstall with: pip install headroom-ai[mcp].But
headroom/ccr/mcp_server.py:52-59deliberately swallows the SDK import failure and setsMCP_AVAILABLE = False. So the import atcli/mcp.py:352succeeds, the guard never fires, and theImportErroris instead raised later atcli/mcp.py:381duringcreate_ccr_mcp_server(...)— outside thetry. The operator gets a raw traceback and never sees the install instruction.The guard is in the wrong place. It must cover construction, not just import.
3. Tests: the only coverage skips exactly when the bug is present.
tests/test_cli/test_mcp.py:302is@pytest.mark.skipif(not MCP_AVAILABLE, reason="MCP SDK not installed"), andtests/_mcp_stub.pyinjects a fake SDK elsewhere. The suite is green (~9321 passed) because the real package is absent. This is a live instance of the warning already in FORK_CHARTER.md: "A passing test suite does not prove a module imports."Fix
cli/mcp.pyguard to covercreate_ccr_mcp_server(...)so a missing SDK exits1with the install instruction and no traceback.MCP_AVAILABLE=Falseso it runs whether or not the SDK is present (i.e. it does not skip itself away).[mcp]extra into the venv and confirmclaude mcp listreports connected.Verification gate
Per FORK_CHARTER.md, not green-tests-alone: live
claude mcp listmust show the server connected, and a real MCPinitializehandshake must return a result over stdio.