Phase 1 ticket T7. Depends on #652 (T4 index_repo).
Context
find_path answers "how does symbol A reach symbol B?" — useful for understanding indirect call chains and refactoring sequences. The underlying operation already exists: Graph.find_paths() (api/graph.py:535-579) and AsyncGraphQuery.find_paths() (api/graph.py:726-745). The CLI command cgraph paths (api/cli.py:317-335) already exposes it. This ticket is a thin async wrapper.
Scope
In:
api/mcp/tools/structural.py::find_path(source_id, dest_id, max_paths=10).
- Wraps
AsyncGraphQuery.find_paths() (api/graph.py:726-745).
- Returns a list of node-sequences, each representing a call path:
[
{"path": [{"id":"a","name":"a","label":"Function","file":"...","line":1}, ...]},
...
]
- Tests in
tests/mcp/test_find_path.py:
- Unit (mocked graph): assert path serialization shape.
- Integration: known path against T3 fixture (e.g.
entrypoint → service → repo → db) — assert the path exists in the result and has the expected length.
- No-path case: source and dest with no connecting path returns
[], not an error.
- CLI parity vs
cgraph paths: same input → same output.
- Protocol round-trip.
Out:
- Path ranking / shortest-path-only mode (deferred).
- Bidirectional path search.
- Cross-relation paths beyond the existing
find_paths Cypher (CALLS* only).
Files to create / modify
api/mcp/tools/structural.py — tool registration
- new
tests/mcp/test_find_path.py
Acceptance criteria
Dependencies
Out of scope (do NOT do in this PR)
- Shortest-path-only mode (the existing
find_paths returns all paths up to a depth limit).
- Bidirectional search.
- Cross-relation paths (only
CALLS per the existing implementation).
Notes for the implementer
- The wrapper should be ~20 lines. Real work is in
api/graph.py.
max_paths is a safety cap to prevent the agent from blowing the response size on highly-connected graphs. If find_paths already supports a limit param, forward it; otherwise add one.
- Reuse the protocol-test helper from T4.
Phase 1 ticket T7. Depends on #652 (T4 index_repo).
Context
find_pathanswers "how does symbol A reach symbol B?" — useful for understanding indirect call chains and refactoring sequences. The underlying operation already exists:Graph.find_paths()(api/graph.py:535-579) andAsyncGraphQuery.find_paths()(api/graph.py:726-745). The CLI commandcgraph paths(api/cli.py:317-335) already exposes it. This ticket is a thin async wrapper.Scope
In:
api/mcp/tools/structural.py::find_path(source_id, dest_id, max_paths=10).AsyncGraphQuery.find_paths()(api/graph.py:726-745).[ {"path": [{"id":"a","name":"a","label":"Function","file":"...","line":1}, ...]}, ... ]tests/mcp/test_find_path.py:entrypoint → service → repo → db) — assert the path exists in the result and has the expected length.[], not an error.cgraph paths: same input → same output.Out:
find_pathsCypher (CALLS*only).Files to create / modify
api/mcp/tools/structural.py— tool registrationtests/mcp/test_find_path.pyAcceptance criteria
source_id: str, dest_id: str, max_paths: int = 10.find_path(entrypoint, db)returns at least one path that traversesentrypoint → service → repo → db.[]— not an exception, not a 404.cgraph paths <src> <dst>and the MCP tool return the same paths for the same input.Dependencies
Out of scope (do NOT do in this PR)
find_pathsreturns all paths up to a depth limit).CALLSper the existing implementation).Notes for the implementer
api/graph.py.max_pathsis a safety cap to prevent the agent from blowing the response size on highly-connected graphs. Iffind_pathsalready supports a limit param, forward it; otherwise add one.