Context
Filed 2026-05-08 as the canonical anchor for M6 of the v13 release path per learn/agentos/v13-path.md §4. M2 (BaseServer common class — #10965) shipped today plus M3/M4/M5 closed; M6 is the next architecturally substantive wave, currently NOT STARTED with no prep tickets filed per the #10960 status snapshot.
The Problem
ai/services.mjs is mature SDK substrate — already consumed by operator scripts (ai:summarize-sessions, ai:run-sandman, ai:backup), tests, and the Memory Core's own processPendingSummarizations path. But its imports today reach into per-server directories:
import KB_QueryService from './mcp/server/knowledge-base/services/QueryService.mjs';
import Memory_Service from './mcp/server/memory-core/services/MemoryService.mjs';
This couples the SDK to per-server filesystem layout. With M2's BaseServer landed (PR #10966 + #10973-#10977) proving uniform Factory-pattern application across all 5 servers, the natural next move is decoupling service implementations from MCP server hosting: services flatten into the SDK boundary, MCP server Server.mjs files shrink to <50 LOC thin endpoint wrappers consuming services via SDK rather than via local imports.
The Architectural Reality
Empirical scope (verified 2026-05-08, dev ad952a10f):
| Server |
Server.mjs LOC |
Service files |
Migration size |
file-system |
61 |
2 |
trivially small (already near target) |
github-workflow |
110 |
~12 + queries/ + sync/ subdirs |
LARGE |
knowledge-base |
139 |
~10 |
LARGE |
memory-core |
417 |
~14 + lifecycle/ subdir |
XL (biggest lift) |
neural-link |
149 |
~9 |
MEDIUM |
Per v13-path.md §4 M6 exit gate: per-server Server.mjs files target <50 LOC.
The migration shape per v13-path.md D4:
- Services move OUT of
ai/mcp/server/<server>/services/* into a flatter SDK structure (final layout TBD per first sub-ticket review)
ai/services.mjs imports from new locations preserving namespaced prefixes (KB_*, Memory_*, GH_*, NL_*) — non-negotiable for SDK consumer compatibility
- Per-server
Server.mjs imports services via SDK rather than directly from per-server services/
- BaseServer extension (M2 substrate) keeps server-specific tool registration; service singletons become SDK-owned
Critical invariant (M2 substrate carryover): the BaseServer's Factory pattern uniform application via RequestContextService.run({...}, ...) MUST remain intact. SDK-side service consumers must operate inside RequestContext when called via MCP dispatch; daemon-side calls without context still work via SHARED_USER_ID fallback per #10556.
The Fix
This epic decomposes into 4 Tier-1 sub-tickets (one per server with substantive service code):
- KB SDK migration — knowledge-base services flattened to SDK; ~10 services + ChromaManager + toolService relocated
- MC SDK migration — memory-core services flattened; ~14 services + lifecycle subdirs (largest lift; staged in 2-3 PRs likely)
- GH-WF SDK migration — github-workflow services flattened; ~12 services + queries/sync subdirs
- NL SDK migration — neural-link services flattened; ~9 services
file-system (61 LOC, 2 services) does NOT warrant its own sub-ticket per feedback_substrate_scope_restraint — overhead exceeds work; cleanup absorbed via incremental polish.
Each Tier-1 sub-ticket follows the same pattern:
- Move service files:
ai/mcp/server/<server>/services/* → SDK-owned location
- Update
ai/services.mjs imports preserving namespaced prefixes
- Update per-server
Server.mjs to import from SDK; shrink to <50 LOC
- Verify Factory pattern uniformity (RequestContextService wraps dispatch unchanged)
- Run unit + integration matrix; capture LOC delta in PR body per AC7
Acceptance Criteria
Out of Scope
- Service-internal refactors (separate tickets if needed)
- Adding new tools or expanding service surface
- file-system server migration as a dedicated PR (absorbed via incremental polish)
- M7 release-cut work (separate epic)
- Daemon scheduling changes (M3/M4 already complete)
Avoided Traps / Gold Standards Rejected
- Rejected: bundle all 4 server migrations into one mega-PR. Per
feedback_substrate_scope_restraint — per-server PRs are review-tractable; mega-PR reviews fragment.
- Rejected: rename services during migration. Renaming + relocation in one PR doubles diff size. Migration preserves names + namespace prefixes; rename concerns deferred to follow-up tickets if needed.
- Rejected: change SDK import path from
ai/services.mjs to per-domain barrels. SDK consumers across the codebase already import from ai/services.mjs; switching would force a cascading breaking change. Internal layout flattens; external API stays.
- Rejected: include file-system server as its own sub-ticket. Empirically 61 LOC + 2 services; the per-ticket overhead exceeds the work.
Related
- Parent: #10960 (v13 Release Tracking)
- Parent epic: #9999 (Cloud-Native Knowledge & Multi-Tenant Memory Core, v13 main epic)
- Strategic anchor:
learn/agentos/v13-path.md §4 M6 + D4 + §8 outcome metrics
- M2 substrate predecessor: #10965 (BaseServer common class) — closed; provides the substrate this epic builds on
- M3 daemon predecessor: #10956 (Memory Core summary sweeps to daemon) — closed
- Sub-tickets: KB (forthcoming this session), MC + GH-WF + NL (forthcoming subsequent sessions; any agent can file following KB as template)
Origin Session ID: 7da190eb-af19-4e98-a3e2-f21f94f676c1
Retrieval Hint: query_raw_memories(query="M6 SDK migration per-server flatter SDK structure thin endpoint wrappers v13")
Context
Filed 2026-05-08 as the canonical anchor for M6 of the v13 release path per
learn/agentos/v13-path.md§4. M2 (BaseServer common class — #10965) shipped today plus M3/M4/M5 closed; M6 is the next architecturally substantive wave, currently NOT STARTED with no prep tickets filed per the #10960 status snapshot.The Problem
ai/services.mjsis mature SDK substrate — already consumed by operator scripts (ai:summarize-sessions,ai:run-sandman,ai:backup), tests, and the Memory Core's ownprocessPendingSummarizationspath. But its imports today reach into per-server directories:import KB_QueryService from './mcp/server/knowledge-base/services/QueryService.mjs'; import Memory_Service from './mcp/server/memory-core/services/MemoryService.mjs';This couples the SDK to per-server filesystem layout. With M2's BaseServer landed (PR #10966 + #10973-#10977) proving uniform Factory-pattern application across all 5 servers, the natural next move is decoupling service implementations from MCP server hosting: services flatten into the SDK boundary, MCP server
Server.mjsfiles shrink to <50 LOC thin endpoint wrappers consuming services via SDK rather than via local imports.The Architectural Reality
Empirical scope (verified 2026-05-08, dev
ad952a10f):Server.mjsLOCfile-systemgithub-workflowknowledge-basememory-coreneural-linkPer
v13-path.md§4 M6 exit gate: per-serverServer.mjsfiles target <50 LOC.The migration shape per
v13-path.mdD4:ai/mcp/server/<server>/services/*into a flatter SDK structure (final layout TBD per first sub-ticket review)ai/services.mjsimports from new locations preserving namespaced prefixes (KB_*,Memory_*,GH_*,NL_*) — non-negotiable for SDK consumer compatibilityServer.mjsimports services via SDK rather than directly from per-serverservices/Critical invariant (M2 substrate carryover): the BaseServer's Factory pattern uniform application via
RequestContextService.run({...}, ...)MUST remain intact. SDK-side service consumers must operate inside RequestContext when called via MCP dispatch; daemon-side calls without context still work viaSHARED_USER_IDfallback per #10556.The Fix
This epic decomposes into 4 Tier-1 sub-tickets (one per server with substantive service code):
file-system(61 LOC, 2 services) does NOT warrant its own sub-ticket perfeedback_substrate_scope_restraint— overhead exceeds work; cleanup absorbed via incremental polish.Each Tier-1 sub-ticket follows the same pattern:
ai/mcp/server/<server>/services/*→ SDK-owned locationai/services.mjsimports preserving namespaced prefixesServer.mjsto import from SDK; shrink to <50 LOCAcceptance Criteria
update_issue_relationshipServer.mjsfiles <50 LOC for all 5 servers (file-system trivially compliant; remaining 4 via sub-tickets)ai/services.mjsimports point at flattened SDK layout, not per-serverservices/dirsv13-path.md§8 target (>30% of pre-migration service LOC); reported in this epic's closing commentOut of Scope
Avoided Traps / Gold Standards Rejected
feedback_substrate_scope_restraint— per-server PRs are review-tractable; mega-PR reviews fragment.ai/services.mjsto per-domain barrels. SDK consumers across the codebase already import fromai/services.mjs; switching would force a cascading breaking change. Internal layout flattens; external API stays.Related
learn/agentos/v13-path.md§4 M6 + D4 + §8 outcome metricsOrigin Session ID:
7da190eb-af19-4e98-a3e2-f21f94f676c1Retrieval Hint:
query_raw_memories(query="M6 SDK migration per-server flatter SDK structure thin endpoint wrappers v13")