Filed 2026-05-08 as M6 sub-issue 1 (knowledge-base) — first per-server SDK migration in the M6 epic #10986 sequence (KB → GH-WF → NL → MC). Selected as #1 because:
Smallest cloud-native server (10 services in source dir; 8 SDK-exported via ai/services.mjs aliases)
Validates the migration shape before tackling more complex servers (memory-core has 13+ services + lifecycle/ + managers/ subdirs)
Per parent M6 epic #10986 §The Fix and learn/agentos/v13-path.md §3 D4: services move from ai/mcp/server/knowledge-base/services/*.mjs → ai/services/knowledge-base/*.mjs. ai/services.mjs becomes a re-export aggregator with stable <Server>_<ServiceName> alias contracts (consumer-side unchanged). M2 BaseServer substrate (#10965) provides the extension contract; per-server Server.mjs gets its getDependentServices() override updated to import from the new SDK paths.
The Problem
KB services currently live under ai/mcp/server/knowledge-base/services/ — 10 files, 8 of which are exposed via ai/services.mjs's aliasing layer (KB_DatabaseService, KB_LifecycleService, KB_DocumentService, KB_HealthService, KB_RecorderService, KB_QueryService, KB_SearchService, KB_ChromaManager). Operator scripts, daemons, integration tests, and the KB server's own bootstrap path consume them through the prefix-namespaced re-export layer.
The friction (per parent epic #10986 framing): the on-disk shape conflates "service implementation" with "MCP transport endpoint" — services are owned by the server-specific dir rather than by the SDK boundary. This sub-issue normalizes KB to the existing ai/services/ConceptService.mjs flat-shape precedent.
The Architectural Reality
Current state (verified 2026-05-08 via ls ai/mcp/server/knowledge-base/services/ + grep on ai/services.mjs):
File
SDK alias (ai/services.mjs)
SDK-exported
ChromaManager.mjs
KB_ChromaManager
✓
DatabaseLifecycleService.mjs
KB_LifecycleService
✓
DatabaseService.mjs
KB_DatabaseService
✓
DocumentService.mjs
KB_DocumentService
✓
HealthService.mjs
KB_HealthService
✓
KBRecorderService.mjs
KB_RecorderService
✓
QueryService.mjs
KB_QueryService
✓
SearchService.mjs
KB_SearchService
✓
VectorService.mjs
(not exported — internal helper to ChromaManager)
—
toolService.mjs
(not exported — MCP tool router)
—
M2 BaseServer substrate (#10965):getDependentServices() override at ai/mcp/server/knowledge-base/Server.mjs:59 resolves service dependencies. Migration updates this override's import paths.
makeSafe() Zod-wrapping (ai/services.mjs:210-216): wraps 7 of 8 SDK-exported services with operation Zod schemas. Migration preserves the wrapping; only import paths change above the wrap.
Existing flat-shape precedent:ai/services/ConceptService.mjs (Concept Ontology) demonstrates the target shape — flat, owned by SDK boundary, not coupled to any MCP server's directory tree.
Update ai/services.mjs import paths (lines 28-35) — alias names (KB_*) preserved; only import paths change.
Update ai/mcp/server/knowledge-base/Server.mjsgetDependentServices() override and any other internal references to the old service paths.
Update KB config.mjs / openapi.yaml if they reference service paths.
Update internal cross-references between KB services (e.g., if VectorService imports ChromaManager, both at new paths).
Remove the now-empty ai/mcp/server/knowledge-base/services/ directory.
Verify operator scripts (ai:summarize-sessions, ai:run-sandman, ai:backup, ai:defrag-*) work unchanged via the preserved KB_* aliases.
Class names UNCHANGED. Service file names UNCHANGED. Only physical locations change.
Neo class-system compatibility note: Neo enforces filepath-to-className matching at setupClass time (per #10965 review correction). KB services appear to be factory-singletons (not Neo classes), so this is likely N/A — but verify during implementation. If any KB service does use Neo.setupClass() with a className matching the old path, the className must be updated alongside the path move.
AC9: Neo class-system compatibility: if any KB service uses Neo.setupClass() with a className matching the old path, className updated to the new path (likely N/A — KB services appear factory-singleton-shape, not Neo classes — verify during implementation).
AC10: PR description includes a brief diff summary table (file count moved, alias-preserved count, consumer-side breakage delta — should be zero).
Out of Scope
makeSafe() Zod schema reshape — wrapping pattern preserved as-is; this sub-issue does not reshape the SDK contract surface.
Removing or renaming KB services — physical move only. Service names + class names + alias names unchanged.
Touching ai/mcp/server/shared/services/* — shared cross-cutting services (DestructiveOperationGuard, AuthService, TransportService, etc.) stay at the shared boundary, unaffected by this sub-issue.
Other Tier-1 servers — github-workflow, neural-link, memory-core migrations are separate sub-issues filed per parent epic #10986 sequencing.
<Server>_<ServiceName> namespace prefix collapse — preserved through M6 per parent epic Out of Scope; future ticket may reshape.
VectorService / toolService SDK exposure — internal-only. Migration moves them physically but does NOT expose them externally via new aliases.
ai/services.mjs re-organization — this sub-issue updates KB import paths only; broader SDK-aggregator restructuring (e.g., per-server sub-modules) is future scope.
Avoided Traps / Gold Standards Rejected
Rejected: only move SDK-exported services, leave internal helpers in old location. Splits KB services across two top-level dirs categorized by export-status; creates ongoing cognitive cost for KB authors deciding "is this internal or SDK?". Move all 10 to keep the directory unified.
Rejected: rename KB_* aliases to drop the prefix during migration. Breaks every operator script, daemon, and test consumer in lockstep with this PR. Reshape is future-ticket scope per parent epic.
Rejected: refactor the makeSafe Zod wrapping pattern alongside the move. Increases PR risk; breaks "do one thing well per PR". makeSafe stays as-is; future tickets can reshape.
Rejected: collapse VectorService into ChromaManager during migration. Architectural reshape, not a migration. Separate ticket if desired.
Rejected: add new external SDK exports for VectorService / toolService. They're internal for a reason (VectorService is a ChromaManager helper; toolService is the MCP tool-routing surface). External exposure should be a deliberate decision, not a side-effect of physical move.
Rejected: gradual migration via indirection layer. A re-export shim under the old paths pointing to the new ones adds complexity; clean cut-over (move files + update imports in same PR) is simpler and safer for a 10-file scope.
Rejected: parallel cadence with sibling M6 sub-issues (GH-WF / NL / MC). Per parent epic #10986 Avoided Traps: each migration touches ai/services.mjs import paths — concurrent PRs would merge-conflict at that file. Linear sequencing keeps the SDK aggregator under single-edit lock.
M2 per-server migration precedent:#10973 — knowledge-base migration to BaseServer (analogous earlier per-server migration; this M6 sub-issue follows the same single-PR per-server pattern). The same Server.mjs that received the M2 BaseServer extension hooks now receives M6's getDependentServices() import-path update.
Context
Filed 2026-05-08 as M6 sub-issue 1 (knowledge-base) — first per-server SDK migration in the M6 epic #10986 sequence (KB → GH-WF → NL → MC). Selected as #1 because:
ai/services.mjsaliases)lifecycle/+managers/subdirs)Per parent M6 epic #10986 §The Fix and
learn/agentos/v13-path.md§3 D4: services move fromai/mcp/server/knowledge-base/services/*.mjs→ai/services/knowledge-base/*.mjs.ai/services.mjsbecomes a re-export aggregator with stable<Server>_<ServiceName>alias contracts (consumer-side unchanged). M2 BaseServer substrate (#10965) provides the extension contract; per-serverServer.mjsgets itsgetDependentServices()override updated to import from the new SDK paths.The Problem
KB services currently live under
ai/mcp/server/knowledge-base/services/— 10 files, 8 of which are exposed viaai/services.mjs's aliasing layer (KB_DatabaseService,KB_LifecycleService,KB_DocumentService,KB_HealthService,KB_RecorderService,KB_QueryService,KB_SearchService,KB_ChromaManager). Operator scripts, daemons, integration tests, and the KB server's own bootstrap path consume them through the prefix-namespaced re-export layer.The friction (per parent epic #10986 framing): the on-disk shape conflates "service implementation" with "MCP transport endpoint" — services are owned by the server-specific dir rather than by the SDK boundary. This sub-issue normalizes KB to the existing
ai/services/ConceptService.mjsflat-shape precedent.The Architectural Reality
Current state (verified 2026-05-08 via
ls ai/mcp/server/knowledge-base/services/+greponai/services.mjs):ChromaManager.mjsKB_ChromaManagerDatabaseLifecycleService.mjsKB_LifecycleServiceDatabaseService.mjsKB_DatabaseServiceDocumentService.mjsKB_DocumentServiceHealthService.mjsKB_HealthServiceKBRecorderService.mjsKB_RecorderServiceQueryService.mjsKB_QueryServiceSearchService.mjsKB_SearchServiceVectorService.mjstoolService.mjsM2 BaseServer substrate (#10965):
getDependentServices()override atai/mcp/server/knowledge-base/Server.mjs:59resolves service dependencies. Migration updates this override's import paths.makeSafe()Zod-wrapping (ai/services.mjs:210-216): wraps 7 of 8 SDK-exported services with operation Zod schemas. Migration preserves the wrapping; only import paths change above the wrap.Existing flat-shape precedent:
ai/services/ConceptService.mjs(Concept Ontology) demonstrates the target shape — flat, owned by SDK boundary, not coupled to any MCP server's directory tree.The Fix
Per-file moves (10 files):
ai/mcp/server/knowledge-base/services/ChromaManager.mjsai/services/knowledge-base/ChromaManager.mjsai/mcp/server/knowledge-base/services/DatabaseLifecycleService.mjsai/services/knowledge-base/DatabaseLifecycleService.mjsai/mcp/server/knowledge-base/services/DatabaseService.mjsai/services/knowledge-base/DatabaseService.mjsai/mcp/server/knowledge-base/services/DocumentService.mjsai/services/knowledge-base/DocumentService.mjsai/mcp/server/knowledge-base/services/HealthService.mjsai/services/knowledge-base/HealthService.mjsai/mcp/server/knowledge-base/services/KBRecorderService.mjsai/services/knowledge-base/KBRecorderService.mjsai/mcp/server/knowledge-base/services/QueryService.mjsai/services/knowledge-base/QueryService.mjsai/mcp/server/knowledge-base/services/SearchService.mjsai/services/knowledge-base/SearchService.mjsai/mcp/server/knowledge-base/services/VectorService.mjsai/services/knowledge-base/VectorService.mjsai/mcp/server/knowledge-base/services/toolService.mjsai/services/knowledge-base/toolService.mjsThen:
ai/services.mjsimport paths (lines 28-35) — alias names (KB_*) preserved; only import paths change.ai/mcp/server/knowledge-base/Server.mjsgetDependentServices()override and any other internal references to the old service paths.config.mjs/openapi.yamlif they reference service paths.VectorServiceimportsChromaManager, both at new paths).ai/mcp/server/knowledge-base/services/directory.ai:summarize-sessions,ai:run-sandman,ai:backup,ai:defrag-*) work unchanged via the preservedKB_*aliases.Class names UNCHANGED. Service file names UNCHANGED. Only physical locations change.
Neo class-system compatibility note: Neo enforces filepath-to-className matching at
setupClasstime (per #10965 review correction). KB services appear to be factory-singletons (not Neo classes), so this is likely N/A — but verify during implementation. If any KB service does useNeo.setupClass()with a className matching the old path, the className must be updated alongside the path move.Contract Ledger Matrix
ai/services/knowledge-base/<ServiceName>.mjspathslearn/agentos/post-M6-epicls ai/services/knowledge-base/confirms move; oldai/mcp/server/knowledge-base/services/removedai/services.mjsKB_*re-export aliasesai/services.mjsKB Server.getDependentServices()overrideServer.mjsJSDocAcceptance Criteria
ai/mcp/server/knowledge-base/services/toai/services/knowledge-base/. Old directory removed.ai/services.mjscontinues exporting all 8 currently-aliased KB services (KB_DatabaseService,KB_LifecycleService,KB_DocumentService,KB_HealthService,KB_RecorderService,KB_QueryService,KB_SearchService,KB_ChromaManager); only import paths change.ai/mcp/server/knowledge-base/Server.mjsgetDependentServices()override updated to import from new SDK paths.VectorServiceimportsChromaManager, both at new paths).Neo.setupClass()with a className matching the old path, className updated to the new path (likely N/A — KB services appear factory-singleton-shape, not Neo classes — verify during implementation).Out of Scope
makeSafe()Zod schema reshape — wrapping pattern preserved as-is; this sub-issue does not reshape the SDK contract surface.ai/mcp/server/shared/services/*— shared cross-cutting services (DestructiveOperationGuard,AuthService,TransportService, etc.) stay at the shared boundary, unaffected by this sub-issue.<Server>_<ServiceName>namespace prefix collapse — preserved through M6 per parent epic Out of Scope; future ticket may reshape.VectorService/toolServiceSDK exposure — internal-only. Migration moves them physically but does NOT expose them externally via new aliases.ai/services.mjsre-organization — this sub-issue updates KB import paths only; broader SDK-aggregator restructuring (e.g., per-server sub-modules) is future scope.Avoided Traps / Gold Standards Rejected
KB_*aliases to drop the prefix during migration. Breaks every operator script, daemon, and test consumer in lockstep with this PR. Reshape is future-ticket scope per parent epic.makeSafeZod wrapping pattern alongside the move. Increases PR risk; breaks "do one thing well per PR".makeSafestays as-is; future tickets can reshape.VectorServiceintoChromaManagerduring migration. Architectural reshape, not a migration. Separate ticket if desired.VectorService/toolService. They're internal for a reason (VectorServiceis a ChromaManager helper;toolServiceis the MCP tool-routing surface). External exposure should be a deliberate decision, not a side-effect of physical move.ai/services.mjsimport paths — concurrent PRs would merge-conflict at that file. Linear sequencing keeps the SDK aggregator under single-edit lock.Related
learn/agentos/v13-path.md§3 D4 + §4 M6getDependentServices()import-path update.Origin Session ID:
33ed57b5-10ed-491d-8b8f-ce5f1223ec38Retrieval Hint:
query_raw_memories(query="M6 SDK migration knowledge-base services flat shape ai/services/knowledge-base KB_ aliases")