Project-scoped stdio MCP server with a path-based `command` shows "Connected" via `claude mcp list`/`get` but its tools never appear in the interactive session

Status Open
Maintainer reply None cached
Activity 2 comments · opened Jul 27, 2026

Title

Project-scoped stdio MCP server with a path-based command shows "Connected" via claude mcp list/get but its tools never appear in the interactive session

Body

Description

A project-scoped stdio MCP server defined in .mcp.json is reported as connected by claude mcp list / claude mcp get <name>, and responds correctly to raw JSON-RPC (initialize + tools/list) when the server binary is invoked directly (bypassing the claude CLI entirely). However, its tools never appear in the interactive session — not found via the tool-search mechanism, and ListMcpResourcesTool reports the server as entirely absent from the list of available servers.

A second stdio server in the same .mcp.json, configured with a bare PATH-resolved command name (no path separators), works correctly and its tools are visible/callable as expected.

.mcp.json (reproduction)

{
  "mcpServers": {
    "broken-server": {
      "type": "stdio",
      "command": "apps/my_app/.venv/bin/python",
      "args": ["apps/my_app/src/mcp_server.py"]
    },
    "working-server": {
      "type": "stdio",
      "command": "some-globally-installed-mcp-binary",
      "args": []
    }
  }
}

broken-server is a Python server built with the official mcp SDK's FastMCP (from mcp.server.fastmcp import FastMCP), version 1.28.1, exposing 4 simple tools (string in / string out).

What I tried (all reproduced across multiple full claude process restarts, not just new conversations)

  1. Relative path in command/args (as above) — tools never visible.
  2. Absolute path (hardcoded, e.g. /Users/me/repo/apps/my_app/.venv/bin/python) — tools never visible.
  3. ${CLAUDE_PROJECT_DIR:-.} expansion (per the documented pattern for portable absolute paths in project .mcp.json, https://code.claude.com/docs/en/mcp.md) — tools never visible.
  4. Removed FastMCP's auto-generated outputSchema (structured tool output) from all 4 tools via @mcp.tool(structured_output=False), on the theory that a JSON Schema shape difference vs. the working server's tools (which have no outputSchema) might be silently rejected — no change.
  5. Confirmed server-side correctness independently: spawned the server directly via Python subprocess, spoke raw JSON-RPC (initializenotifications/initializedtools/list) over stdio, and got a clean, correctly-shaped response listing all 4 tools with valid schemas. stderr only contained normal INFO-level logging, no errors.
  6. Confirmed ~/.claude.json's project entry has enableAllProjectMcpServers: true and .claude/settings.local.json has enabledMcpjsonServers: ["broken-server"] — not in a pending-approval state (claude mcp get never showed ⏸ Pending approval).
  7. As a final isolation test, wrapped the venv Python invocation in a small shell script and placed it on PATH under a bare name (matching exactly how working-server is configured) — this is the one variable I have not yet confirmed the outcome of at time of filing (in progress).

Key diagnostic finding

claude mcp list and claude mcp get <name> (invoked as short-lived subprocesses, e.g. via the Bash tool from within a session) consistently report the broken server as ✔ Connected with the correct command/args — this appears to be an independent, fresh connection check that does not reflect whether the actual long-running interactive host process has incorporated the server's tools into its own live toolset. This makes claude mcp list/get an unreliable signal for diagnosing this specific class of bug.

Environment

  • claude --version: v2.1.220 (also reproduced on v2.1.218)
  • OS: macOS
  • Both servers are "type": "stdio"
  • Interface used: VS Code native extension (Claude Code) and standalone terminal CLI — reproduced identically on both

Expected behavior

A stdio MCP server configured with a path-based command (relative, absolute, or ${CLAUDE_PROJECT_DIR}-expanded) should expose its tools in the interactive session exactly as a PATH-resolved bare-command server does, given that claude mcp list/get reports it as connected.

Additional notes

Happy to provide the exact mcp_server.py source, full raw JSON-RPC transcripts (initialize/tools/list responses for both the broken and working server, captured via direct subprocess testing), and the exact .claude.json/settings.local.json state if useful for reproduction. Redacted the actual project/business details above since this is a work repository, but can provide a minimal fully-reproducible example (a toy FastMCP server + toy .mcp.json) on request.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗