Skip to content

Commit 078a2d9

Browse files
gxklclaude
andcommitted
docs(wiki): record egg MCP container-citizen + mount-then-compat idiom
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 46297b4 commit 078a2d9

2 files changed

Lines changed: 10 additions & 1 deletion

File tree

wiki/concepts/tegg-module-plugin.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ Hosts: `StandaloneApp.init()` (standalone) and `ModuleHandler.init()` via
117117
otherwise-plain inject with `EggType.CONTEXT` first (ctx wins), which a
118118
singleton inner object cannot inject. App-only names (`runtimeConfig`,
119119
`logger` — the latter is CONTEXT-blacklisted) are stamped APP automatically.
120+
- Mount-then-compat is the idiom for making an imperatively-built host object
121+
injectable to inner objects: an object that genuinely needs the live `app`
122+
to construct (e.g. the controller plugin's `EggMcpRouter`, built in the boot
123+
hook) is assigned to an `app.<name>` property BEFORE the inner-object graph
124+
builds; it then becomes an app property with a compat proto, and an inner
125+
object injects it with `@EggQualifier(EggType.APP)` (optional when the mount
126+
is conditional). This is how the egg MCP register became a container citizen
127+
without threading the whole `app` into the DI graph — see the controller
128+
plugin's `EggMCPRegisterProvider`.
120129

121130
## Access and qualifier boundary
122131

wiki/log.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Dates use the workspace-local Asia/Shanghai calendar date.
66

77
- sources touched: `tegg/plugin/tegg/src/lib/{ModuleHandler,EggAppLoader,EggCompatibleProtoImpl}.ts`, `tegg/core/runtime/src/impl/InnerObjectLoadUnitBuilder.ts`, `tegg/plugin/controller/src/{app.ts,lib/impl/http/EggHTTPRegisterProvider.ts}` (+ deleted `EggHTTPControllerRegister.ts`), controller-runtime `ControllerModule.ts` fold-in
88
- pages updated: `wiki/concepts/tegg-module-plugin.md`, `wiki/log.md`
9-
- note: A four-commit controller/tegg refactor. (1) Folded the `Egg*` inner-object shell subclasses into the runtime base classes (decorators moved onto `RootProtoManager`/`ControllerRegisterFactory`/`ControllerLoadUnitHook`/`ControllerPrototypeHook`; hosts re-export the bases). (2) Made the egg HTTP register a container citizen: `EggHTTPRegisterProvider` (@InnerObjectProto) replaces the static-TeggScope-slot `EggHTTPControllerRegister`, mirroring the fetch host's provider; the imperative enqueue/drain bypass now serves MCP only (MCP's `EggMcpRouter` genuinely needs the live `app` — the boundary the `McpRouter` abstraction exists for). (3) The load-bearing change: instead of ModuleHandler hand-providing `logger`/`runtimeConfig`/`router` as PRIVATE `ProvidedInnerObjectProto`s, it now feeds `EggAppLoader.buildAppSingletonCompatClazzList(PRIVATE)` into the inner-object graph via `InnerObjectLoadUnitBuilder.addCompatibleClazzList`, so inner objects inject app properties through the same `() => app[name]` compat protos business modules use. Enablers/gotchas: `EggCompatibleProtoImpl` now honors the descriptor accessLevel (was hardcoded PUBLIC) so the inner-unit copies are PRIVATE and don't collide with the app load unit's PUBLIC copies; CONTEXT-scoped compat protos are excluded (inner objects are singletons); compat protos are fed AFTER scanned inner objects and skip name clashes (inner object wins); `moduleConfigs` stays an explicit provided instance (blacklisted in EggAppLoader + wants a `ModuleConfigs` wrapper); an app property whose name is also a ctx property (`router`) needs `@EggQualifier(EggType.APP)` because `EggQualifierProtoHook` stamps a plain inject CONTEXT-first. Regression green (tegg/controller/mcp-client/aop/eventbus/config/schedule/service-worker) modulo the pre-existing 5000ms-suite-default flaky (`ControllerMetaManager` boot-error, `MultiApp` isolate — both pass in isolation) and dal tests needing MySQL.
9+
- note: A controller/tegg refactor arc. (1) Folded the `Egg*` inner-object shell subclasses into the runtime base classes (decorators moved onto `RootProtoManager`/`ControllerRegisterFactory`/`ControllerLoadUnitHook`/`ControllerPrototypeHook`; hosts re-export the bases). (2) Made the egg HTTP register a container citizen: `EggHTTPRegisterProvider` (@InnerObjectProto) replaces the static-TeggScope-slot `EggHTTPControllerRegister`, mirroring the fetch host's provider. (2b, commit `0e59ce453`) Did the same for the egg MCP register: mount the per-app `EggMcpRouter` on `app.mcpRouter` in the controller boot (it needs the live `app`, so it is still built imperatively) so its compat proto reaches inner objects; an `EggMCPRegisterProvider` optional-injects `@EggQualifier(EggType.APP) mcpRouter` and plugs in the MCP creator. With both HTTP and MCP on providers, the imperative enqueue/drain bypass `ControllerRegisterDefaults` (and `ControllerRegisterFactory.applyDefaultRegisters`) is DELETED — egg and standalone now differ only in their router/mcpRouter implementations. Added the first running egg MCP-controller test (`mcp-proxy/test/mcp-tegg-register.test.ts`: teggController + mcpProxy + a tegg `@MCPController`, asserts `app.mcpRouter` mounted and `GET /mcp/stateless/stream` → 405). (3) The load-bearing change: instead of ModuleHandler hand-providing `logger`/`runtimeConfig`/`router` as PRIVATE `ProvidedInnerObjectProto`s, it now feeds `EggAppLoader.buildAppSingletonCompatClazzList(PRIVATE)` into the inner-object graph via `InnerObjectLoadUnitBuilder.addCompatibleClazzList`, so inner objects inject app properties through the same `() => app[name]` compat protos business modules use. Enablers/gotchas: `EggCompatibleProtoImpl` now honors the descriptor accessLevel (was hardcoded PUBLIC) so the inner-unit copies are PRIVATE and don't collide with the app load unit's PUBLIC copies; CONTEXT-scoped compat protos are excluded (inner objects are singletons); compat protos are fed AFTER scanned inner objects and skip name clashes (inner object wins); `moduleConfigs` stays an explicit provided instance (blacklisted in EggAppLoader + wants a `ModuleConfigs` wrapper); an app property whose name is also a ctx property (`router`) needs `@EggQualifier(EggType.APP)` because `EggQualifierProtoHook` stamps a plain inject CONTEXT-first. Regression green (tegg/controller/mcp-client/aop/eventbus/config/schedule/service-worker) modulo the pre-existing 5000ms-suite-default flaky (`ControllerMetaManager` boot-error, `MultiApp` isolate — both pass in isolation) and dal tests needing MySQL.
1010

1111
## [2026-07-10] package | four-package controller layering (runtime library + per-host plugins)
1212

0 commit comments

Comments
 (0)