Context
Operator refinement during the #11720/#11743 receiver/auth V-B-A: the KB ingest_source_files MCP tool should not be exposed unconditionally. If tenant repo-push ingestion is only meaningful for a cloud deployment where external clients can reach the KB server over StreamableHTTP/SSE, then the tool should only appear in that deployed HTTP profile. In local stdio mode it is not needed and adds command-plane/tool-surface weight.
This follows the active #11743 correction: the missing #11720 piece is not simply "non-MCP receiver required." A real MCP-over-StreamableHTTP path may be viable, but only if the deployment provides an operator-facing push client and auth flow. The transport-gating rule tightens that story: expose the ingestion tool where it has an actual remote client consumer; hide it where it is just local tool-surface noise.
Duplicate sweep:
ask_knowledge_base(query='duplicate ticket conditionally expose ingest_source_files only for StreamableHTTP SSE transport hide stdio MCP KB ingestion tool', type='ticket') surfaced archived transport migration tickets such as #9533, but those concern server transport mechanics, not conditional exposure of this ingestion tool.
rg "ingest_source_files|StreamableHTTP|stdio|tool exposure|MCP client" resources/content/issues resources/content/discussions learn/agentos ai/mcp/server/knowledge-base ai/mcp/client surfaced Discussion #11690's adjacent ingest_source_files tool-surface governance discussion and no filed implementation ticket for transport-gated exposure.
- GitHub issue search for
ingest_source_files StreamableHTTP stdio surfaced #11743 as the parent receiver/auth decision issue, not this narrower implementation rule.
The Problem
ingest_source_files currently appears as a normal Knowledge Base MCP tool because it is declared in ai/mcp/server/knowledge-base/openapi.yaml and mapped unconditionally in ai/mcp/server/knowledge-base/toolService.mjs.
Current reality:
openapi.yaml declares /db/data/ingest with operationId: ingest_source_files.
ToolService.initializeToolMapping() turns every OpenAPI operation with an operationId into a listed MCP tool.
knowledge-base/toolService.mjs maps ingest_source_files to ingestSourceFilesViaMcp unconditionally.
aiConfig.transport defaults to stdio; sse / StreamableHTTP is the cloud/remote deployment transport.
That means local stdio harnesses carry a repo-push ingestion tool even though their normal ingestion paths are local script/service paths (ai:sync-kb, ai:ingest-tenant, direct service calls). The tool's meaningful external consumer is the HTTP-deployed tenant push client from #11743/#11728, not every local agent session.
The Architectural Reality
Verified surfaces:
| Surface |
Current behavior |
Gap |
ai/mcp/server/knowledge-base/openapi.yaml |
Declares ingest_source_files as a regular MCP operation. |
No per-transport visibility metadata. |
ai/mcp/ToolService.mjs |
Lists every OpenAPI operation with an operationId; no config/transport filter. |
No generic way to hide a tool from tools/list by deployment profile. |
ai/mcp/server/knowledge-base/toolService.mjs |
Registers ingest_source_files in serviceMapping unconditionally. |
Stdio and HTTP deployments expose the same ingestion tool. |
ai/mcp/server/knowledge-base/config.mjs |
transport defaults to stdio; sse is the HTTP/StreamableHTTP deployment mode. |
Tool visibility does not inspect transport. |
| #11743 |
Owns repo-push receiver/auth decision. |
Needs the MCP path to be concrete and operator-facing if retained. |
| Discussion #11690 |
Adjacent tool-surface governance pressure around ingest_source_files. |
Broader governance/demotion history; this ticket is the narrow transport-gated compromise. |
The Fix
Add a transport-aware visibility rule for the Knowledge Base ingest_source_files MCP operation:
- Hide
ingest_source_files from tools/list when the KB MCP server runs in stdio transport.
- Keep it exposed when the KB MCP server runs in
sse / StreamableHTTP transport.
- Decide whether hidden tools should also reject direct
tools/call by name in stdio mode. Preferred posture: fail closed; a hidden stdio tool should not remain callable by clients that know the name.
- Keep non-MCP ingestion paths intact:
ai:ingest-tenant and direct service use are not affected by this tool-visibility gate.
- Document the behavior in the cloud-deployment / tooling docs so #11728 does not teach local stdio users to call a remote-push tool and does not hide the fact that cloud deployments need an HTTP client/auth setup.
Implementation shape is intentionally open. Candidate options:
- Add an OpenAPI vendor extension such as
x-transports: ['sse'] and teach ToolService to filter both listing and dispatch with a server-provided context.
- Keep the filter local to the KB tool service if a generic ToolService change is over-broad for one tool.
- Split the ingestion operation into a separate profile-specific spec only if the filtering approach proves too invasive.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
KB tools/list in stdio mode |
#11743 receiver/auth correction; Discussion #11690 tool-surface pressure; aiConfig.transport |
ingest_source_files is omitted from the listed KB MCP tools when transport === 'stdio'. |
If filtering cannot be done generically, implement a KB-local filter and document why. |
KnowledgeBase.md / cloud-deployment docs. |
Unit/integration test proves stdio list excludes the tool. |
KB tools/list in sse / StreamableHTTP mode |
#11720 tenant repo-push deployment path; #11743 |
ingest_source_files remains listed because remote tenant push clients may need it. |
If #11743 later chooses a non-MCP receiver, this ticket may be superseded by full demotion. |
HookWiring.md / day-0 tutorial handoff. |
Test proves HTTP profile includes the tool. |
Direct tools/call by hidden name in stdio |
Fail-closed tool-surface policy |
Preferred: reject with a clear transport-gated error rather than silently executing. |
If backward compatibility requires callable-but-hidden, document the exception explicitly. |
Tooling docs. |
Test covers the chosen behavior. |
| Non-MCP ingestion paths |
#11635 / #11679 / ai:ingest-tenant |
CLI/service ingestion remains available independent of MCP tool exposure. |
None; this ticket must not break ai:ingest-tenant. |
Hook wiring. |
Existing CLI tests remain green; add targeted regression if touched. |
Acceptance Criteria
Out of Scope
- Implementing the operator-facing push client or OAuth automation identity flow. That remains #11743 / a child ticket under #11743 if decomposed further.
- Full tool-surface governance from Discussion #11690 beyond this one acute
ingest_source_files transport gate.
- Server-side ref-only webhook / clone credentials. That remains #11731.
- Removing
ingest_source_files from all deployments unless #11743 or #11690 follow-up explicitly supersedes the MCP path.
Avoided Traps
| Trap |
Why rejected |
| Full demotion before #11743 decides the receiver path |
MCP-over-StreamableHTTP may still be the right remote push path if paired with a prescribed client/auth flow. |
| Leaving the tool unconditionally visible |
Keeps local stdio agents carrying a code-event ingestion tool with no normal interactive consumer. |
| Documentation-only fix |
The tool surface itself remains misleading unless tools/list reflects the deployment profile. |
| Conflating transport availability with operator readiness |
The HTTP tool can exist and still need a concrete push client + automation identity model. |
Related
Parent / decision context: #11743
Epic context: #11720, #11728
Related substrate: #11634, #11635, #11679, Discussion #11690, #11731
Origin Session ID
2741c4bd-92b2-428b-92d3-ab718d9a7c41
Handoff Retrieval Hints
ask_knowledge_base({query: 'ingest_source_files ToolService openapi transport stdio sse', type: 'all'})
query_raw_memories({query: '#11743 MCP client automation account ingest_source_files transport gate'})
- Source anchors:
ai/mcp/server/knowledge-base/toolService.mjs, ai/mcp/server/knowledge-base/openapi.yaml, ai/mcp/ToolService.mjs, ai/mcp/server/knowledge-base/config.mjs.
Context
Operator refinement during the #11720/#11743 receiver/auth V-B-A: the KB
ingest_source_filesMCP tool should not be exposed unconditionally. If tenant repo-push ingestion is only meaningful for a cloud deployment where external clients can reach the KB server over StreamableHTTP/SSE, then the tool should only appear in that deployed HTTP profile. In localstdiomode it is not needed and adds command-plane/tool-surface weight.This follows the active #11743 correction: the missing #11720 piece is not simply "non-MCP receiver required." A real MCP-over-StreamableHTTP path may be viable, but only if the deployment provides an operator-facing push client and auth flow. The transport-gating rule tightens that story: expose the ingestion tool where it has an actual remote client consumer; hide it where it is just local tool-surface noise.
Duplicate sweep:
ask_knowledge_base(query='duplicate ticket conditionally expose ingest_source_files only for StreamableHTTP SSE transport hide stdio MCP KB ingestion tool', type='ticket')surfaced archived transport migration tickets such as #9533, but those concern server transport mechanics, not conditional exposure of this ingestion tool.rg "ingest_source_files|StreamableHTTP|stdio|tool exposure|MCP client" resources/content/issues resources/content/discussions learn/agentos ai/mcp/server/knowledge-base ai/mcp/clientsurfaced Discussion #11690's adjacentingest_source_filestool-surface governance discussion and no filed implementation ticket for transport-gated exposure.ingest_source_files StreamableHTTP stdiosurfaced #11743 as the parent receiver/auth decision issue, not this narrower implementation rule.The Problem
ingest_source_filescurrently appears as a normal Knowledge Base MCP tool because it is declared inai/mcp/server/knowledge-base/openapi.yamland mapped unconditionally inai/mcp/server/knowledge-base/toolService.mjs.Current reality:
openapi.yamldeclares/db/data/ingestwithoperationId: ingest_source_files.ToolService.initializeToolMapping()turns every OpenAPI operation with anoperationIdinto a listed MCP tool.knowledge-base/toolService.mjsmapsingest_source_filestoingestSourceFilesViaMcpunconditionally.aiConfig.transportdefaults tostdio;sse/ StreamableHTTP is the cloud/remote deployment transport.That means local stdio harnesses carry a repo-push ingestion tool even though their normal ingestion paths are local script/service paths (
ai:sync-kb,ai:ingest-tenant, direct service calls). The tool's meaningful external consumer is the HTTP-deployed tenant push client from #11743/#11728, not every local agent session.The Architectural Reality
Verified surfaces:
ai/mcp/server/knowledge-base/openapi.yamlingest_source_filesas a regular MCP operation.ai/mcp/ToolService.mjsoperationId; no config/transport filter.tools/listby deployment profile.ai/mcp/server/knowledge-base/toolService.mjsingest_source_filesinserviceMappingunconditionally.ai/mcp/server/knowledge-base/config.mjstransportdefaults tostdio;sseis the HTTP/StreamableHTTP deployment mode.ingest_source_files.The Fix
Add a transport-aware visibility rule for the Knowledge Base
ingest_source_filesMCP operation:ingest_source_filesfromtools/listwhen the KB MCP server runs instdiotransport.sse/ StreamableHTTP transport.tools/callby name in stdio mode. Preferred posture: fail closed; a hidden stdio tool should not remain callable by clients that know the name.ai:ingest-tenantand direct service use are not affected by this tool-visibility gate.Implementation shape is intentionally open. Candidate options:
x-transports: ['sse']and teachToolServiceto filter both listing and dispatch with a server-provided context.Contract Ledger Matrix
tools/listinstdiomodeaiConfig.transportingest_source_filesis omitted from the listed KB MCP tools whentransport === 'stdio'.KnowledgeBase.md/ cloud-deployment docs.tools/listinsse/ StreamableHTTP modeingest_source_filesremains listed because remote tenant push clients may need it.HookWiring.md/ day-0 tutorial handoff.tools/callby hidden name in stdioai:ingest-tenantai:ingest-tenant.Acceptance Criteria
ingest_source_filesis not returned by KBtools/listwhen the KB server is configured forstdiotransport.ingest_source_filesis returned by KBtools/listwhen the KB server is configured forsse/ StreamableHTTP transport.tools/callbehavior foringest_source_filesis explicitly decided and tested; preferred behavior is fail-closed with a clear transport-gated error.ai:ingest-tenantand directKnowledgeBaseIngestionService.ingestSourceFiles()use remain unaffected.Out of Scope
ingest_source_filestransport gate.ingest_source_filesfrom all deployments unless #11743 or #11690 follow-up explicitly supersedes the MCP path.Avoided Traps
tools/listreflects the deployment profile.Related
Parent / decision context: #11743
Epic context: #11720, #11728
Related substrate: #11634, #11635, #11679, Discussion #11690, #11731
Origin Session ID
2741c4bd-92b2-428b-92d3-ab718d9a7c41Handoff Retrieval Hints
ask_knowledge_base({query: 'ingest_source_files ToolService openapi transport stdio sse', type: 'all'})query_raw_memories({query: '#11743 MCP client automation account ingest_source_files transport gate'})ai/mcp/server/knowledge-base/toolService.mjs,ai/mcp/server/knowledge-base/openapi.yaml,ai/mcp/ToolService.mjs,ai/mcp/server/knowledge-base/config.mjs.