SessionStart hooks with mcp_tool type fire before MCP servers connect
Description
Plugin SessionStart hooks that use type: "mcp_tool" always fail because they fire before the MCP server has connected. The hooks execute synchronously during startup, and MCP connection begins ~290ms later. Every mcp_tool hook gets skipped with "MCP server not connected."
Steps to Reproduce
- Create a plugin with
hooks/hooks.jsoncontaining SessionStart hooks that call MCP tools:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "mcp_tool",
"server": "concurai-ememory",
"tool": "e_property",
"input": { "action": "list" },
"timeout": 30
}
]
}
]
}
}
- Plugin has
.mcp.jsonconfiguring an HTTP MCP server - Launch Claude Code with
--plugin-dir
Expected Behavior
SessionStart hooks with type: "mcp_tool" should execute after the MCP server they reference has connected, or Claude Code should provide an McpReady hook event that fires after MCP connections are established.
Actual Behavior
All mcp_tool hooks are skipped with warning: Hooks: mcp_tool hook skipped — MCP server 'concurai-ememory' not connected
Debug log shows the timing gap clearly:
2026-05-11T01:45:08.907Z [WARN] Hooks: mcp_tool hook skipped — MCP server 'concurai-ememory' not connected
2026-05-11T01:45:08.907Z [WARN] Hooks: mcp_tool hook skipped — MCP server 'concurai-ememory' not connected
2026-05-11T01:45:08.907Z [WARN] Hooks: mcp_tool hook skipped — MCP server 'concurai-ememory' not connected
2026-05-11T01:45:08.907Z [WARN] Hooks: mcp_tool hook skipped — MCP server 'concurai-ememory' not connected
2026-05-11T01:45:08.921Z [DEBUG] MCP server "plugin:concurai-ememory:concurai-ememory": Starting connection...
2026-05-11T01:45:09.197Z [DEBUG] MCP server "plugin:concurai-ememory:concurai-ememory": Successfully connected (transport: http) in 280ms
Hooks fire at .907, MCP connection starts at .921 and completes at .197 — hooks never had a chance.
Use Case
Session memory continuity. Our plugin uses SessionStart hooks to restore context from a knowledge store on startup (orient), on context compaction (restore session state), and on resume (cross-session context). These are the primary use cases for mcp_tool hooks — they're useless if they can't call the MCP server they depend on.
Suggested Fix
Either:
- Wait for MCP connections before firing SessionStart hooks that reference MCP tools
- Add an
McpReadyhook event that fires after all MCP servers have connected - Retry
mcp_toolhooks that fail due to server not connected (with backoff)
Environment
- Claude Code v2.1.138
- macOS (Darwin 25.3.0)
- MCP transport: HTTP (Streamable HTTP)
- Plugin loaded via
--plugin-dir
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗