Summary
In ExecuteSearch (Mcp/McpToolHandlers.cs:307), all SearchSnippetFormatter.ToCompactResult calls run synchronously over the full results list, clamping each snippet's line widths individually via LineWidthFormatter. For large result sets (e.g., 1000 chunk matches on a common identifier), this forces serialization of all snippets before any filtering or streaming can occur. Each result's ...(+N)... elision markers and line-width clamping are computed upfront, meaning wide queries pay quadratic memory cost. No streaming / pagination path exists to fence memory growth.
Where
src/CodeIndex/Mcp/McpToolHandlers.cs:307 (JsonSerializer.SerializeToNode materializes entire results)
src/CodeIndex/Cli/SearchSnippetFormatter.cs (ToCompactResult called per-result without streaming)
src/CodeIndex/Database/LineWidthFormatter.cs:15-27 (line clamp per-result, no batching or early exit)
Suggested approach
- Implement an IEnumerable-returning
SearchSnippetFormatter.ToCompactResults that yields results lazily
- For MCP tools, collect results into a pre-serialized JsonArray while respecting a per-result memory budget
- Implement streaming JSON serialization in McpToolHandlers so each result is written to output immediately rather than accumulated
- Add an
early_truncated field to responses when a result's line-clamp could not complete within budget
- Update TestSnippetFormatter to validate lazy enumeration doesn't force materialization
- Document this pattern for all tools returning large result sets
Summary
In ExecuteSearch (Mcp/McpToolHandlers.cs:307), all SearchSnippetFormatter.ToCompactResult calls run synchronously over the full results list, clamping each snippet's line widths individually via LineWidthFormatter. For large result sets (e.g., 1000 chunk matches on a common identifier), this forces serialization of all snippets before any filtering or streaming can occur. Each result's
...(+N)...elision markers and line-width clamping are computed upfront, meaning wide queries pay quadratic memory cost. No streaming / pagination path exists to fence memory growth.Where
src/CodeIndex/Mcp/McpToolHandlers.cs:307(JsonSerializer.SerializeToNode materializes entire results)src/CodeIndex/Cli/SearchSnippetFormatter.cs(ToCompactResult called per-result without streaming)src/CodeIndex/Database/LineWidthFormatter.cs:15-27(line clamp per-result, no batching or early exit)Suggested approach
SearchSnippetFormatter.ToCompactResultsthat yields results lazilyearly_truncatedfield to responses when a result's line-clamp could not complete within budget