Owner MCP facade = 在两个容器上做通用的发现与调用
上级:backend-domain-modules · 相关:facade-parity · facade-directions
决定(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 上已不存在。