Owner MCP facade = generic discovery + invoke over the two containers
Parent: backend-domain-modules · Related: facade-parity · facade-directions
Decision (2026-07-27, owner)
The owner's agent (owner's own MCP client / Claude Code) must reach capabilities the same generic way the visitor agent does: discover from the container, invoke by name. No explicit per-capability host code.
Give the owner agent, over MCP, two generic discover+invoke doors — one per container:
| container | discover | invoke |
|---|---|---|
capability (capreg) | list registered capabilities | invoke a capability's tool by name, in owner context |
connector (Hub) | list connected connectors | connector.invoke(category, verb, args) (opaque door — already exists) |
"这样就通用了" — instead of N explicit owner caps, TWO generic doors. Owner books = discover
the booker capability → invoke it; owner sets policy = same; owner uses calendar = discover
the calendar connector → invoke. The owner side is zero explicit cap code.
What this replaces / deletes
- The entire
internal/plugins/ownercoreexplicitcap_*surface (~29 hand-written owner caps:cap_calendar/cap_booking/cap_chat/cap_corpus_*/ …). They become discovered from the registry, not hand-written.cap_calendar/cap_bookingin particular are the anti-pattern the owner flagged: an externalized capability (booker sandbox) re-implemented as explicit host code. See external-means-fully-external. - This is the endgame of facade-from-registry (facade-parity): every facade generated-from / verified-against the one capability registry.
The one real mechanism to build (the crux)
capreg already had List() (discovery was done). The missing piece was owner-context invocation
of a capability — especially a sandbox capability. Until then a sandbox cap was dialed only inside a
visitor session (Capability.VisitorBinding(ctx, AssembleInput) → dialAndList per
ConversationID; extMCPCapability/mcpAppCapability were ShapeVisitorOnly, OwnerMCPBindings()
returned []). There was no owner-context dial: the owner has no visitor session, only an
owner_id.
Built (7f02bccc1, 2026-07-29): the manifest declares owner tools as data (mcpplugin.Manifest.OwnerTools,
internal/capabilities/mcpplugin/manifest.go), and routes/capload/capreg_mcp_app_owner.go turns each
declared tool into an OwnerMCPBindings() entry whose handler dials the sandbox only when invoked, with
owner context (owner_id, no visitor/code/conversation) and forwards the tools/call. The table is
enumerated at assembly time so facade-parity reconciles against it without dialing anything at boot. The
sandbox tool runs its logic via the same generic reach-back it already used (connector.invoke +
capstore + owner.meta); booker declares its owner-facing tools (owner list_slots,
calendar_cancel_booking, policy get/set, bookings-list) in mcp-servers/booker/main.go, and the host's
duplicate policy/slots evaluator was deleted in the same commit. The same hole reopened once more for
settings — a capability could declare owner tools but not owner-tunable fields, so booker's booking
policy was hand-written on the host again — and was closed the same way: Manifest.Config /
capconfig (cc5c1db47, 2026-07-31).
Consequence for internal/
Reaching the "plugins gone" target was gated on this build, and it went through: internal/plugins
dissolved into owner/ (fea7ae93f, 2026-07-29), the domains declare their own ops and the dispatcher
only aggregates (53733b661, 2026-08-01), and ownercore itself is gone (f35e82c04, 2026-08-02). As of
2026-09-07 internal/ holds 11 directories — the 8 core domains + capabilities + routes + infra —
which is exactly the whitelist check-internal-dirs.sh enforces.
Scope / verification
Foundational, replaces ownercore, must be verified by real owner + visitor booking e2e
(gcal + sandbox rebuild; make test-only SPEC=booking). Compile+lint green is NOT sufficient.
Status
Shipped. Owner-context invocation 2026-07-29 (7f02bccc1), plugins dissolved 2026-07-29 (fea7ae93f),
ownercore deleted 2026-08-02 (f35e82c04). Proof files: internal/routes/capload/capreg_mcp_app_owner.go,
internal/capabilities/mcpplugin/manifest.go; internal/plugins/ and internal/owner/ownercore/ no
longer exist on main.