Cursor CLI 2026.04.17-787b533: MCP tools disappear from toolset in -p mode when multiple stdio MCP servers are configured (race condition)

,

Where does the bug appear (feature/product)?

Cursor CLI

Describe the Bug

Summary

In Cursor CLI 2026.04.17-787b533, running agent -p --approve-mcps … with multiple stdio MCP servers configured in .cursor/mcp.json intermittently delivers an empty MCP toolset to the model even though every server reports ready via agent mcp list and all tools are visible via agent mcp list-tools . Version 2026.04.15-dccdccd does not exhibit this behaviour with the same configuration.

The symptom is: the model answers “I don’t see that tool in my functions” for any tool provided by one of the slower-to-initialize MCP servers, and falls back to FetchMcpResource / WebFetch. The only reliable workaround today is pinning to 04.15.

This matches the regression profile of anthropics/claude-code#43298 (deferred tool list frozen before MCP connections complete) but the bug is still present for local stdio servers in the Cursor CLI build.

Steps to Reproduce

Minimal reproduction

Two stdio MCP servers, both local. One is a trivial “fast” Python MCP that exposes a single tool and responds instantly. One is a trivial “slow” Python MCP that responds identically but with a configurable sleep before the loop starts.

fast_mcp.py (both roles; FAST_MCP_DELAY_MS controls startup sleep):

#!/usr/bin/env python3
import json, os, sys
if int(os.environ.get(“FAST_MCP_DELAY_MS”, “0”)) > 0:
import time; time.sleep(int(os.environ[“FAST_MCP_DELAY_MS”]) / 1000)
NAME = os.environ.get(“TOOL_NAME”, “fast_ping”)
def resp(o): sys.stdout.write(json.dumps(o)+“\n”); sys.stdout.flush()
for line in sys.stdin:
try: r = json.loads(line.strip() or “{}”)
except Exception: continue
mid, m = r.get(“id”), r.get(“method”,“”)
if m == “initialize”:
resp({“jsonrpc”:“2.0”,“id”:mid,“result”:{“protocolVersion”:“2024-11-05”,“capabilities”:{“tools”:{“listChanged”:False}},“serverInfo”:{“name”:NAME,“version”:“0.1”}}})
elif m == “notifications/initialized”: pass
elif m == “tools/list”:
resp({“jsonrpc”:“2.0”,“id”:mid,“result”:{“tools”:[{“name”:NAME,“description”:“Return PONG”,“inputSchema”:{“type”:“object”,“properties”:{}}}]}})
elif m == “tools/call”:
resp({“jsonrpc”:“2.0”,“id”:mid,“result”:{“content”:[{“type”:“text”,“text”:f"PONG from {NAME}“}]}})
elif m in (“resources/list”,“prompts/list”):
resp({“jsonrpc”:“2.0”,“id”:mid,“result”:{m.split(”/")[0]:}})
else:
resp({“jsonrpc”:“2.0”,“id”:mid,“error”:{“code”:-32601,“message”:“Method not found”}})

.cursor/mcp.json:

{
“mcpServers”: {
“fast-a”: { “command”: “python3”, “args”: [“fast_mcp.py”], “env”: {“TOOL_NAME”:“tool_a”} },
“fast-b”: { “command”: “python3”, “args”: [“fast_mcp.py”], “env”: {“TOOL_NAME”:“tool_b”,“FAST_MCP_DELAY_MS”:“1500”} }
}
}

Run:

agent -p --model auto --force --trust --approve-mcps --output-format json
“Call fast-a-tool_a and return its output verbatim. If no such tool, say NO_TOOL.”

Observed

With a single server (fast-a alone) — always returns PONG from tool_a.

With fast-a + fast-b the outcome becomes non-deterministic and depends on fast-b’s startup delay:

FAST_MCP_DELAY_MS of fast-b

Outcome across 3 runs

0

3/3 OK (tool_a called)

500

1/3 OK, 2/3 NO_TOOL

1000

1/3 OK, 2/3 NO_TOOL

2000

1/3 OK, 2/3 NO_TOOL

The same matrix on CLI 2026.04.15-dccdccd: 3/3 OK across all delays (including 5000ms). Note the non-monotonicity — 0ms is always safe, but from ~500ms up it becomes flaky; this is typical of a race condition, not a simple timeout threshold.

Impact

Any .cursor/mcp.json that mixes fast- and slow-starting stdio MCP servers is affected. Real-world servers that routinely take 1–3 seconds to reach tools/list (Python + FastMCP + auth, npx-based JavaScript servers) intermittently disappear from the toolset, even though agent mcp list shows them as ready and agent mcp list-tools returns the full schema. The model then behaves as if those tools do not exist (falls back to WebFetch, returns “no such tool” answers, etc.).

All of the obvious workarounds do not help:

sleep N in the prompt

retrying (–resume, fresh session, new workspace)

varying --force, --yolo, --sandbox enabled/disabled, --model

explicit --workspace

–approve-mcps (auto-approval succeeds, tools still missing)

filtering a server’s tool set via its own ENABLED_TOOLS-style env

The only reliable fix is staying on 2026.04.15-dccdccd.

Suggested fix

Wait for all stdio MCP initialize → tools/list round-trips to complete (with a configurable hard timeout) before sealing the toolset in -p mode, the same way interactive mode does.

Or expose a --wait-for-mcp[=timeout] flag so operators can opt in explicitly.

In the meantime, document the race in MCP | Cursor Docs so that users hitting 04.17 regressions don’t spend a day bisecting.

Operating System

Linux

Version Information

CLI: 2026.04.17-787b533 (regression). 2026.04.15-dccdccd is fine.

Model: reproduced on auto, claude-4.6-sonnet-medium, claude-opus-4-7-medium.

OS: Linux x86_64 and linux/arm64 (docker image python:3.12-slim).

Auth: CURSOR_API_KEY from env.

Tier: Team.

Does this stop you from using Cursor

Yes - Cursor is unusable

Hey,
Thanks for the thorough bug report — the minimal reproduction, version comparison matrix, and bisection to the 04.17 build are extremely helpful.

We’ve confirmed this is a real regression introduced in the 04.17 CLI build. When multiple stdio MCP servers are configured and one takes longer to initialize, there’s a race condition where the toolset can be sealed before all servers have completed their tools/list round-trip.

We were able to reproduce this on our end using your exact setup: with a 3-second delay on the second server, 4 out of 5 runs returned NO_TOOL instead of calling the tool correctly. Single-server setups work 100% of the time, confirming the race is specific to multi-server configurations.

Our team is aware of this and working on a fix. In the meantime, pinning to 2026.04.15-dccdccd as you’ve been doing is the right workaround.

We’ll update this thread once a fix ships. Thanks again for the detailed report — it made tracking this down much faster.