Skip to content

feat(core): port server/tools_query.py to backend-neutral queries#20

Merged
joy-software merged 1 commit into
developfrom
feature/duckdb-mcp-tools
Jun 1, 2026
Merged

feat(core): port server/tools_query.py to backend-neutral queries#20
joy-software merged 1 commit into
developfrom
feature/duckdb-mcp-tools

Conversation

@joy-software
Copy link
Copy Markdown
Contributor

Summary

Fourth PR in the Kuzu → DuckDB migration. The most-used MCP tool file (`symbol_lookup`, `find_callers`, `find_callees`, `imports_of`, `search_symbols`, `subgraph`) now uses backend-neutral helpers. Both backends return identical results for these tools.

What lands

File What's new
`core/protocol.py` 3 new helpers: `find_nodes`, `find_neighbors`, `reach_via_edge`
`core/db_kuzu.py` / `db_duckdb.py` All 3 helpers implemented. DuckDB uses composite JOINs for edge traversal + recursive CTE for transitive reach.
`server/tools_query.py` Every `conn.execute()` gone. All 6 MCP tools route through the helpers.
`tests/test_core/test_graph_helpers.py` 18 new parametrized tests covering find_nodes / find_neighbors / reach_via_edge on both backends.

End-to-end verification

3-function 2-file repo with `a.py` defining `helper` + `caller`, `b.py` importing helper:

Tool Kuzu DuckDB
`symbol_lookup('helper')` `{file: /a.py}` `{file: /a.py}`
`find_callers('helper')` `[caller, wrapper]` `[caller, wrapper]`
`imports_of('/b.py')` `[{/a.py, 'helper'}]` `[{/a.py, 'helper'}]`

Test count

274 → 292 (+18 new parity tests).

Not in this PR (follow-ups)

Fourth step of the Kuzu -> DuckDB migration. The most-used MCP tool
file (symbol_lookup, find_callers, find_callees, imports_of,
search_symbols, subgraph) now uses backend-neutral helpers. Both
backends answer these MCP tools identically.

What lands:

- codegraph/core/protocol.py: three new GraphDB methods covering the
  query patterns in tools_query.py.
  - find_nodes(label, where=..., contains=..., return_fields=...,
    limit=...) -> list[dict]
    Used by symbol_lookup + search_symbols. Both exact match (=) and
    substring (CONTAINS / LIKE) supported; multi-field substrings get
    OR'd, so search_symbols on TFResource matches when either name or
    type contains the query.
  - find_neighbors(edge_type, src_key=..., dst_key=..., src_where=...,
    dst_where=..., return_src=..., return_dst=..., return_edge=...)
    -> list[dict]
    Used by find_callers, find_callees, imports_of, who_imports. Result
    rows are flattened to {src_<field>: ..., dst_<field>: ...,
    edge_<field>: ...} so the caller can pick what they need without
    every tool reaching into Kuzu's "table.field" shape.
  - reach_via_edge(edge_type, start_key, max_depth=..., return_fields=...)
    -> list[dict]
    Used by subgraph at depth > 1. Backed by Cypher's `*1..n` path
    syntax on Kuzu and a recursive CTE on DuckDB.

- codegraph/core/db_kuzu.py + db_duckdb.py: all three helpers
  implemented on both backends. Edge tables in DuckDB use composite
  JOINs (e.g. `FROM edge_calls e, function a, function b WHERE
  e.from_id = a.id AND e.to_id = b.id`) so anchoring on either side
  and filtering by neighbor fields uses the same SQL shape.

- codegraph/server/tools_query.py: every conn.execute() call gone,
  the _rows import gone. Each of the six MCP tools (symbol_lookup,
  find_callers, find_callees, imports_of, search_symbols, subgraph)
  goes through one or two GraphDB helper calls and translates the
  result dicts into the tool's JSON payload.

- tests/test_core/test_graph_helpers.py: 18 new parametrized tests
  covering find_nodes (where + contains + multi-field OR + limit),
  find_neighbors (anchor on src, anchor on dst via where, edge props),
  and reach_via_edge (single hop + two-hop).

End-to-end verification on a 3-function 2-file repo:

  Kuzu:
    symbol_lookup helper       -> /tmp/.../a.py
    find_callers helper        -> [caller, wrapper]
    imports_of /b.py           -> [{ /a.py, 'helper' }]

  DuckDB (CGH_DB=duckdb):
    symbol_lookup helper       -> /tmp/.../a.py
    find_callers helper        -> [caller, wrapper]
    imports_of /b.py           -> [{ /a.py, 'helper' }]

  Identical results. 292 tests pass (was 274 + 18 new = 292).

What's NOT in this PR (next migration PRs):

- tools_viz.py (19 Cypher queries — bigger file, dedicated PR)
- tools_arch.py (3 queries)
- tools_docs.py (6 queries)
- analysis/{context_builder,dead_code}.py (5 queries)
- cli/commands_monitor.py (12 stats queries — separate task #10)
- federation.py (kuzu-direct opens — task #11)
@joy-software joy-software merged commit 778da29 into develop Jun 1, 2026
1 check passed
@joy-software joy-software deleted the feature/duckdb-mcp-tools branch June 1, 2026 22:12
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.

1 participant