Skip to content

fix(mcp): rank symbol searches and report truncated pages - #75

Merged
knight22-21 merged 2 commits into
knight22-21:mainfrom
sundaysebasidian-byte:fix/search-pagination-38
Oct 13, 2026
Merged

knight22-21 merged 2 commits into
knight22-21:mainfrom
sundaysebasidian-byte:fix/search-pagination-38

Conversation

@sundaysebasidian-byte

Copy link
Copy Markdown
Contributor

Summary

Closes #38.

Substring symbol search currently applies an unordered 50-row cap before relevance or project filtering, so an exact run symbol can be omitted behind 60 partial matches. Rank exact names, then prefixes, then other matches in SQLite before limiting, with stable name/file/id ordering. Apply the existing kind and literal project-prefix filters before pagination, and return the complete filtered total plus truncated through MCP.

Append limit to the MCP tool's arguments with default 50 and an accepted range of 1–500. Preserve the existing list-returning StorageManager/QueryEngine APIs. The SQL window count keeps the page and total in one SQLite snapshot. Update the tool description, README and changelog, and add 26 real-SQLite/temporary-index cases.

Type of change

  • Bug fix
  • New feature or improvement
  • Performance
  • Documentation only
  • Refactor, tests or tooling (no behaviour change)

How was it tested?

On macOS with the existing Python 3.14.6 development environment, against main 6ee2ff6251af85f32dce90320b5ed956b98b1fa3 and isolated XDG/test directories:

  • Baseline full suite: 764 passed, 1 skipped.
  • Three regressions through the existing list APIs failed on the old implementation: exact match beyond row 50, prefix ranking and stable file tie-breaking. New API cases were excluded from the before-fix result.
  • Focused search/storage/query/MCP/path/embedding suites: 170 passed, 1 skipped.
  • Full suite with coverage and the 80% requirement: 790 passed, 1 skipped; coverage 89.47%.
  • Repository-wide ruff check codeprism/ tests/ and ruff format --check codeprism/ tests/: passed.
  • Touched-file mypy with --follow-imports=silent: the same 20 pre-existing diagnostics as main after removing line offsets; no new diagnostics, including in the new test file.
  • A real in-process MCP Client with the normal server lifespan retrieved the registered tool schema and called search_symbol on the issue fixture. Default limit 50 was advertised; limit=1 returned count=1, total=61, truncated=true, with run first. Direct default/limit-100 calls returned the expected cut/complete pages.
  • Independent review read the entire diff and issue requirements, reran all 26 new cases successfully, and verified the tested source hashes and exact mypy diagnostic multisets. No blocking findings remained.

Cases cover empty/below/exact/above-limit pages, limits 1/50/500, invalid direct-API limits and unknown kinds, filters before counting/capping, relative/absolute paths including literal %/_, and legacy serializer/semantic behavior.

Checklist

  • Tests added or updated for all changed behaviour.
  • ruff check and ruff format --check pass.
  • No new mypy errors in the files changed.
  • All existing tests pass (one existing skip).
  • Docstrings added or updated for public functions.
  • docs/changelog.md updated.
  • README/tool documentation updated.
  • Commit follows Conventional Commits.

Notes for reviewers

Completeness metadata and configurable limits apply to substring mode. Semantic search retains its existing top-20 neighbor cap, ordering, post-filtering and count/matches response shape; it ignores the new limit and omits total/truncated because a complete semantic total is unavailable. This keeps the separate embedding issues in #36 outside this fix. Existing literal startswith project-prefix semantics are preserved.

AI assistance: implementation, tests and documentation were prepared with Codex and independently reviewed by a separate Codex agent. No dependencies or software were added or installed. Local execution used macOS / Python 3.14.6 and existing FastMCP 4.0.10; other interpreter/platform/framework combinations were not run locally. Optional real embedding models/vector storage were not installed or exercised; semantic compatibility tests use lightweight components with actual indexed SQLite IDs. Mypy remains advisory and not fully green upstream.

@sundaysebasidian-byte
sundaysebasidian-byte marked this pull request as ready for review October 4, 2026 01:59
@knight22-21

Copy link
Copy Markdown
Owner

Thanks @sundaysebasidian-byte! PR #73 and PR #74 have just been merged into \main, which introduced a merge conflict (primarily in \docs/changelog.md). Could you please update your branch / rebase onto the latest \main\ to resolve the conflicts? Once updated and CI checks pass, we'll be ready to review and merge this.

@knight22-21 knight22-21 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Excellent implementation adding SQL ranking for symbol search, pagination limit parameter, and truncation metadata.

@knight22-21
knight22-21 merged commit d8d9152 into knight22-21:main Oct 13, 2026
4 checks passed
@knight22-21

Copy link
Copy Markdown
Owner

Merged, thank you @sundaysebasidian-byte! This adds ranking for symbol searches, pagination limits, and accurate truncation reporting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

search_symbol silently truncates at 50 unranked rows and can drop the exact match

2 participants