Plugin-registered MCP servers don't expose tools to the AI (tools visible in `claude mcp list` but not callable)
Summary
MCP servers registered via a plugin's plugin.json mcpServers field connect successfully and list their tools correctly, but those tools never appear as callable tools in the AI's session. The identical server registered via claude mcp add --scope user works correctly.
Environment
- Claude Code: v2.1.142
- OS: Linux (Ubuntu, kernel 6.17)
- Plugin: context-mode v1.0.134
Steps to Reproduce
- Install a plugin that provides an MCP server via
plugin.json:
``json``
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/start.mjs"]
}
}
}
- Start a Claude Code session
- Run
claude mcp list— server shows as✓ Connectedwith its tool count
- Ask Claude to use one of the server's tools — Claude cannot find it, falls back to alternative behavior
Expected Behavior
Tools from plugin-registered MCP servers should be available to the AI in the same way as tools from user-registered servers.
Actual Behavior
claude mcp listshowsplugin:context-mode:context-mode: ✓ Connected- The server responds correctly to
tools/list(11 tools returned, verified by direct MCP handshake test) - Plugin hooks fire correctly (session DB shows events written by PreToolUse, PostToolUse, SessionStart hooks)
- But the tools never appear as deferred tools — ToolSearch returns nothing, the AI cannot call them
- The skill that wraps
ctx_doctorfalls back to a CLI subprocess instead of calling the MCP tool directly
Workaround
Register the same server manually:
claude mcp add --scope user my-server-name /path/to/bun -- /path/to/start.mjs
This writes to ~/.claude.json instead of relying on the plugin system. The tools immediately appear as callable in new sessions.
Evidence
Verified by direct comparison in the same environment:
| Registration method | claude mcp list | Tools callable by AI |
|---|---|---|
| Plugin plugin.json mcpServers | ✓ Connected | ✗ No |
| claude mcp add --scope user | ✓ Connected | ✓ Yes |
The server binary, command, and args are identical in both cases. The only difference is how the registration is recorded.
Impact
Any plugin that provides an MCP server is affected. Users have to manually re-register the server via claude mcp add to get tool access, and must manually update the hardcoded version path after each plugin upgrade since the plugin system's auto-update doesn't touch ~/.claude.json.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗