Skip to content

bug(mcp): find_code repo_path filter resolves against server cwd, not indexed root — silently returns 0 results #1633

Description

@pm-dun86

Summary

find_code's repo_path filter silently returns 0 results when passed a repo name or relative path — with no error. It only works if the caller passes the exact absolute path that was used as the indexing root, which isn't what other tools return in a directly reusable form.

Root cause

Across src/codegraphcontext/tools/code_finder.py (find_by_function_name, find_by_class_name, find_by_variable_name, find_by_content, and ~20 other query sites), the filter is:

repo_filter = "AND node.path STARTS WITH $repo_path" if repo_path else ""

repo_path is used verbatim, with no normalization, as a raw string prefix against the stored .path property. Indexed node paths are stored as the absolute filesystem path used at indexing time (e.g. /data/repos/service-a/module/file.py). If a caller passes anything other than that exact absolute prefix — a bare repo name, a relative path, a path with different casing/trailing slash — the STARTS WITH comparison matches nothing, and the tool returns an empty result set indistinguishable from "no matches exist."

There's a separate, unrelated .resolve() call in code_finder.py (in audit_kotlin_call_ambiguity) that resolves a relative repo_path against the process cwd — that one has its own bug (wrong resolution base) but is a different code path from find_code/find_related_code, which has no resolution step at all.

Repro (verified locally, current main @ 810ea8a, v0.5.8, KuzuDB backend)

db = KuzuDBManager(db_path="<scratch-db>")
cf = CodeFinder(db)

cf.find_related_code("SomeClass", False, 2, repo_path=None)
# -> total_matches=4  (baseline: query alone works)

cf.find_related_code("SomeClass", False, 2, repo_path="service_a")
# -> total_matches=0  (short repo name — silently empty)

cf.find_related_code("SomeClass", False, 2, repo_path="/abs/path/to/repro-repo/service_a")
# -> total_matches=4  (exact absolute index root — works)

Repo was indexed via cgc index service_a (repo containing one file with a SomeClass class). cgc list afterward shows the repo's Path column as the absolute path — so even copying that exact displayed value works, but the natural/short form (repo name, or a relative path a user might type) does not, and nothing in the tool response indicates why.

Originally observed against a Neo4j-backed MCP server (0.5.3-ish); reproduced independently against KuzuDB on latest main — so this is backend-independent and still present at HEAD.

Impact

Any caller that filters find_code by repo — using the repo name from list_indexed_repositories/cgc list, or any path not byte-identical to the original indexing root — gets an empty result for real, indexed content, with no error or warning. This is worse than a hard failure since it looks like "no matches" rather than "wrong filter."

Suggested fix

  • Normalize both sides consistently: store/compare canonical (resolved, OS-normalized) paths, and normalize incoming repo_path the same way before filtering — resolving against the repo's known indexed root (looked up by repo name), not the caller's cwd or a raw string.
  • At minimum, when repo_path doesn't correspond to any indexed path (as a full prefix or by repo-name lookup), return a clear error/warning instead of a silent empty match.
  • Consider accepting repo name (as shown by list_indexed_repositories) as first-class input, resolved server-side to whatever root path is actually stored — most callers won't know or want to reconstruct the original absolute indexing path.

Environment

  • codegraphcontext version: 0.5.8 (main @ 810ea8a), also separately reproduced against a Neo4j-backed 0.5.3-class deployment
  • Graph DB backends tested: Neo4j (original report) and KuzuDB (this repro)
  • OS: macOS (Darwin)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    In progress
    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions