Problem
MCP search with guard filters and countOnly:true counts matched display rows, while CLI guarded count output counts distinct indexed result units. Multiple guarded matches in one indexed chunk therefore inflate the MCP count and its top_files histogram.
This affects the existing MCP branch without semantic filters. It was discovered during #5349 review; that PR's new semantic path needs the shared counting semantics, while changing the established non-semantic route is a separate follow-up.
Reproduction and observed results
Observed on macOS arm64 with the repository-built cdidx 1.49.0, Debug/net8.0, and the canonical database matching commit f90640d76f65211901e6ba6d270cd0ecf2e44641.
After initializing the MCP server with --db .cdidx/codeindex.db, call:
{"name":"search","arguments":{"query":"Query","exact":true,"path":"src/CodeIndex/Mcp/McpToolHandlers.Query.Search.cs","requireBefore":"var","guardWindow":8,"countOnly":true}}
MCP reports count:38, total:38, truncated:false, and a top_files count of 38 for the file. No origin, excludeOrigin, or result-kind/fixture filter is supplied, so the existing non-semantic handler executes.
The corresponding CLI request reports count:7, file_count:1, degraded:false, authoritative_count:true, and exit 0:
dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll search Query --exact --path src/CodeIndex/Mcp/McpToolHandlers.Query.Search.cs --require-before var --guard-window 8 --count --json --db .cdidx/codeindex.db
Counts describe this indexed checkout and may change as the source file changes. The mismatch follows from ExecuteSearch counting reader.Search rows directly, while the CLI uses CountFilteredSearchResultUnits for guarded non-token-boundary counts.
Expected behavior and validation
- Reuse the CLI's count-unit semantics for guarded MCP count requests, including the per-file histogram.
- Preserve bounded candidate scans, count authority, semantic-filter behavior, and the existing token-boundary distinction.
- Add a small shared fixture with multiple guarded matches in one chunk plus multiple chunks/files, and compare CLI/MCP counts with and without token-boundary mode on .NET 8/9.
- Update the affected bilingual documentation and add a changelog fragment.
Duplicate checks: reviewed all current open issue titles and searched MCP search count and guard count. #5357 concerns unknown-origin authority in CLI count output, a different issue.
Problem
MCP
searchwith guard filters andcountOnly:truecounts matched display rows, while CLI guarded count output counts distinct indexed result units. Multiple guarded matches in one indexed chunk therefore inflate the MCP count and itstop_fileshistogram.This affects the existing MCP branch without semantic filters. It was discovered during #5349 review; that PR's new semantic path needs the shared counting semantics, while changing the established non-semantic route is a separate follow-up.
Reproduction and observed results
Observed on macOS arm64 with the repository-built cdidx 1.49.0, Debug/net8.0, and the canonical database matching commit
f90640d76f65211901e6ba6d270cd0ecf2e44641.After initializing the MCP server with
--db .cdidx/codeindex.db, call:{"name":"search","arguments":{"query":"Query","exact":true,"path":"src/CodeIndex/Mcp/McpToolHandlers.Query.Search.cs","requireBefore":"var","guardWindow":8,"countOnly":true}}MCP reports
count:38,total:38,truncated:false, and atop_filescount of 38 for the file. Noorigin,excludeOrigin, or result-kind/fixture filter is supplied, so the existing non-semantic handler executes.The corresponding CLI request reports
count:7,file_count:1,degraded:false,authoritative_count:true, and exit 0:Counts describe this indexed checkout and may change as the source file changes. The mismatch follows from
ExecuteSearchcountingreader.Searchrows directly, while the CLI usesCountFilteredSearchResultUnitsfor guarded non-token-boundary counts.Expected behavior and validation
Duplicate checks: reviewed all current open issue titles and searched
MCP search countandguard count. #5357 concerns unknown-origin authority in CLI count output, a different issue.