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