Phase 1 ticket T8. Depends on #652 (T4 index_repo).
Context
search_code is the agent's entry point for finding symbols by name when it doesn't yet have a symbol id. It's prefix search across the Searchable label, backed by FalkorDB's full-text index. The underlying operation already exists: Graph.prefix_search() (api/graph.py:325-358), AsyncGraphQuery.prefix_search() (api/graph.py:714-724), and async_prefix_search() (api/auto_complete.py:10-16). The CLI command cgraph search (api/cli.py:265-282) already exposes it.
Scope
In:
api/mcp/tools/structural.py::search_code(prefix, limit=20).
- Wraps
async_prefix_search() (api/auto_complete.py:10-16) or AsyncGraphQuery.prefix_search() (api/graph.py:714-724) — whichever produces the cleanest call site.
- Returns a typed result list:
[
{"id":"...","name":"foo","label":"Function","file":"src/x.py","line":12},
...
]
- Tests in
tests/mcp/test_search_code.py:
- Unit (mocked graph): empty result, single result, limit honored.
- Integration: assert known prefix hits against T3 fixture (e.g.
search_code("ent") returns a node with name entrypoint).
- CLI parity vs
cgraph search: same prefix → same hits.
- Protocol round-trip.
Out:
- Full-text / fuzzy search (only prefix in v1).
- Embedding / semantic search.
- Filter by label, file, or directory (could be added later via params).
Files to create / modify
api/mcp/tools/structural.py — tool registration
- new
tests/mcp/test_search_code.py
Acceptance criteria
Dependencies
Out of scope (do NOT do in this PR)
- Fuzzy / typo-tolerant search.
- Semantic / embedding search.
- Label or path filters (deferred — could be added via optional params).
Notes for the implementer
- The wrapper should be ~15 lines.
limit should be enforced server-side via the underlying prefix_search limit parameter — don't slice in Python after fetching everything.
- Reuse the protocol-test helper from T4.
Phase 1 ticket T8. Depends on #652 (T4 index_repo).
Context
search_codeis the agent's entry point for finding symbols by name when it doesn't yet have a symbol id. It's prefix search across theSearchablelabel, backed by FalkorDB's full-text index. The underlying operation already exists:Graph.prefix_search()(api/graph.py:325-358),AsyncGraphQuery.prefix_search()(api/graph.py:714-724), andasync_prefix_search()(api/auto_complete.py:10-16). The CLI commandcgraph search(api/cli.py:265-282) already exposes it.Scope
In:
api/mcp/tools/structural.py::search_code(prefix, limit=20).async_prefix_search()(api/auto_complete.py:10-16) orAsyncGraphQuery.prefix_search()(api/graph.py:714-724) — whichever produces the cleanest call site.[ {"id":"...","name":"foo","label":"Function","file":"src/x.py","line":12}, ... ]tests/mcp/test_search_code.py:search_code("ent")returns a node with nameentrypoint).cgraph search: same prefix → same hits.Out:
Files to create / modify
api/mcp/tools/structural.py— tool registrationtests/mcp/test_search_code.pyAcceptance criteria
prefix: str, limit: int = 20.expected.yamlpasses.cgraph search <prefix>and the MCP tool return the same set of node ids for the same prefix.Dependencies
Out of scope (do NOT do in this PR)
Notes for the implementer
limitshould be enforced server-side via the underlyingprefix_searchlimit parameter — don't slice in Python after fetching everything.