《Cursor文檔》-ACP

概述

Cursor 命令行界面支持用於高級集成的 ACP (智能體客戶端協議) 。您可以運行 agent acp,並通過 JSON-RPC 在 stdio 上連接自定義客戶端。

更多信息請參閱官方 智能體客戶端協議文檔

ACP 旨在用於構建自定義客戶端和集成。對於常規終端
工作流,請使用帶 agent 的交互式命令行界面。

啓動 ACP 服務器

以 ACP 模式啓動 Cursor 命令行界面:

agent acp

傳輸與消息格式

  • 傳輸方式:stdio
  • 協議封裝:JSON-RPC 2.0
  • 分幀:以換行符分隔的 JSON (每行一條消息)
  • 方向:
  • 客戶端將請求/通知寫入 stdin
  • Cursor 命令行界面將響應/通知寫入 stdout
  • 日誌可能會寫入 stderr

請求流程

典型的 ACP 會話流程:

  1. initialize
  2. 使用 methodId: "cursor_login" 執行 authenticate
  3. session/new (或 session/load)
  4. session/prompt
  5. 在模型流式輸出期間處理 session/update 通知
  6. 通過返回決策處理 session/request_permission
  7. 可選:發送 session/cancel

認證

Cursor 命令行界面將 cursor_login 作爲 ACP 認證方法提供。實際上,你可以在啓動前通過現有的 CLI 認證方式預先完成認證:

  • agent login
  • --api-key (或 CURSOR_API_KEY)
  • --auth-token (或 CURSOR_AUTH_TOKEN)

你還可以通過根 CLI 命令傳入端點和 TLS 選項:

agent --api-key "$CURSOR_API_KEY" acp
agent -e https://api2.cursor.sh acp
agent -k acp

會話、模式與權限

會話

  • 使用 session/new 創建會話
  • 使用 session/load 恢復現有會話

模式

ACP 會話支持與命令行界面 (CLI) 相同的核心模式:

  • agent (完整工具訪問權限)
  • plan (規劃模式,僅可讀取)
  • ask (問答模式,僅可讀取)

權限

當工具需要獲得批准時,Cursor 會發送 session/request_permission。客戶端應返回以下選項之一:

  • allow-once
  • allow-always
  • reject-once

如果客戶端未響應權限請求,工具執行可能會被阻塞。

MCP 服務器

ACP 支持使用項目級或用戶級 .cursor/mcp.json 中定義的 MCP 服務器。在項目目錄中啓動 agent,然後批准要使用的服務器。

ACP 模式不支持通過 Cursor 儀表盤配置的團隊級 MCP 服務器。

Cursor 擴展方法

Cursor 會發送 ACP 擴展方法,以提供更豐富的客戶端體驗。分爲兩類:

  • 阻塞方法 (cursor/ask_questioncursor/create_plan):智能體會等待響應後再繼續。客戶端必須返回 JSON-RPC 響應。
  • 通知方法 (cursor/update_todoscursor/taskcursor/generate_image):智能體會以即發即棄的方式發送這些通知。客戶端可以顯示這些通知,但無需響應。
方法 類型 用途
cursor/ask_question 阻塞 向用戶提出多項選擇題
cursor/create_plan 阻塞 請求明確批准方案
cursor/update_todos 通知 通知客戶端待辦事項狀態更新
cursor/task 通知 通知客戶端子智能體任務已完成
cursor/generate_image 通知 通知客戶端已生成圖像輸出

cursor/ask_question

向用戶展示多項選擇題。智能體會一直阻塞,直到客戶端作出響應。

請求:

interface CursorAskQuestionRequest {
  toolCallId: string;
  title?: string;
  questions: Array<{
    id: string;
    prompt: string;
    options: Array<{ id: string; label: string }>;
    allowMultiple?: boolean;
  }>;
}

響應:

interface CursorAskQuestionResponse {
  outcome:
    | {
        outcome: "answered";
        answers: Array<{
          questionId: string;
          selectedOptionIds: string[];
        }>;
      }
    | { outcome: "skipped"; reason?: string }
    | { outcome: "cancelled" };
}

請求示例:

{
  "toolCallId": "call_123",
  "title": "Need input",
  "questions": [
    {
      "id": "q1",
      "prompt": "Which mode should I use?",
      "options": [
        { "id": "agent", "label": "Agent" },
        { "id": "plan", "label": "Plan" }
      ],
      "allowMultiple": false
    }
  ]
}

cursor/create_plan

請求用戶批准方案。智能體會阻塞,直到客戶端接受或拒絕該方案。

請求:

interface CursorCreatePlanRequest {
  toolCallId: string;
  name?: string;
  overview?: string;
  plan: string;
  todos: Array<{
    id: string;
    content: string;
    status: "pending" | "in_progress" | "completed" | "cancelled";
  }>;
  isProject?: boolean;
  phases?: Array<{
    name: string;
    todos: Array<{
      id: string;
      content: string;
      status: "pending" | "in_progress" | "completed" | "cancelled";
    }>;
  }>;
}
  • plan:描述完整方案的 markdown string。
  • phases:可選。對於較大的方案,可將 todos 按命名階段分組。

響應:

interface CursorCreatePlanResponse {
  outcome:
    | { outcome: "accepted"; planUri?: string }
    | { outcome: "rejected"; reason?: string }
    | { outcome: "cancelled" };
}

請求示例:

{
  "toolCallId": "call_124",
  "name": "Refactor tabs layout",
  "overview": "Tighten layout behavior and preserve existing UX.",
  "plan": "1. Inspect current tab sizing logic.\n2. Update layout calculations.\n3. Verify editor behavior.",
  "todos": [
    { "id": "todo-1", "content": "Inspect current tab sizing logic", "status": "completed" },
    { "id": "todo-2", "content": "Update layout calculations", "status": "in_progress" },
    { "id": "todo-3", "content": "Verify editor behavior", "status": "pending" }
  ],
  "isProject": false
}

cursor/update_todos

更新客戶端的待辦事項列表。以通知形式發送,無需響應。

請求:

interface CursorUpdateTodosRequest {
  toolCallId: string;
  todos: Array<{
    id: string;
    content: string;
    status: "pending" | "in_progress" | "completed" | "cancelled";
  }>;
  merge: boolean;
}
  • merge:若爲 true,將這些待辦事項合併到現有列表中;若爲 false,則替換整個列表。

響應:

interface CursorUpdateTodosResponse {
  outcome:
    | {
        outcome: "accepted";
        todos: Array<{
          id: string;
          content: string;
          status: "pending" | "in_progress" | "completed" | "cancelled";
        }>;
      }
    | { outcome: "rejected"; reason?: string }
    | { outcome: "cancelled" };
}

請求示例:

{
  "toolCallId": "call_125",
  "todos": [
    { "id": "1", "content": "Set up project structure", "status": "completed" },
    { "id": "2", "content": "Add authentication", "status": "in_progress" },
    { "id": "3", "content": "Write unit tests", "status": "pending" }
  ],
  "merge": true
}

cursor/task

向客戶端通知子智能體任務。以通知形式發送,無需響應。

請求:

interface CursorTaskRequest {
  toolCallId: string;
  description: string;
  prompt: string;
  subagentType:
    | "unspecified"
    | "computer_use"
    | "explore"
    | "video_review"
    | "browser_use"
    | "shell"
    | "vm_setup_helper"
    | { custom: string };
  model?: string;
  agentId?: string;
  durationMs?: number;
}
  • subagentType:要運行的子智能體類型。自定義子智能體類型請使用 { custom: "your_type" }
  • agentId:設置此項可恢復此前創建的子智能體。
  • durationMs:任務運行時長,包含在響應中。

響應:

interface CursorTaskResponse {
  outcome:
    | { outcome: "completed"; agentId?: string; durationMs?: number }
    | { outcome: "rejected"; reason?: string }
    | { outcome: "cancelled" };
}

請求示例:

{
  "toolCallId": "call_126",
  "description": "Explore codebase",
  "prompt": "Find where authentication is handled and report the file paths.",
  "subagentType": "explore"
}

cursor/generate_image

向客戶端通知已生成圖像。以通知形式發送;無需響應。

請求:

interface CursorGenerateImageRequest {
  toolCallId: string;
  description: string;
  filePath?: string;
  referenceImagePaths?: string[];
}
  • filePath:生成圖像的建議保存路徑。
  • referenceImagePaths:作爲輸入的參考圖像路徑。

響應:

interface CursorGenerateImageResponse {
  outcome:
    | { outcome: "generated"; filePath: string; imageData?: string }
    | { outcome: "rejected"; reason?: string }
    | { outcome: "cancelled" };
}

請求示例:

{
  "toolCallId": "call_127",
  "description": "Minimal flat app icon for a note-taking app",
  "filePath": "/tmp/icon.png",
  "referenceImagePaths": ["/tmp/reference.png"]
}

最簡 Node.js 客戶端

本示例展示自定義 ACP 客戶端的最小控制流程:

import { spawn } from "node:child_process";
import readline from "node:readline";

const agent = spawn("agent", ["acp"], { stdio: ["pipe", "pipe", "inherit"] });

let nextId = 1;
const pending = new Map();

function send(method, params) {
  const id = nextId++;
  agent.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
  return new Promise((resolve, reject) => pending.set(id, { resolve, reject }));
}

function respond(id, result) {
  agent.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, result }) + "\n");
}

const rl = readline.createInterface({ input: agent.stdout });
rl.on("line", line => {
  const msg = JSON.parse(line);

  if (msg.id && (msg.result || msg.error)) {
    const waiter = pending.get(msg.id);
    if (!waiter) return;
    pending.delete(msg.id);
    msg.error ? waiter.reject(msg.error) : waiter.resolve(msg.result);
    return;
  }

  if (msg.method === "session/update") {
    const update = msg.params?.update;
    if (update?.sessionUpdate === "agent_message_chunk" && update.content?.text) {
      process.stdout.write(update.content.text);
    }
    return;
  }

  if (msg.method === "session/request_permission") {
    respond(msg.id, { outcome: { outcome: "selected", optionId: "allow-once" } });
  }
});

const init = async () => {
  await send("initialize", {
    protocolVersion: 1,
    clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false },
    clientInfo: { name: "acp-minimal-client", version: "0.1.0" }
  });

  await send("authenticate", { methodId: "cursor_login" });
  const { sessionId } = await send("session/new", { cwd: process.cwd(), mcpServers: [] });
  const result = await send("session/prompt", {
    sessionId,
    prompt: [{ type: "text", text: "Say hello in one sentence." }]
  });

  console.log(`\n\n[stopReason=${result.stopReason}]`);
};

init().finally(() => {
  agent.stdin.end();
  agent.kill();
});

IDE 集成

ACP 讓 Cursor 的 AI 智能體能夠在 Cursor 桌面端應用以外的編輯器中工作。您可以爲偏好的開發環境構建或使用第三方集成。

使用示例

  • JetBrains IDEs — 將 IntelliJ IDEA、WebStorm、PyCharm 或其他 JetBrains IDE 連接到 Cursor 智能體。設置說明請參閱 JetBrains 集成指南

  • Neovim (avante.nvim) — 使用 avante.nvim 通過 ACP 將 Neovim 連接到 Cursor 智能體。請參閱下方的 Neovim 設置

  • Zed — 啓動 agent acp 並通過 stdio 通信,即可與 Zed 的現代編輯器集成。Zed 擴展可以實現 ACP 客戶端協議,將 AI 請求路由至 Cursor。

  • 自定義編輯器 — 任何支持擴展的編輯器都可以實現 ACP 客戶端。啓動智能體進程,通過 stdio 發送 JSON-RPC 消息,並在編輯器 UI 中處理響應。

Neovim (avante.nvim)

avante.nvim 是一款提供 AI 編程助手的 Neovim 插件。它支持 ACP,因此你可以將其連接到 Cursor 智能體,在 Neovim 中進行智能體編程。

在你的 lazy.nvim 插件配置中添加以下內容 (例如 ~/.config/nvim/lua/plugins/avante.lua) :

return {
  {
    "yetone/avante.nvim",
    event = "VeryLazy",
    version = false,
    build = "make",
    opts = {
      provider = "cursor",
      mode = "agentic",
      acp_providers = {
        cursor = {
          command = os.getenv("HOME") .. "/.local/bin/agent",
          args = { "acp" },
          auth_method = "cursor_login",
          env = {
            HOME = os.getenv("HOME"),
            PATH = os.getenv("PATH"),
          },
        },
      },
    },
    dependencies = {
      "nvim-lua/plenary.nvim",
      "MunifTanjim/nui.nvim",
      "nvim-tree/nvim-web-devicons",
      {
        "MeanderingProgrammer/render-markdown.nvim",
        opts = {
          file_types = { "markdown", "Avante" },
        },
        ft = { "markdown", "Avante" },
      },
    },
  },
}

關鍵設置:

  • provider:設爲 "cursor",將請求路由至 Cursor 的智能體。
  • mode:設爲 "agentic" 以獲得完整工具訪問權限 (文件編輯、終端命令) 。僅聊天模式請使用 "normal"
  • command:指向 agent 二進制文件。默認安裝路徑爲 ~/.local/bin/agent。如果安裝在其他位置,請相應調整。
  • auth_method:使用 "cursor_login"。請先在終端中運行 agent login 進行認證。

構建集成

  1. agent acp 作爲子進程啓動
  2. 通過 stdin/stdout 使用 JSON-RPC 進行通信
  3. 處理 session/update 通知以顯示流式響應
  4. 當工具需要批准時,響應 session/request_permission
  5. 可選擇實現 Cursor 擴展方法,以提供更豐富的用戶體驗

可參考上方的最簡 Node.js 客戶端,瞭解可運行的參考實現。

相關內容

CLI 中的 MCP

在 Cursor 命令行界面中管理和使用 MCP 服務器

MCP 概覽

瞭解 MCP 傳輸方式、配置及服務器設置

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜