MCP tools silently disappear when a server exceeds the hardcoded 15-second startup budget
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
Environment
- ZCode 3.11.2 (build 3.11.2.6792)
- macOS 26.6.2 (25G83), Apple silicon
- ZCode Agent
- 21 configured MCP servers: 13 enabled and 8 disabled
Steps to reproduce
- Configure several enabled MCP servers so that they start concurrently, including one stdio-backed remote MCP route whose initialise and tools/list handshake can take longer than 15 seconds under cold concurrent load.
- Open a fresh ZCode session.
- Wait for the slow server to connect successfully after 15 seconds.
- Ask ZCode to call one of the slow server tools.
- Inspect the
mcp.startup.completed,mcp.server.connected, andmcp.tools.registeredrecords in the ZCode JSONL log.
Expected behaviour
Every enabled server that connects successfully has its tools registered for the session. If startup must have a deadline, it should be configurable per server or a late successful connection should trigger tool registration.
Actual behaviour
ZCode completes MCP startup at the hardcoded 15-second boundary while the slow route is still connecting. The route then connects successfully, but its tools never become available because registration runs only once.
One captured session shows:
mcp.startup.completed:durationMs: 15010,statusCounts: {connected: 12, disabled: 8, connecting: 1},toolCount: 99- 1.4 seconds later,
mcp.server.connectedfor the slow route:durationMs: 16399,toolCount: 74 mcp.tools.registered:registeredToolCount: 99
A comparison session where the same route completed at 12.294 seconds registered 173 tools, exactly 99 + 74.
The route itself is healthy: an isolated MCP initialise probe succeeds in approximately 4.5 to 6.5 seconds. The failure appears only under cold concurrent startup load.
Runtime evidence
In /Applications/ZCode.app/Contents/Resources/glm/zcode.cjs, ZCode 3.11.2 sets yci=15e3 and passes it as oauthAuthorizationTimeoutMs to connectConfiguredServers.
waitForSharedConnection races the in-flight connection against setTimeout. When the timer wins, it returns the current status, which is still connecting with an empty tools array. The connection continues and later logs success, but the session does not perform another tools registration pass.
The same option is not exposed as an MCP configuration key, and a per-server transport timeout controls a different deadline.
Impact
A healthy managed MCP server can silently lose all of its tools for an entire session depending on cold-start contention. There is no visible connection failure once the server finishes, so the user and agent see an incomplete toolset with no recovery short of opening another session.
Suggested remedies
Any of these would address the runtime ownership side:
- make the bootstrap budget configurable, ideally per server;
- wait for enabled servers up to their declared startup timeout;
- register tools when a late server reaches
connected; - visibly fail or offer retry when startup settles with enabled routes still
connecting.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with /Applications/ZCode.app/Contents/Resources/glm/zcode.cjs and inspect connectConfiguredServers, waitForSharedConnection, and the one-time tools registration path. Compare the mcp.startup.completed and late mcp.server.connected records in the JSONL log; done means a server connecting after the startup boundary has its tools registered or the incomplete startup is visibly reported with recovery.
Written by the indexing model from the issue text.
Assessment
- Domain
- backend-api-design, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100