zai-org / zai-org/feedback

MCP tools silently disappear when a server exceeds the hardcoded 15-second startup budget

Open
#643 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

priority: P2
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

  1. 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.
  2. Open a fresh ZCode session.
  3. Wait for the slow server to connect successfully after 15 seconds.
  4. Ask ZCode to call one of the slow server tools.
  5. Inspect the mcp.startup.completed, mcp.server.connected, and mcp.tools.registered records 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.connected for 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.