ACP agent silently ignores mcpServers in session/new

,

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

  1. Is dynamic MCP server attachment via session/new planned for a future agent release?
  2. Is the loadSession: true capability intentionally advertised, or is it premature?
  3. 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

Hey, thanks for the report.

I checked locally and can confirm. Also, the issue is broader: the static ~/.cursor/mcp.json isn’t picked up in agent acp either. I have about 17 servers in the config, and the agent doesn’t see any of them.

  • Dynamic mcpServers in session/new: accepted silently, but no connection happens
  • Static config: not loaded either
  • session/load: returns “Invalid params”, even though loadSession: true is listed

On your questions: dynamic MCP and loadSession aren’t implemented yet, even though the capabilities say they are. It’s related to this thread about MCP in the IDE agent (The Agent cannot access the MCP Servers configured in Cursor Settings), but it’s a separate issue since that’s IDE and this is ACP mode.

There’s no workaround for MCP in ACP right now. I’ve passed it to the team, no ETA yet.

2 Likes

Hi, thanks so much for the prompt investigation and follow up! Do keep me posted.

Thanks,

Dave

Hi @deanrie , just checking in. Any word on an ETA for this issue? Thanks so much again for all your help.

Thanks,

Dave

Just want to add one more request for this :slight_smile:

2 Likes

Hey @dherman no ETA yet, unfortunately. The issue is logged and the team is aware, but I can’t share a specific timeline. A few users are reporting something similar, so that helps with prioritization.

I’ll update the thread when I have news.

Another request for this :melting_face: this has become a blocker for my project

I kind of worked it around by writing CLI to MCP gateway and translating all MCP calls to CLI API, exposing to Cursor via skills.md, but now the gateway tool had to take care of MCP management and corp auth.

Hope it gets fixed soon.