[BUG] MCP servers connect successfully but tools are not exposed to assistant

Status Closed — not planned
Maintainer reply None cached
Activity 15 comments · opened Nov 22, 2025 · closed Jul 11, 2026

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?

MCP servers are connecting successfully and reporting available tools in the debug logs, but these tools never become available to the Claude Code assistant. This issue affects all MCP servers (both user-level and project-level configurations) and persists across complete reinstalls of Claude Code.

What Should Happen?

When an MCP server is configured and connects successfully, its tools should be available to the assistant for use during conversations.

Error Messages/Logs

From ~/.claude/debug/latest:
  2025-11-22T22:42:34.165Z [DEBUG] MCP server "notion": Starting connection with timeout of 30000ms
  2025-11-22T22:42:34.692Z [DEBUG] MCP server "notion": Successfully connected to stdio server in
  529ms
  2025-11-22T22:42:34.693Z [DEBUG] MCP server "notion": Connection established with capabilities:
  {"hasTools":true,"hasPrompts":false,"hasResources":false,"serverVersion":{"name":"Notion
  API","version":"1.0.0"}}

Steps to Reproduce

  1. Configure any MCP server (tested with Notion MCP server):

claude mcp add --transport stdio notion --env NOTION_API_KEY=<key> -- /opt/homebrew/bin/npx -y
@notionhq/notion-mcp-server

  1. Verify connection: claude mcp list shows "✓ Connected"
  2. Start a Claude Code conversation
  3. Observe that no mcp__notion__* tools are available to the assistant
  4. Check debug logs - they show successful connection

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.0.50

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

15 Comments

github-actions[bot] · 9 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/2682
  2. https://github.com/anthropics/claude-code/issues/9133
  3. https://github.com/anthropics/claude-code/issues/11175

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

isiahw1 · 9 months ago

Additional Test Case: Docker MCP Gateway

I can confirm this issue affects Docker MCP Gateway as well. After extensive testing, I've verified that the problem is not specific to individual MCP servers but affects how Claude Code handles MCP tool exposure generally.

Environment

  • Claude Code Version: 2.0.50 (latest)
  • OS: macOS (Darwin 24.5.0)
  • MCP Server: Docker MCP Gateway (patched with PR #263)
  • Servers Tested: github-official, cloudflare-docs
  • Configuration: .mcp.json in project root

Test Results

Gateway Connection: ✅ SUCCESS

$ claude mcp list
MCP_DOCKER: docker mcp gateway run --secrets .env.mcp --servers cloudflare-docs - ✓ Connected

Gateway Tool Output: ✅ CORRECT FORMAT

$ docker mcp gateway run --servers cloudflare-docs
# Tools returned with MCP-compliant naming:
"name":"cloudflare-docs__search_cloudflare_documentation"
"name":"cloudflare-docs__migrate_pages_to_workers_guide"

Claude Code Tool Exposure: ❌ FAILURE

$ claude mcp list | grep "mcp__MCP_DOCKER"
# No output - no tools exposed despite successful connection

Technical Details

The Docker MCP Gateway is properly implementing the MCP protocol:

  1. Initialize handshake completes successfully
  2. tools/list returns proper tool definitions with valid names matching ^[a-zA-Z0-9_-]{1,64}$
  3. Server capabilities correctly advertised: {"tools":{"listChanged":true}}
  4. Tool naming uses double-underscore separator (MCP-compliant)

Configuration Used

.mcp.json:

{
  "mcpServers": {
    "MCP_DOCKER": {
      "command": "docker",
      "args": ["mcp", "gateway", "run", "--secrets", ".env.mcp", "--servers", "cloudflare-docs"],
      "type": "stdio"
    }
  }
}

.claude/settings.local.json:

{
  "permissions": {
    "allow": ["mcp__MCP_DOCKER__*"]
  },
  "enableAllProjectMcpServers": true
}

What We've Ruled Out

This is NOT caused by:

  • ❌ Tool naming format (verified MCP-compliant with double underscores)
  • ❌ Server connection issues (gateway shows ✓ Connected)
  • ❌ MCP protocol violations (handshake and tools/list work correctly)
  • ❌ Permissions configuration (tried multiple permission patterns)
  • ❌ Specific server implementation (affects GitHub, Cloudflare, Notion, Atlassian)

Pattern Confirmed

This issue affects multiple independent MCP implementations:

  • ✅ Notion MCP Server (reported by @original-reporter)
  • ✅ Atlassian MCP Server (issue #9133)
  • ✅ Docker MCP Gateway with GitHub server (this report)
  • ✅ Docker MCP Gateway with Cloudflare docs (this report)

All show same symptoms:

  1. Server connects successfully
  2. Debug logs show tools available
  3. Claude Code assistant cannot access tools
  4. claude mcp list doesn't show tools

Related Testing

I also tested building Docker MCP Gateway from PR #263 (fixes tool naming to use __ instead of :), which confirmed the gateway produces properly formatted tool names. Even with this fix, Claude Code still doesn't expose the tools.

Impact

This makes Docker MCP Gateway completely unusable with Claude Code, affecting access to 200+ MCP servers in the Docker catalog including:

  • GitHub (40 tools)
  • Cloudflare Docs (2 tools)
  • Playwright (6 tools)
  • Brave Search
  • And many more...

Request

Could the Claude Code team investigate what's preventing MCP tools from being exposed to the assistant despite successful server connections? This appears to be a systemic issue affecting multiple MCP server implementations.

Happy to provide additional debug logs or test specific scenarios if helpful!

github-actions[bot] · 8 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

Daanvdplas · 7 months ago

Why is no one working on this issue (or the ones that have been closed because they are duplicate of this one)? I literally can't use the mcp that I'm building because of this bug for quite some time

winzee · 7 months ago

Environment:

  • Claude Code version: 2.1.7
  • Platform: macOS (Darwin 24.6.0)
  • Shell: zsh
  • MCP Servers: 3 configured (bigquery via Google Cloud Toolbox 0.25.0, dbt-mcp 1.7.0, gitlab)

Confirmation:
All 3 MCP servers show ✓ Connected via claude mcp list, but no mcp__* tools are available to the assistant. Attempted tool calls return:
Error: No such tool available: mcp__bigquery__list_dataset_ids

Additional Finding - Environment Variable Timing:
We initially suspected environment variables weren't reaching MCP servers. After extensive debugging:

  1. SessionStart hooks with CLAUDE_ENV_FILE: Hook executes, file is written correctly, but variables weren't available to subsequent commands. Appears to be a separate issue or related timing problem.
  2. env key in .claude/settings.local.json: Successfully sets environment variables for Bash commands:

```{
"env": {
"BIGQUERY_PROJECT": "my-project-id"
}
}

2. After restart, `echo $BIGQUERY_PROJECT` works in Bash, but MCP tools still aren't exposed.

This confirms the issue is NOT about environment variables - the MCP servers receive their config (they show "Connected"), but the tool registration/exposure step fails.

---
**Update: Found the fix.**

Servers in `.mcp.json` need explicit enablement before tools are exposed to the assistant.

Solution: Either run `/mcp` and approve each server, or manually add to `~/.claude.json:`

`"enabledMcpjsonServers": ["dbt", "bigquery", "gitlab"]`

under the project path in projects.

The confusing part: `claude mcp list` shows "Connected" and servers respond correctly at the protocol level, but tools aren't available until enabled. A clearer status message would help.
Daanvdplas · 7 months ago

@claude fix this issue please

LIS-Benjamin · 6 months ago

How is this not fixed yet?!

clausqr · 6 months ago

this temp fix solved it for me

``` bash
claude mcp reset-project-choices
claude mcp add --transport http <mcp-server-1-name> <mcp-server-1-url>
claude mcp add --transport http <mcp-server-2-name> <mcp-server-2-url>
...
claude mcp add --transport http <mcp-server-n-name> <mcp-server-n-url>

then on next agent start mcps are there.
matjoos · 5 months ago

Still happening as of April 2026 on macOS with the Claude Code Desktop app (latest version).

Setup:

  • 4 stdio MCP servers configured (azure-devops, gitlab, laravel-boost, herd) via claude mcp add -s local and .mcp.json
  • - 1 HTTP MCP server (vuetify-mcp) via .mcp.json

Symptoms:

  • claude mcp list (from terminal in project directory) shows all 4 stdio servers as ✓ Connected
  • - In Desktop app sessions, only the HTTP server (vuetify-mcp) tools are available — zero stdio server tools appear
  • - - Restarting the Desktop app and starting new sessions does not help
  • - - - Config in ~/.claude.json is intact and correct

Key observation: HTTP-based MCP servers work fine. Only stdio/command-based servers fail to expose their tools to the assistant, despite connecting successfully. This pattern is consistent across all 4 of my stdio servers (different packages, different commands: npx, php).

bhosmer-ant · 3 months ago

Fixed — ships in v2.1.132.

omgoshjosh · 3 months ago

Just curious if this also fixes the file upload from claude code?

https://github.com/anthropics/claude-code/issues/25871

demyanm · 3 months ago

Adding our findings here since #62888 was flagged as a duplicate of this thread — posting in case the additional data points help narrow it down.

Environment

  • Claude Code 2.1.140 (downgraded from 2.1.152 in attempt to work around the 2.1.142+ tool-indexing regression — same symptom on both)
  • macOS 15.3 (Darwin 25.3.0), Node 20.19.5 via nvm
  • Mix of HTTP and stdio servers in .mcp.json (4 total)

Symptom (matches this issue exactly)

  • MCP logs show Successfully connected + capabilities: {"hasTools":true,...}
  • claude mcp list reports all four as ✓ Connected
  • mcp__<server>__* tools are absent from the session manifest (verified via ToolSearch and the deferred-tools list)
  • Affects both HTTP servers (Atlassian, AIO Tests) and stdio servers (Playwright MCP, Chrome DevTools MCP) — not stdio-only

State in ~/.claude.json for the project

{
  "hasTrustDialogAccepted": true,
  "enableAllProjectMcpServers": true,
  "enabledMcpjsonServers": [],
  "disabledMcpjsonServers": [],
  "mcpServers": {}
}

Top-level (user-scope) mcpServers in the same file initially contained only an unrelated entry. The loader only honored the user-scope list — the project .mcp.json was effectively ignored for manifest purposes, despite the flags above.

Workarounds tested

| Attempt | Result |
|---|---|
| enableAllProjectMcpServers: true (default) | ❌ Project servers absent from manifest |
| Explicit enabledMcpjsonServers: ["atlassian","aio-tests","playwright","chrome-devtools"] | ❌ Same — still absent |
| Re-accepting the trust dialog (delete + restart) | ❌ No change |
| Clearing ~/.claude/mcp-needs-auth-cache.json | ❌ No change (cache was already clean) |
| Mirror every server into user-scope mcpServers via claude mcp add --scope user ... | ✅ Tools appear in manifest |

The user-scope mirror is the only configuration that produces a working session. For stdio servers with relative --config ./... args, the mirror needs absolute paths so it resolves regardless of cwd.

Smell

The loader appears to read only top-level mcpServers in ~/.claude.json when populating the session, and claude mcp list walks all scopes — which is why the CLI subcommand and the in-session manifest disagree silently. Neither enableAllProjectMcpServers nor an explicit enabledMcpjsonServers allowlist changes that. From a user's perspective the failure mode is "everything looks green, nothing works," which is the worst kind for a config bug.

Happy to attach mcp-logs-* JSONLs if useful — they look identical to the original report (Successfully connected, hasTools:true, then crickets in the session).

Cross-ref: #62888 (this report, same project, more detail on the allowlist-doesn't-help angle).

caioribeiroclw-pixel · 3 months ago

The May reports in #51736 / #62888 make this look less like a single stdio bug and more like a missing boundary in the regression evidence: “connected” is being treated as equivalent to “tools crossed into the agent-visible catalog”.

A small diagnostic receipt that might help keep duplicate reports comparable:

registration_source: user | project .mcp.json | plugin.json | claude.ai connector | desktop project
server_transport: stdio | http | remote connector
server_connected: yes/no
initialize_completed: yes/no
proxy_or_server_tools_list_count: N
proxy_or_server_tools_list_sample: [tool_a, tool_b]
client_registry_enabled_for_project: yes/no/unknown
ToolSearch_or_deferred_catalog_count: N
ToolSearch_or_deferred_catalog_sample: [mcp__server__tool]
first_invoke_result: allowed | refused | not_found | auth_required
stopped_at: launch | initialize | tools/list | project choice | deferred catalog | first invoke

The useful bit is separating these cases:

  • server never launched / handshake failed
  • tools/list works, but project/user/plugin registration does not enable it for the current session
  • deferred catalog / ToolSearch never indexes the tools
  • catalog indexes the tools, but first invoke fails

That would also explain why some workarounds (reset-project-choices, re-adding as user-scope, toggling connectors) appear to help different people: they may be nudging different boundaries, not fixing the same failure mode.

visualcrossing · 2 months ago

Reproduces on HTTP transport with a fully spec-compliant server — adds evidence on the likely failure point.

Most reports here are stdio. This is the same symptom on HTTP transport, with a server that lets us isolate exactly
where the handshake breaks down.

Note: we arrived here via #55914 → #51736 → this issue.

Environment:

  • Claude Code CLI, Windows 11
  • Transport: Streamable HTTP
  • Server: Visual Crossing Weather MCP (currently internal - Happy to share the endpoint details with a maintainer

directly — feel free to DM me or leave a contact here.)

  • Registered via:

claude mcp add --scope user --transport http visualcrossing-weather \
https://<internalserver>.visualcrossing.com/VisualCrossingWebServices/rest/api/v1/mcp \
--header "X-VC-API-Key: <key>"

(no key is necessary for tool listing)
---
Symptom: claude mcp list shows ✓ Connected, but no tools are ever surfaced in the session. ToolSearch finds nothing
from this server.

---
Server is fully Streamable HTTP MCP spec-compliant. Verified with curl -i:

curl -i -X POST https://<internalserver>.visualcrossing.com/VisualCrossingWebServices/rest/api/v1/mcp \
-H "Content-Type: application/json" \
-H "X-VC-API-Key: <key>" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"client
Info":{"name":"test","version":"1.0"}}}'

Response:
HTTP/1.1 200
Mcp-Session-Id: 8baffdaa-8543-4491-b71f-428c6995ddaa
Content-Type: application/json

{"result":{"capabilities":{"tools":{}},"serverInfo":{"name":"visualcrossing-mcp-prototype","version":"0.1.0"},"protoco
lVersion":"2025-03-26","sessionId":"..."},...}

The server returns Mcp-Session-Id as a proper HTTP response header (not just a JSON body field) — exactly as the spec
requires.

When Mcp-Session-Id is attached manually on subsequent requests, notifications/initialized and tools/list both succeed
and return the tool catalog correctly.

---
Hypothesis on failure point:

Claude Code receives Mcp-Session-Id from the initialize response header (hence "✓ Connected"), but does not attach it
on subsequent requests (notifications/initialized, tools/list). The server rejects those requests as session-less,
tool discovery silently fails, and nothing is surfaced.

This is consistent with #29562 and #14977 (custom headers not propagated on post-init path). The difference here is
the missing header isn't one the user configured — it's one the server issued during initialize that the client should
be echoing back per the Streamable HTTP spec.

---
Workaround: Calling the endpoint manually via curl with the full 3-step handshake works correctly every time. Not
viable as a permanent solution but confirms the server is not the problem.

github-actions[bot] · 1 month ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.