Where does the bug appear (feature/product)?
Cursor CLI
Describe the Bug
The Cursor ACP agent (agent acp) silently ignores mcpServers passed in session/new. It accepts the request without error but never connects to any of the specified MCP servers — neither stdio nor HTTP. The agent then responds to prompts without access to the registered tools.
This appears related to the agent cannot access the MCP servers configured in Cursor settings, but affects the ACP programmatic interface specifically.
Environment
- Cursor agent version:
2026.02.27-e7d2ef6(agent --version) - OS: macOS (Darwin 24.6.0)
- Node.js: v24.12.0 (but the repro works with Node 18+)
The Problem
The ACP spec says:
Agents SHOULD connect to all MCP servers specified by the Client.
The Cursor agent advertises MCP support in its initialize response:
{
"agentCapabilities": {
"mcpCapabilities": { "http": true, "sse": true },
"loadSession": true
}
}
But when mcpServers are included in session/new, the agent:
- Returns a valid
sessionId(no error) - Never spawns the stdio MCP server process
- Never sends an HTTP request to the HTTP MCP server
- Responds to prompts saying it has no access to MCP tools
What I’ve Already Tested
I tested this systematically across all transport types and API methods:
| Test | Result |
|---|---|
session/new with type: "stdio" |
Accepted, server never spawned |
session/new with type: "http" |
Accepted, no HTTP request |
session/new with type: "sse" |
Accepted, no HTTP request |
session/load with various param combos |
All return “Invalid params” |
The agent advertises loadSession: true and mcpCapabilities: { http: true, sse: true } in its initialize response, but neither feature works.
Impact
This blocks any ACP client from providing dynamic MCP tools to the Cursor agent. The only workaround is statically configuring MCP servers in ~/.cursor/mcp.json, which defeats the purpose of the ACP mcpServers field.
Questions for the team
- Is dynamic MCP server attachment via
session/newplanned for a future agent release? - Is the
loadSession: truecapability intentionally advertised, or is it premature? - Is this related to the broader MCP-in-Agent regression reported in this thread?
Steps to Reproduce
Minimal Reproduction
Two files, zero dependencies. Requires Node.js 18+ and the Cursor agent CLI.
mcp-server.mjs — a minimal stdio MCP server with one tool:
#!/usr/bin/env node
import { appendFileSync } from "node:fs";
import { createInterface } from "node:readline";
const MARKER = "/tmp/cursor-mcp-repro-marker.log";
const log = (msg) => appendFileSync(MARKER, msg + "\n");
log("MCP server started PID=" + process.pid);
const rl = createInterface({ input: process.stdin });
rl.on("line", (line) => {
const msg = JSON.parse(line);
if (msg.method === "initialize") {
respond(msg.id, {
protocolVersion: "2024-11-05",
capabilities: { tools: { listChanged: false } },
serverInfo: { name: "repro-tools", version: "1.0.0" },
});
} else if (msg.method === "tools/list") {
respond(msg.id, {
tools: [{ name: "ping", description: "Returns pong",
inputSchema: { type: "object", properties: {} } }],
});
} else if (msg.method === "tools/call") {
respond(msg.id, { content: [{ type: "text", text: "pong!" }] });
}
});
function respond(id, result) {
process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result }) + "\n");
}
repro.mjs — spawns agent acp, registers the MCP server, and checks if it connects:
#!/usr/bin/env node
import { spawn } from "node:child_process";
import { createServer } from "node:http";
import { existsSync, unlinkSync } from "node:fs";
import { createInterface } from "node:readline";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const MCP_SERVER = resolve(__dirname, "mcp-server.mjs");
const MARKER = "/tmp/cursor-mcp-repro-marker.log";
// HTTP listener — just detects whether the agent connects
let httpHit = false;
const httpServer = createServer((req, res) => {
httpHit = true;
console.log(`[http] ${req.method} ${req.url}`);
res.writeHead(200).end("{}");
});
await new Promise(r => httpServer.listen(0, "127.0.0.1", r));
const httpPort = httpServer.address().port;
// Spawn agent and talk raw JSON-RPC
if (existsSync(MARKER)) unlinkSync(MARKER);
const proc = spawn("agent", ["acp"], { stdio: ["pipe", "pipe", "pipe"] });
const responses = new Map();
const chunks = [];
createInterface({ input: proc.stdout }).on("line", (line) => {
try {
const msg = JSON.parse(line);
if (msg.id != null) responses.set(msg.id, msg);
if (msg.params?.update?.type === "agent_message_chunk")
chunks.push(msg.params.update.textDelta ?? "");
} catch {}
});
const send = (id, method, params) =>
proc.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
const wait = (id, ms = 15000) => new Promise((ok, fail) => {
const iv = setInterval(() => {
if (responses.has(id)) { clearInterval(iv); clearTimeout(t); ok(responses.get(id)); }
}, 50);
const t = setTimeout(() => { clearInterval(iv); fail(new Error("timeout")); }, ms);
});
// 1. Initialize
send(1, "initialize", { protocolVersion: 1, clientCapabilities: {} });
const init = await wait(1);
console.log("Capabilities:", JSON.stringify(init.result?.agentCapabilities?.mcpCapabilities));
// 2. Create session with stdio + HTTP MCP servers
send(2, "session/new", {
cwd: process.cwd(),
mcpServers: [
{ type: "stdio", name: "repro-stdio", command: process.execPath,
args: [MCP_SERVER], env: [] },
{ type: "http", name: "repro-http",
url: `http://127.0.0.1:${httpPort}`, headers: [] },
],
});
const session = await wait(2);
// 3. Wait for potential MCP connections
await new Promise(r => setTimeout(r, 5000));
console.log(`stdio MCP spawned: ${existsSync(MARKER) ? "YES" : "NO"}`);
console.log(`HTTP MCP contacted: ${httpHit ? "YES" : "NO"}`);
// 4. Ask agent to use the tool
send(3, "session/prompt", {
sessionId: session.result.sessionId,
prompt: [{ type: "text", text: "Use the ping tool. If unavailable, say NO_PING_TOOL." }],
});
await wait(3, 30000);
await new Promise(r => setTimeout(r, 1000));
console.log("Agent reply:", chunks.join("").slice(0, 300));
proc.kill();
httpServer.close();
Run: node repro.mjs
Expected Behavior
Capabilities: {"http":true,"sse":true}
stdio MCP spawned: YES
HTTP MCP contacted: YES
Agent reply: pong!
Operating System
MacOS
Version Information
- Cursor agent version:
2026.02.27-e7d2ef6(agent --version) - OS: macOS (Darwin 24.6.0)
- Node.js: v24.12.0 (but the repro works with Node 18+)
For AI issues: which model did you use?
Opus 4.6
Does this stop you from using Cursor
Yes - Cursor is unusable