CLI、MCP 与 A2A 接入
让外部 Agent 在授权目录内操作本地文件,并跟踪任务和输出。
更新于Codex、WorkBuddy 等本地 Agent 可以通过 MCP 或 CLI + Skill 使用 OpenFiles;两者与 A2A 共用文件能力和任务管理。日常接入按下面的安装与 setup 步骤完成即可。A2A 面向自行开发的客户端,不能把 /a2a 填到 MCP 地址中;调用进程需要与 OpenFiles 在同一台电脑上。
安装 CLI
需要 Node.js 22 或更新版本,以及包含 resources/agent 的 OpenFiles 桌面构建。CLI 随桌面应用提供,从本地目录安装一次即可;下面是 macOS 默认安装位置:
npm install -g "/Applications/OpenFiles.app/Contents/Resources/agent"
Windows 使用 PowerShell,将示例路径替换为实际安装目录下的 resources\agent:
npm install -g "C:\path\to\OpenFiles\resources\agent"
源码开发时,先在仓库运行 npm run build,再运行 npm install -g ./dist/agent。安装后即可使用 openfiles 命令,不必记住脚本路径。
接入 Codex
运行以下命令。它会自动启动或连接 OpenFiles,通过 Codex CLI 注册 MCP,并将配套 Skill 安装到 ~/.agents/skills/openfiles。需要 codex 命令可用;完成后重启 Codex 加载配置。
openfiles setup codex
接入 WorkBuddy
运行以下命令。它会自动启动或连接 OpenFiles,将服务合并到 ~/.workbuddy/mcp.json,保留其他 MCP 服务并备份修改前的配置。完成后重启 WorkBuddy;如需 CLI + Skill,也可在“技能 → 添加技能”中导入命令输出的 skillArchive ZIP。MCP 本身已可直接使用。
openfiles setup workbuddy
首次 setup 默认创建并授权 ~/OpenFilesAgent,输出放在其 output 子目录。把待处理文件放入该目录,然后向 Agent 提出任务,例如:“用 OpenFiles 把工作目录里的 CDR 导出为全部页面 SVG 的 ZIP,等待完成并告诉我输出位置。”需要使用已有目录时,在 setup 后加 --workspace DIR;--output DIR 可指定输出目录。--dry-run 只预览配置路径。
授权目录与桌面路径保存在 ~/.openfiles/agent/setup.json。后续 CLI、MCP 和已安装 Skill 会按保存的配置启动桌面服务,自动读取地址与 token。配置中没有固定端口或 token。改变已运行网关的授权目录时,先退出 OpenFiles,再重试 setup;不会强制中断现有任务。
官方配置参考: Codex MCP · WorkBuddy MCP
检查连接与排错
doctor 只检查连接,不启动应用;capabilities 会启动已配置的桌面服务。schema 无需连接即可查看工具参数。MCP 显示已连接仅表示适配器已启动,仍应调用 capabilities 确认文件服务可用。
openfiles doctor
openfiles capabilities
openfiles schema openfiles_convert
找不到桌面应用时,用 setup codex --app /absolute/path/to/OpenFiles 指定可执行文件(WorkBuddy 替换客户端名)。Node.js 或桌面安装位置变化后重新安装 CLI 并运行 setup。目录权限错误应先核对返回的 readRoots / outputRoots。不要重新提交结果未知的写入任务,先用 tasks 查找。
手动启用网关(可选)
使用包含 resources/agent/openfiles.cjs 的桌面构建(macOS 位于 OpenFiles.app/Contents/Resources),客户端需要 Node.js 22 或更新版本。启动 OpenFiles 可执行文件时添加 --agent-read-root=/absolute/input --agent-output-root=/absolute/output。两个目录必须已存在;多个目录可重复传参。网关默认关闭,修改授权目录需要退出并重新启动桌面应用。源码仓库提供以下客户端命令:
npm run build-electron
npm run agent -- capabilities
npm run agent -- mcp-config
npm run agent -- skill
发现能力并执行
先读取 capabilities:conversionFormats 列出具体转换组合,metadata.formats 列出可编辑字段。openfiles_inspect 返回单个文件的转换目标。渲染接受 HTML、Markdown、SVG,输出 PNG 或 PDF,并禁用脚本与外部资源。CDR 转换输出包含全部页面 SVG 的 ZIP。用 openfiles_workflow 执行已保存的 .ofw,sourcePaths 替换文件输入节点;已保存的批量目录和蒙版也必须获得授权。PDF/OFD 元信息通过 metadata.edit、metadata.remove 节点处理。AI 节点需要已安装运行环境,并可能下载模型权重。将以下参数保存为 request.json,替换其中的路径:
JPEG 与热成像 JPEG 共用扩展名:若检查结果包含 contentDetectionRequired,列出的目标是候选格式,执行时会根据文件内容确认。
{"sourcePaths":["/input/design.cdr"],"outputDir":"/output","format":"zip"}
node dist/agent/openfiles.cjs call openfiles_convert --input request.json --wait
跟踪和恢复任务
写入会保留原文件,在 outputDir 下创建新的 openfiles-* 目录。轮询至 completed、failed 或 canceled,再检查 result.paths 和逐文件错误。--wait 默认等待 300 秒,可通过 --timeout 调整;超时后任务仍继续运行。重新提交前,先用 tasks 找回任务 ID。列表支持 --json 或 --input,可传 state、contextId、pageSize、pageToken;列表省略产物,需查询单个任务获取输出。网关最多保留 100 个任务,同时运行最多 8 个;重启会清空任务记录。取消会保留已完成的输出。
node dist/agent/openfiles.cjs tasks
node dist/agent/openfiles.cjs task TASK_ID --wait
node dist/agent/openfiles.cjs cancel TASK_ID
连接 MCP 与安装 Skill
mcp-config 只打印配置,不修改客户端设置;将其中的命令与参数配置到外部客户端。mcp 通过 stdio 使用按行分隔的 JSON-RPC;skill 输出随包提供的 OpenFiles 指南。默认连接文件为 ~/.openfiles/agent/connection.json。自定义位置时,桌面的 --agent-connection=PATH 与客户端的 --connection PATH 应对应。不要公开其中的 bearer token。下方源码示例中的 dist/agent/openfiles.cjs 可替换为安装包内客户端路径。对话设置中的出站 MCP 服务与此处外部网关是独立配置。
调用 A2A
从连接文件读取本机回环地址,访问 /.well-known/agent-card.json;securityRequirements 声明 bearer 认证。向 /a2a POST 下方 JSON,并带上 Content-Type: application/json、A2A-Version: 1.0、Authorization: Bearer <token>。网络重试时复用相同消息 ID 和消息内容。使用 { "id": "TASK_ID" } 调用 GetTask 轮询,或调用 CancelTask。ListTasks 支持 contextId、status、statusTimestampAfter、分页和 includeArtifacts。不提供流式响应、推送通知或自然语言规划。路径均属于当前电脑;截图编辑和插件安装仍通过桌面界面操作。
{
"jsonrpc": "2.0",
"id": 1,
"method": "SendMessage",
"params": {
"message": {
"messageId": "unique-request-id",
"role": "ROLE_USER",
"parts": [{"data": {"name": "openfiles_capabilities", "arguments": {}}}]
},
"configuration": {"returnImmediately": true}
}
}
步骤不清楚或与界面不一致?告诉我们。