跳转到内容

Gemini CLI伴侣插件:接口规范

最后更新:2025年9月15日

本文档定义了构建一个伴侣插件的合同,以启用Gemini CLI的IDE模式。对于VS Code,这些功能(本地差异比较、上下文感知)由官方扩展提供(市场)。此规范适用于希望为其他编辑器(如JetBrains IDEs、Sublime Text等)带来类似功能的贡献者。

Gemini CLI和IDE插件通过本地通信通道进行通信。

插件必须运行一个实现**模型上下文协议(MCP)**的本地HTTP服务器。

  • **协议:**服务器必须是一个有效的MCP服务器。如果可用的话,我们建议使用您选择的语言的现有MCP SDK。
  • **端点:**服务器应该公开一个单一端点(例如,/mcp)用于所有MCP通信。
  • 端口:服务器必须监听一个动态分配的端口(即,监听端口0)。

为了让Gemini CLI连接,它需要发现它正在运行的IDE实例以及您的服务器正在使用的端口。插件必须通过创建一个“发现文件”来促进这一点。

命令行界面如何找到文件: 命令行界面通过遍历进程树来确定其运行的IDE的进程ID(PID)。然后查找一个包含此PID的名称的发现文件。 文件位置: 文件必须创建在特定目录中:os.tmpdir()/gemini/ide/。如果不存在,您的插件必须创建此目录。 文件命名约定: 文件名至关重要,必须遵循以下模式:gemini-ide-server-${PID}-${PORT}.json

  • ${PID}:父IDE进程的进程ID。您的插件必须确定此PID并将其包含在文件名中。
  • ${PORT}:您的MCP服务器监听的端口。 文件内容和工作空间验证: 文件必须包含一个具有以下结构的JSON对象:
{
"port": 12345,
"workspacePath": "/path/to/project1:/path/to/project2",
"authToken": "a-very-secret-token",
"ideInfo": {
"name": "vscode",
"displayName": "VS Code"
}
}
  • port(数字,必填):MCP服务器的端口。
  • workspacePath(字符串,必填):所有打开的工作空间根路径列表,由操作系统特定的路径分隔符分隔(Linux/macOS为:,Windows为;)。命令行界面使用此路径确保其运行在与IDE中打开的同一项目文件夹中。如果命令行界面的当前工作目录不是workspacePath的子目录,连接将被拒绝。您的插件必须提供正确的、绝对路径到打开的工作空间根目录。
  • authToken(字符串,必填):用于保护连接的秘密令牌。命令行界面将在所有请求的Authorization: Bearer <token>头部包含此令牌。
  • ideInfo(对象,必填):有关IDE的信息。
    • name(字符串,必填):IDE的简短、小写标识符(例如,vscodejetbrains)。
    • displayName(字符串,必填):IDE的用户友好名称(例如,VS CodeJetBrains IDE)。

认证: 为了确保连接安全,插件必须生成一个唯一且保密的令牌,并将其包含在发现文件中。命令行界面(CLI)随后将在所有请求MCP服务器的请求头中包含这个令牌(例如,Authorization)。您的服务器必须对每个请求验证此令牌,并拒绝任何未经授权的请求。 使用环境变量解决冲突(推荐): 为了获得最可靠的体验,您的插件应该既创建发现文件,又在集成终端中设置GEMINI_CLI_IDE_SERVER_PORT环境变量。文件作为主要的发现机制,但环境变量对于解决冲突至关重要。如果用户为同一个工作空间打开了多个IDE窗口,CLI会使用GEMINI_CLI_IDE_SERVER_PORT变量来识别并连接到正确窗口的服务器。

为了启用上下文感知,插件可以向CLI提供关于用户在IDE中活动的实时信息。

插件可以在用户上下文发生变化时向CLI发送一个ide/contextUpdate通知。 通知

  • 触发事件: 此通知应在以下情况下发送(建议使用50ms的防抖动):

    • 打开、关闭或聚焦文件。
    • 用户在活动文件中的光标位置或文本选择发生变化。
  • 负载(IdeContext): 通知参数必须是一个IdeContext对象:

    interface IdeContext {
    workspaceState?: {
    openFiles?: File[];
    isTrusted?: boolean;
    };
    }
    interface File {
    // Absolute path to the file
    path: string;
    // Last focused Unix timestamp (for ordering)
    timestamp: number;
    // True if this is the currently focused file
    isActive?: boolean;
    cursor?: {
    // 1-based line number
    line: number;
    // 1-based character number
    character: number;
    };
    // The text currently selected by the user
    selectedText?: string;
    }

    注意: openFiles 列表应只包含磁盘上存在的文件。虚拟文件(例如,没有路径且未保存的文件,编辑器设置页面)必须被排除。

(以下部分未提供英文原文,故无法翻译。)

在接收到IdeContext对象后,CLI 会执行几个标准化和截断步骤,然后再将信息发送给模型。

  • 文件排序: CLI 使用timestamp字段来确定最近使用的文件。它根据这个值对openFiles列表进行排序。因此,您的插件必须为文件最后一次聚焦时提供一个准确的 Unix 时间戳。
  • 活动文件: CLI 仅将排序后最新的文件视为“活动”文件。它会忽略其他所有文件的isActive标志,并清除它们的cursorselectedText字段。您的插件应专注于设置isActive: true,并仅为当前聚焦的文件提供光标/选择详情。
  • 截断: 为了管理令牌限制,CLI 会将文件列表(截断为10个文件)和selectedText(截断为16KB)进行截断。

虽然 CLI 负责最后的截断,但强烈建议您的插件也限制发送的上下文量。

为了启用交互式代码修改,插件可以暴露一个差异比较接口。这允许 CLI 请求 IDE 打开一个差异视图,显示对文件的拟议更改。用户可以在 IDE 中直接查看、编辑并最终接受或拒绝这些更改。

插件必须在其 MCP 服务器上注册一个openDiff工具。

  • 描述: 此工具指示 IDE 为特定文件打开一个可修改的差异视图。

  • 请求(OpenDiffRequest): 通过tools/call请求调用该工具。请求的params中的arguments字段必须是一个OpenDiffRequest对象。

    interface OpenDiffRequest {
    // The absolute path to the file to be diffed.
    filePath: string;
    // The proposed new content for the file.
    newContent: string;
    }

响应 (CallToolResult): 工具 必须 立即返回一个 CallToolResult 以确认请求并报告差异视图是否成功打开。

  • 成功时:如果差异视图成功打开,响应 必须 包含空内容(即 content: [])。
  • 失败时:如果错误阻止了差异视图的打开,响应 必须isError: true 并在 content 数组中包含一个 TextContent 块来描述错误。

差异的实际结果(接受或拒绝)是通过通知异步传递的。

插件 必须 在其MCP服务器上注册一个 closeDiff 工具。

  • 描述: 此工具指示IDE关闭特定文件的打开差异视图。

  • 请求 (CloseDiffRequest): 通过 tools/call 请求调用工具。请求的 params 中的 arguments 字段 必须 是一个 CloseDiffRequest 对象。

    interface CloseDiffRequest {
    // The absolute path to the file whose diff view should be closed.
    filePath: string;
    }
  • 响应 (CallToolResult): 工具 必须 返回一个 CallToolResult

    • 成功时:如果差异视图成功关闭,响应 必须 在内容数组中包含一个单独的 TextContent 块,其中包含关闭前文件的最终内容。
    • 失败时:如果错误阻止了差异视图的关闭,响应 必须isError: true 并在 content 数组中包含一个 TextContent 块来描述错误。

当用户在差异视图中接受更改(例如,通过点击“应用”或“保存”按钮)时,插件 必须 向CLI发送一个 ide/diffAccepted 通知。

  • 有效载荷: 通知参数 必须 包括文件路径和文件的最终内容。如果用户在差异视图中进行了手动编辑,内容可能与原始 newContent 不同。

    {
    // The absolute path to the file that was diffed.
    filePath: string;
    // The full content of the file after acceptance.
    content: string;
    }

当用户拒绝更改(例如,在不接受的情况下关闭差异视图),插件必须向 CLI 发送一个 ide/diffRejected 通知。

  • 负载:通知参数必须包括被拒绝差异的文件路径。

    {
    // The absolute path to the file that was diffed.
    filePath: string;
    }

插件必须根据 IDE 的生命周期正确管理其资源和发现文件。

  • 激活时(IDE 启动/插件启用):
    1. 启动 MCP 服务器。
    2. 创建发现文件。
  • 停用时(IDE 关闭/插件禁用):
    1. 停止 MCP 服务器。
    2. 删除发现文件。