Where does the bug appear (feature/product)?
Cursor CLI
Describe the Bug
MCP servers passed via session/new don’t work in ACP mode. The approval middleware blocks them silently, and there’s no ACP-compatible way to approve.
--approve-mcpsis not wired to ACP (only affects the interactive CLI path)--yolo/--forcebypasses tool permissions but not MCP approval
Steps to Reproduce
You can pre-create the approval file. The key is ${name}-${sha256(JSON.stringify({path: cwd, server: {url}})).hex.slice(0, 16)}, written to ~/.cursor/projects/<slug>/mcp-approvals.json where slug is the cwd with non-alphanum replaced by -.
curl https://cursor.com/install -fsS | bash
npm install @agentclientprotocol/sdk
Run below as node connect-mcp-server.mjs:
import * as acp from "@agentclientprotocol/sdk";
import { spawn } from "node:child_process";
import { mkdirSync, writeFileSync, realpathSync } from "node:fs";
import { join } from "node:path";
import { tmpdir, homedir } from "node:os";
import { Readable, Writable } from "node:stream";
import { createHash } from "node:crypto";
const mcpUrl = "https://mcp.kiwi.com";
const mcpName = "kiwi";
const cwd = realpathSync(mkdirSync(join(tmpdir(), `cursor-mcp-${Date.now()}`), { recursive: true }) || join(tmpdir(), `cursor-mcp-${Date.now()}`));
// pre-approve the MCP server
const slug = cwd.replace(/[^A-Za-z0-9]+/g, "-").replace(/^-|-$/g, "");
const hash = createHash("sha256").update(JSON.stringify({ path: cwd, server: { url: mcpUrl } })).digest("hex").substring(0, 16);
const projectDir = join(homedir(), ".cursor", "projects", slug);
mkdirSync(projectDir, { recursive: true });
writeFileSync(join(projectDir, "mcp-approvals.json"), JSON.stringify([`${mcpName}-${hash}`]));
const child = spawn("cursor-agent", ["acp"], { stdio: ["pipe", "pipe", "inherit"] });
const stream = acp.ndJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout));
let toolCalled = false;
const client = new acp.ClientSideConnection(() => ({
sessionUpdate: async (p) => { if (p.update.sessionUpdate === "tool_call" && p.update.title?.includes("kiwi")) toolCalled = true; },
requestPermission: async (p) => ({ outcome: { outcome: "selected", optionId: p.options.find((o) => o.kind === "allow_once")?.optionId || p.options[0]?.optionId } }),
}), stream);
await client.initialize({ protocolVersion: acp.PROTOCOL_VERSION, clientCapabilities: { fs: { readTextFile: false, writeTextFile: false } }, clientInfo: { name: "test", version: "1.0.0" } });
const { sessionId } = await client.newSession({ cwd, mcpServers: [{ type: "http", name: mcpName, url: mcpUrl, headers: [] }] });
await client.prompt({ sessionId, prompt: [{ type: "text", text: "Use kiwi to search for flights from BKI to SYD tomorrow." }] });
console.log(`Kiwi tool called: ${toolCalled ? "YES" : "NO"}`);
child.kill(); process.exit(0);
With the pre-approval: Kiwi tool called: YES. Without it: agent says kiwi tools don’t exist.
Expected Behavior
Clients shouldn’t have to reverse-engineer the approval key format. Ideally either:
- Wire
--approve-mcpsto ACP (it already works in interactive CLI) - Auto-approve servers the client explicitly passes in
session/new - Have
--yoloalso bypass MCP approval, not just tool permissions
Operating System
MacOS
Version Information
2026.02.27-e7d2ef6
Additional Information
Does this stop you from using Cursor
Sometimes - I can sometimes use Cursor