主题
Gemini CLI 伴侣插件:接口规范
最后更新:2025 年 9 月 15 日
本文档定义了构建伴侣插件以启用 Gemini CLI IDE 模式的契约。对于 VS Code,这些功能(原生差异对比、上下文感知)由官方扩展提供(市场)。此规范适用于希望将类似功能带到其他编辑器(如 JetBrains IDE、Sublime Text 等)的贡献者。
I. 通信接口
Gemini CLI 和 IDE 插件通过本地通信通道进行通信。
1. 传输层:基于 HTTP 的 MCP
插件必须运行一个实现 Model Context Protocol (MCP) 的本地 HTTP 服务器。
- 协议: 服务器必须是有效的 MCP 服务器。如果可用,我们建议使用你选择语言的现有 MCP SDK。
- 端点: 服务器应为所有 MCP 通信公开单个端点(例如
/mcp)。 - 端口: 服务器必须监听动态分配的端口(即监听端口
0)。
2. 发现机制:端口文件
为了让 Gemini CLI 连接,它需要发现它正在运行的 IDE 实例以及你的服务器使用的端口。插件必须通过创建"发现文件"来促进这一点。
CLI 如何找到文件: CLI 通过遍历进程树确定它正在运行的 IDE 的进程 ID (PID)。然后它查找名称中包含此 PID 的发现文件。
文件位置: 文件必须在特定目录中创建:
os.tmpdir()/gemini/ide/。如果此目录不存在,你的插件必须创建它。文件命名约定: 文件名至关重要,必须遵循模式:
gemini-ide-server-${PID}-${PORT}.json${PID}:父 IDE 进程的进程 ID。你的插件必须确定此 PID 并将其包含在文件名中。${PORT}:你的 MCP 服务器正在监听的端口。
文件内容和工作区验证: 文件必须包含具有以下结构的 JSON 对象:
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 为;)。CLI 使用此路径确保它运行在 IDE 中打开的同一项目文件夹中。如果 CLI 的当前工作目录不是workspacePath的子目录,连接将被拒绝。你的插件必须提供打开工作区根目录的正确绝对路径。authToken(字符串,必需):用于保护连接的密钥令牌。CLI 将在所有请求的Authorization: Bearer <token>头中包含此令牌。ideInfo(对象,必需):关于 IDE 的信息。name(字符串,必需):IDE 的简短小写标识符(例如vscode、jetbrains)。displayName(字符串,必需):IDE 的用户友好名称(例如VS Code、JetBrains IDE)。
认证: 为保护连接,插件必须生成唯一的密钥令牌并将其包含在发现文件中。然后 CLI 将在对 MCP 服务器的所有请求的
Authorization头中包含此令牌(例如Authorization: Bearer a-very-secret-token)。你的服务器必须在每个请求上验证此令牌并拒绝任何未授权的请求。使用环境变量进行决胜(推荐): 为获得最可靠的体验,你的插件应该同时创建发现文件并在集成终端中设置
GEMINI_CLI_IDE_SERVER_PORT环境变量。文件作为主要发现机制,但环境变量对于决胜至关重要。如果用户为同一工作区打开了多个 IDE 窗口,CLI 使用GEMINI_CLI_IDE_SERVER_PORT变量来识别并连接到正确窗口的服务器。
II. 上下文接口
为启用上下文感知,插件可以向 CLI 提供关于用户在 IDE 中活动的实时信息。
ide/contextUpdate 通知
插件可以在用户上下文更改时向 CLI 发送 ide/contextUpdate 通知。
触发事件: 此通知应在以下情况下发送(建议 50ms 防抖):
- 文件被打开、关闭或聚焦。
- 用户在活动文件中的光标位置或文本选择更改。
负载(
IdeContext): 通知参数必须是IdeContext对象:typescriptinterface IdeContext { workspaceState?: { openFiles?: File[]; isTrusted?: boolean; }; } interface File { // 文件的绝对路径 path: string; // 最后聚焦的 Unix 时间戳(用于排序) timestamp: number; // 如果这是当前聚焦的文件则为 true isActive?: boolean; cursor?: { // 基于 1 的行号 line: number; // 基于 1 的字符号 character: number; }; // 用户当前选择的文本 selectedText?: string; }注意:
openFiles列表应只包含磁盘上存在的文件。虚拟文件(例如没有路径的未保存文件、编辑器设置页面)必须被排除。
CLI 如何使用此上下文
收到 IdeContext 对象后,CLI 在将信息发送给模型之前执行几个规范化和截断步骤。
- 文件排序: CLI 使用
timestamp字段确定最近使用的文件。它根据此值对openFiles列表进行排序。因此,你的插件必须提供文件最后聚焦时的准确 Unix 时间戳。 - 活动文件: CLI 只将最近的文件(排序后)视为"活动"文件。它将忽略所有其他文件上的
isActive标志并清除它们的cursor和selectedText字段。你的插件应专注于仅为当前聚焦的文件设置isActive: true并提供光标/选择详情。 - 截断: 为管理 token 限制,CLI 截断文件列表(到 10 个文件)和
selectedText(到 16KB)。
虽然 CLI 处理最终截断,但强烈建议你的插件也限制它发送的上下文量。
III. 差异接口
为启用交互式代码修改,插件可以公开差异接口。这允许 CLI 请求 IDE 打开差异视图,显示对文件的建议更改。然后用户可以直接在 IDE 中审查、编辑并最终接受或拒绝这些更改。
openDiff 工具
插件必须在其 MCP 服务器上注册 openDiff 工具。
描述: 此工具指示 IDE 为特定文件打开可修改的差异视图。
请求(
OpenDiffRequest): 工具通过tools/call请求调用。请求params中的arguments字段必须是OpenDiffRequest对象。typescriptinterface OpenDiffRequest { // 要进行差异对比的文件的绝对路径。 filePath: string; // 文件的建议新内容。 newContent: string; }响应(
CallToolResult): 工具必须立即返回CallToolResult以确认请求并报告差异视图是否成功打开。- 成功时:如果差异视图成功打开,响应必须包含空内容(即
content: [])。 - 失败时:如果错误阻止差异视图打开,响应必须具有
isError: true并在content数组中包含描述错误的TextContent块。
差异的实际结果(接受或拒绝)通过通知异步传达。
- 成功时:如果差异视图成功打开,响应必须包含空内容(即
closeDiff 工具
插件必须在其 MCP 服务器上注册 closeDiff 工具。
描述: 此工具指示 IDE 关闭特定文件的打开差异视图。
请求(
CloseDiffRequest): 工具通过tools/call请求调用。请求params中的arguments字段必须是CloseDiffRequest对象。typescriptinterface CloseDiffRequest { // 应关闭其差异视图的文件的绝对路径。 filePath: string; }响应(
CallToolResult): 工具必须返回CallToolResult。- 成功时:如果差异视图成功关闭,响应必须在内容数组中包含单个 TextContent 块,其中包含关闭前文件的最终内容。
- 失败时:如果错误阻止差异视图关闭,响应必须具有
isError: true并在content数组中包含描述错误的TextContent块。
ide/diffAccepted 通知
当用户接受差异视图中的更改(例如,通过点击"应用"或"保存"按钮)时,插件必须向 CLI 发送 ide/diffAccepted 通知。
负载: 通知参数必须包含文件路径和文件的最终内容。如果用户在差异视图中进行了手动编辑,内容可能与原始
newContent不同。typescript{ // 进行差异对比的文件的绝对路径。 filePath: string; // 接受后文件的完整内容。 content: string; }
ide/diffRejected 通知
当用户拒绝更改(例如,通过关闭差异视图而不接受)时,插件必须向 CLI 发送 ide/diffRejected 通知。
负载: 通知参数必须包含被拒绝差异的文件路径。
typescript{ // 进行差异对比的文件的绝对路径。 filePath: string; }
IV. 生命周期接口
插件必须根据 IDE 的生命周期正确管理其资源和发现文件。
- 激活时(IDE 启动/插件启用):
- 启动 MCP 服务器。
- 创建发现文件。
- 停用时(IDE 关闭/插件禁用):
- 停止 MCP 服务器。
- 删除发现文件。