Owner MCP facade = 在两个容器上做通用的发现与调用

更新于 · 在 sijie.xyz 查看原条目 ↗

决定(2026-07-27,owner)

owner 的 agent(owner 自己的 MCP 客户端 / Claude Code)必须以和访客 agent 完全相同的通用方式 去触达各种能力:从容器里发现,按名字调用。不允许为每个能力单独写 host 代码。

给 owner agent 在 MCP 上开两扇通用的"发现+调用"门——每个容器一扇:

容器 discover(发现) invoke(调用)
capability(capreg) 列出已注册的能力 按名字调用某个能力的工具,在owner 上下文中
connector(Hub) 列出已连接的 connector connector.invoke(category, verb, args)(不透明的门——已经存在)

"这样就通用了"——用两扇通用的门,取代 N 个显式的 owner 能力。owner 订房 = 发现 booker 能力 → 调用它;owner 设置策略 = 同样的路径;owner 使用日历 = 发现 calendar connector → 调用。 owner 这一侧是零显式能力代码。

这个决定替换 / 删掉了什么

  • 整个 internal/plugins/ownercore 里显式的 cap_* 表面(约 29 个手写的 owner 能力: cap_calendar / cap_booking / cap_chat / cap_corpus_* / ……)。它们会变成从 registry 里发现出来的,而不是手写的。cap_calendar/cap_booking 尤其是 owner 点名批评过的反模式: 一个本该被**externalized(外部化)**的能力(booker sandbox)却被重新实现成了显式的 host 代码。 见 external-means-fully-external。
  • 这是 facade-from-registry(facade-parity)的终局:每一个 facade 都由同一个能力 registry 生成、并与之校验。

唯一要建的真实机制(关键点)

capreg 当时已经有 List()(发现这一块已经做完了)。缺的那一块是在 owner 上下文里调用一个 能力——尤其是 sandbox 能力。 那时 sandbox 能力只能在访客会话里被拨通 (Capability.VisitorBinding(ctx, AssembleInput) → 按 ConversationID 走 dialAndList; extMCPCapability/mcpAppCapability 都是 ShapeVisitorOnly,OwnerMCPBindings() 返回 [])。没有 owner 上下文的拨号路径:owner 没有访客会话,只有一个 owner_id。

已建成(7f02bccc1,2026-07-29):manifest 把 owner 工具声明成数据(mcpplugin.Manifest.OwnerTools, internal/capabilities/mcpplugin/manifest.go),routes/capload/capreg_mcp_app_owner.go 把每一条声明变成 一个 OwnerMCPBindings() 条目,其 handler 只在被调用时才拨号 sandbox,带 owner 上下文 (owner_id,没有 visitor/code/conversation),转发那次 tools/call。工具表在装配时就枚举出来, 于是 facade-parity 不用在启动时拨任何东西就能对账。sandbox 工具跑自己的逻辑时,走的还是它已经在用的 那条通用回连路径(connector.invoke + capstore + owner.meta);booker 在 mcp-servers/booker/main.go 里声明了自己面向 owner 的工具(owner 版 list_slots、 calendar_cancel_booking、policy get/set、bookings-list),host 侧那份重复的 policy/slots 求值器在同一 提交里删掉。同一个洞后来在设置上又开了一次 —— 能力能声明 owner 工具却不能声明 owner 可调的字段, 于是 booker 的预约策略又被手写回 host —— 用同样的办法堵上:Manifest.Config / capconfig (cc5c1db47,2026-07-31)。

对 internal/ 的影响

"plugins 清空"这个目标卡在这个 build 上,而它已经走通:internal/plugins 并入 owner/ (fea7ae93f,2026-07-29),各领域自己声明 op、dispatcher 只做聚合(53733b661,2026-08-01), ownercore 本身也没了(f35e82c04,2026-08-02)。截至 2026-09-07,internal/ 下是 11 个目录 —— 8 个核心领域 + capabilities + routes + infra —— 正好就是 check-internal-dirs.sh 强制的那份白名单。

范围 / 验证

这是基础性的改动,替换掉 ownercore,必须靠真实的 owner + visitor 订房端到端测试来验证 (gcal + sandbox 重建;make test-only SPEC=booking)。编译+lint 通过不算数。

状态

已上线。 owner 上下文调用 2026-07-29(7f02bccc1),plugins 拆解 2026-07-29(fea7ae93f), ownercore 删除 2026-08-02(f35e82c04)。证据文件:internal/routes/capload/capreg_mcp_app_owner.go、 internal/capabilities/mcpplugin/manifest.go;internal/plugins/ 和 internal/owner/ownercore/ 在 main 上已不存在。

相关笔记