Skip to content

feat(mcp): 安全物化 OpenCode HTTP MCP 配置 - #4

Closed
wanglongan587 wants to merge 4 commits into
ora-space:mainfrom
wanglongan587:codex/issue-488-opencode-http-mcp
Closed

feat(mcp): 安全物化 OpenCode HTTP MCP 配置#4
wanglongan587 wants to merge 4 commits into
ora-space:mainfrom
wanglongan587:codex/issue-488-opencode-http-mcp

Conversation

@wanglongan587

Copy link
Copy Markdown

关联 Issue

Closes ora-space/desktop#488

背景与问题

Desktop 已定义 Agent MCP Configuration protocol v1,用来让 Host(负责启动和协调 Agent 的桌面端进程)把 Workspace 中完整的 MCP 配置快照交给 Agent。MCP 即 Model Context Protocol,是应用向模型提供外部工具和数据源的一套协议。

OpenCode Agent 之前没有声明和实现这项能力,因此 Host 即使解析出了 HTTP MCP,也无法把它安全地写成 OpenCode 能直接读取的配置。若简单覆盖用户配置,还会带来密钥泄漏、误删用户文件、并发覆盖和错误接管既有文件等风险。

本 PR 提交的功能

  1. 声明 HTTP-only MCP 能力

    • 通过 plugin SDK(软件开发工具包)的高层 Agent API 注册 protocol v1。
    • 只声明 HTTP transport(网络传输方式);stdio transport(通过标准输入输出连接子进程)仍由 Host 判定为不支持并跳过。
  2. 物化 OpenCode 托管配置

    • 将 Host 提供的完整 Workspace MCP snapshot(某一时刻的完整配置状态)写入 <workspace>/.opencode/opencode.json
    • 输出仅包含 $schema 和顶层 mcp 映射,使用严格 UTF-8 JSON、两空格缩进、LF 换行、固定字段顺序和唯一末尾换行。
    • Tavily 等 HTTP MCP 会保留已解析的 HTTPS URL 和请求头,并输出 OpenCode 所需的 type: "remote"enabled: trueoauth: false
  3. 稳定标识与回执

    • 按规范生成 native key,即 OpenCode mcp 映射中稳定且可读的配置键;版本或配置修订变化不会改变该键。
    • 对完整文档计算 SHA-256 fingerprint。fingerprint 是内容摘要,可用于判断文件是否仍是之前写入的同一份内容,而不必在日志中暴露敏感正文。
    • 返回覆盖全部受支持 MCP 的完整 entry receipts,供 Host 校验每个条目的处理结果。
  4. 所有权与冲突保护

    • 在插件私有存储中维护 ownership ledger(所有权账本),只保存已应用和正在准备的内容指纹,不保存 URL、Authorization 或文档正文。
    • 已存在但无法证明由 Ora 管理的 .opencode/opencode.json 不会被接管。
    • 替换或删除前再次核验指纹;若用户或其他进程在操作期间修改文件,则返回冲突并保留外部修改。
    • 同一 operation 的重放具备幂等性:幂等表示重复执行同一请求不会产生额外副作用,并会得到相同结果。
    • 项目根目录的 opencode.json / opencode.jsonc 只用于检测 native-key 冲突,不会被修改。JSONC 是允许注释的 JSON 变体。
  5. 文件系统与 Git 安全措施

    • 在目标目录创建空的 staging file(提交前的临时文件),先限制其访问权限,再写入包含凭据的正文。
    • Windows 使用 ACL(访问控制列表,用于规定哪些系统用户可以访问文件),Unix-like 系统使用仅当前用户可读写的权限。
    • 写入完成后采用 same-directory atomic replacement(同目录原子替换):文件要么保持旧版本,要么一次性切换到完整新版本,避免进程中断留下半份配置。
    • 处理部分写入、同步文件内容,并在操作系统支持时同步目录元数据。
    • Git Workspace 只在仓库私有 exclude 中加入精确路径 /.opencode/opencode.json,不修改 .gitignore,也不忽略整个 .opencode 目录。
    • 若托管路径已被 Git 跟踪、Git 状态异常或 exclude 写入失败,会在敏感配置落盘前阻止操作。
    • 删除最后一个 MCP 时只删除指纹匹配的托管文档,不删除 .opencode 目录及任何相邻文件。
  6. 版本、文档与测试

    • 将 OpenCode Agent 对应版本和说明更新为 0.3.0。
    • 新增 MCP 模块说明、共享 receipt fixture 兼容性测试、公开注册测试,以及 Git/非 Git、冲突、权限、原子替换、删除和敏感信息保护等回归测试。

为什么采用这种方案

  • 使用 SDK 高层 API,而不复制协议类型:让 Host、SDK 与 Agent 共享同一份协议定义,避免多个实现随时间产生不兼容的“协议漂移”。
  • 独立托管文件,而不合并用户根配置:OpenCode 可以同时读取配置层;分离后可以明确证明文件所有权,也能避免重排、改写或误删用户手写配置。
  • 冲突时阻止,而不自动覆盖或接管:这会让某些异常情况需要用户处理,但优先保证用户数据和凭据安全。
  • 保存指纹而不保存完整快照:足以证明所有权和检测并发修改,同时减少私有状态中敏感信息的存留范围。
  • 只忽略一个文件,而不忽略目录:配置凭据不会意外进入 Git,但 .opencode 下其他用户文件和 Skill Surface 仍可正常被版本控制。
  • 只支持 HTTP:严格遵循 #488 的 OpenCode 能力范围,没有提前实现 stdio 或后续 ticket 的兼容层。

权衡与取舍

  • 为保证安全,无法证明所有权、检测到 tracked path、根配置键冲突或 Git 状态损坏时均选择显式失败;这比“尽量写入”更保守,但不会静默覆盖用户状态。
  • 原子替换和权限控制通过小型可注入接口隔离,代码量有所增加,但关键故障路径可以在测试中稳定复现,且不同操作系统的行为更清晰。
  • 正式依赖指向 @ora-space/plugin-sdk@0.6.0,因为该版本对应 Desktop 固定基线中的 MCP 高层 API。目前该版本尚未发布到 JSR,发布前标准依赖解析会失败;本地验证使用固定 Desktop SDK 基线完成。这里没有回退到旧 SDK,也没有在 Agent 仓库复制协议定义,以避免形成长期不兼容实现。SDK 0.6.0 需要先于 OpenCode Agent 0.3.0 发布。

验证

  • deno fmt --check:通过
  • deno check(映射到固定 Desktop SDK 基线):通过
  • deno lint:通过
  • MCP 单元/集成测试:15 项全部通过
  • deno bundle(映射到固定 Desktop SDK 基线):通过
  • Standards 独立复审:无有效问题
  • Spec 独立复审:无有效实现问题

未修改 Desktop 仓库,也未包含 #489 或后续 ticket 的实现。

@wanglongan587

Copy link
Copy Markdown
Author

建议关闭。本 PR 属于已被规格否决的工作区文件物化方案。后续请看 #6 (ACP 透明转发,不再写 OpenCode 配置文件)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Agent MCP 07] Materialize safe OpenCode HTTP MCP configuration documents

1 participant