Context
Operator technical-debt review on 2026-05-26 flagged that ai/mcp/server/knowledge-base/toolService.mjs currently contains the ingestSourceFilesViaMcp() method body inline above the serviceMapping dispatch table.
The live substrate now intentionally keeps the remote StreamableHTTP/SSE ingest_source_files path after #11743 and #11744, while hiding and fail-closing it for local stdio. This ticket is therefore not a demotion ticket. It is a narrow refactor to keep the retained MCP facade but remove implementation logic from the mapping module.
Duplicate sweep:
rg "ingest_source_files|ingestSourceFilesViaMcp|IngestSourceFilesTool|toolService.*mapping" resources/content/issues resources/content/discussions surfaced #11690, #11743, and #11744.
- #11690 resolved an earlier demotion pressure, but #11743 and #11744 later established the transport-gated compromise: remote MCP path retained, local stdio hidden and fail-closed.
- #11744 implemented transport gating, not this extraction.
- No existing ticket was found for moving the MCP facade implementation out of
toolService.mjs while retaining the remote tool.
The Problem
toolService.mjs has two roles mixed together:
- server-local tool listing / dispatch composition; and
- the concrete
ingest_source_files facade implementation, including MCP volume counting, KB_INGEST_VOLUME_EXCEEDED, and service dispatch.
The mapping object should read as a declarative OpenAPI operationId to handler table. Keeping a full method definition inline makes the file harder to scan and encourages future tool-specific implementations to accrete directly into the mapping surface.
The Architectural Reality
Verified surfaces:
| Surface |
Current behavior |
Relevance |
ai/mcp/server/knowledge-base/toolService.mjs |
Defines ingestSourceFilesViaMcp() inline and maps ingest_source_files to it. |
Refactor target. |
ai/mcp/ToolService.mjs |
Generic OpenAPI operationId to handler dispatcher. |
Should remain generic and not learn KB-specific transport policy. |
KnowledgeBaseIngestionService.ingestSourceFiles() |
Domain ingestion service consumed by MCP, CLI, and server-side pull paths. |
Should not receive MCP facade naming or transport exposure logic. |
test/playwright/unit/ai/mcp/server/knowledge-base/IngestSourceFilesTool.spec.mjs |
Already names this surface as an MCP facade and tests the exported handler directly. |
Test naming supports extracting a dedicated facade module. |
| #11744 |
Retains ingest_source_files for StreamableHTTP/SSE and hides/fail-closes stdio. |
This ticket must preserve that behavior. |
Structural pre-flight:
Pre-Flight (structural full): considered ai/mcp/server/knowledge-base/, ai/services/knowledge-base/helpers/, and a new ai/mcp/server/knowledge-base/tools/ subdirectory; consulted learn/benefits/ArchitectureOverview.md Structural Inventory, learn/agentos/v13-path.md M6 service/MCP boundary, ADR list, and sibling files. Chosen destination is an existing KB MCP-server-local sibling module, recommended ai/mcp/server/knowledge-base/ingestSourceFilesTool.mjs, because this is transport/tool-boundary policy over a retained remote facade, not reusable ingestion-domain logic. Map-maintenance: not needed; this decomposes an existing server-local file and introduces no new subsystem row.
The Fix
Extract the ingest_source_files facade implementation out of toolService.mjs into a KB MCP-server-local module.
Recommended shape:
- Add
ai/mcp/server/knowledge-base/ingestSourceFilesTool.mjs.
- Move
ingestSourceFilesViaMcp() there.
- Move any tightly coupled batch-volume helper with it.
- Consider moving the
ingest_source_files transport visibility and fail-closed policy with it if that improves locality without obscuring listTools() flow.
- Keep
toolService.mjs as the composition root that imports the handler and maps ingest_source_files: ingestSourceFilesViaMcp.
- Keep
KnowledgeBaseIngestionService free of MCP facade naming and transport policy.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
ingest_source_files MCP behavior |
#11634, #11743, #11744, current IngestSourceFilesTool.spec.mjs |
Behavior unchanged: remote SSE listed/callable, stdio hidden/fail-closed, over-threshold payload returns KB_INGEST_VOLUME_EXCEEDED. |
If extraction exposes ambiguity, keep transport visibility in toolService.mjs and move only the handler body. |
Existing cloud deployment docs; no user-facing doc change expected. |
Existing IngestSourceFilesTool.spec.mjs should remain green or be updated to import the new module. |
toolService.mjs service mapping |
Generic ToolService dispatch pattern and local server composition |
Mapping stays declarative and imports handlers rather than defining full tool bodies inline. |
None. |
JSDoc comment on extracted module. |
Unit coverage proves mapping still dispatches. |
KnowledgeBaseIngestionService.ingestSourceFiles() |
Service-layer ingestion boundary |
No MCP-specific method names or transport visibility policy move into the service. |
A pure reusable batch-volume helper may live under ai/services/knowledge-base/helpers/ only if multiple non-MCP consumers appear. |
Existing JSDoc remains authoritative. |
No service behavior change. |
Acceptance Criteria
Out of Scope
- Removing
ingest_source_files from StreamableHTTP/SSE deployments.
- Changing the OpenAPI operation or schema.
- Changing
ai:ingest-tenant, ai:kb-push-client, or server-side TenantRepoSyncService ingestion behavior.
- Introducing a generic cross-server tool plugin registry.
Related
Origin Session ID: 1578fb3e-7f5a-4b43-a6d0-ba00e66a9885
Handoff Retrieval Hints:
ask_knowledge_base({query: "ingest_source_files facade toolService transport gate", type: "all"})
rg "ingestSourceFilesViaMcp|ingest_source_files|listTransportVisibleTools" ai/mcp/server/knowledge-base test/playwright/unit/ai/mcp/server/knowledge-base -S
Context
Operator technical-debt review on 2026-05-26 flagged that
ai/mcp/server/knowledge-base/toolService.mjscurrently contains theingestSourceFilesViaMcp()method body inline above theserviceMappingdispatch table.The live substrate now intentionally keeps the remote StreamableHTTP/SSE
ingest_source_filespath after #11743 and #11744, while hiding and fail-closing it for local stdio. This ticket is therefore not a demotion ticket. It is a narrow refactor to keep the retained MCP facade but remove implementation logic from the mapping module.Duplicate sweep:
rg "ingest_source_files|ingestSourceFilesViaMcp|IngestSourceFilesTool|toolService.*mapping" resources/content/issues resources/content/discussionssurfaced #11690, #11743, and #11744.toolService.mjswhile retaining the remote tool.The Problem
toolService.mjshas two roles mixed together:ingest_source_filesfacade implementation, including MCP volume counting,KB_INGEST_VOLUME_EXCEEDED, and service dispatch.The mapping object should read as a declarative OpenAPI operationId to handler table. Keeping a full method definition inline makes the file harder to scan and encourages future tool-specific implementations to accrete directly into the mapping surface.
The Architectural Reality
Verified surfaces:
ai/mcp/server/knowledge-base/toolService.mjsingestSourceFilesViaMcp()inline and mapsingest_source_filesto it.ai/mcp/ToolService.mjsKnowledgeBaseIngestionService.ingestSourceFiles()test/playwright/unit/ai/mcp/server/knowledge-base/IngestSourceFilesTool.spec.mjsingest_source_filesfor StreamableHTTP/SSE and hides/fail-closes stdio.Structural pre-flight:
Pre-Flight (structural full): considered
ai/mcp/server/knowledge-base/,ai/services/knowledge-base/helpers/, and a newai/mcp/server/knowledge-base/tools/subdirectory; consultedlearn/benefits/ArchitectureOverview.mdStructural Inventory,learn/agentos/v13-path.mdM6 service/MCP boundary, ADR list, and sibling files. Chosen destination is an existing KB MCP-server-local sibling module, recommendedai/mcp/server/knowledge-base/ingestSourceFilesTool.mjs, because this is transport/tool-boundary policy over a retained remote facade, not reusable ingestion-domain logic. Map-maintenance: not needed; this decomposes an existing server-local file and introduces no new subsystem row.The Fix
Extract the
ingest_source_filesfacade implementation out oftoolService.mjsinto a KB MCP-server-local module.Recommended shape:
ai/mcp/server/knowledge-base/ingestSourceFilesTool.mjs.ingestSourceFilesViaMcp()there.ingest_source_filestransport visibility and fail-closed policy with it if that improves locality without obscuringlistTools()flow.toolService.mjsas the composition root that imports the handler and mapsingest_source_files: ingestSourceFilesViaMcp.KnowledgeBaseIngestionServicefree of MCP facade naming and transport policy.Contract Ledger Matrix
ingest_source_filesMCP behaviorIngestSourceFilesTool.spec.mjsKB_INGEST_VOLUME_EXCEEDED.toolService.mjsand move only the handler body.IngestSourceFilesTool.spec.mjsshould remain green or be updated to import the new module.toolService.mjsservice mappingToolServicedispatch pattern and local server compositionKnowledgeBaseIngestionService.ingestSourceFiles()ai/services/knowledge-base/helpers/only if multiple non-MCP consumers appear.Acceptance Criteria
ingestSourceFilesViaMcp()is no longer defined inline inai/mcp/server/knowledge-base/toolService.mjs.toolService.mjsimports the facade handler and keepsserviceMappingreadable as operationId to handler wiring.ingest_source_filesbehavior remains unchanged for bothsseandstdiotransports.KB_INGEST_VOLUME_EXCEEDEDwithout dispatching toKnowledgeBaseIngestionService.test/playwright/unit/ai/mcp/server/knowledge-base/IngestSourceFilesTool.spec.mjsis updated only as needed for the new import location and passes.KnowledgeBaseIngestionService.Out of Scope
ingest_source_filesfrom StreamableHTTP/SSE deployments.ai:ingest-tenant,ai:kb-push-client, or server-sideTenantRepoSyncServiceingestion behavior.Related
Origin Session ID: 1578fb3e-7f5a-4b43-a6d0-ba00e66a9885
Handoff Retrieval Hints:
ask_knowledge_base({query: "ingest_source_files facade toolService transport gate", type: "all"})rg "ingestSourceFilesViaMcp|ingest_source_files|listTransportVisibleTools" ai/mcp/server/knowledge-base test/playwright/unit/ai/mcp/server/knowledge-base -S