How the Graph Query Tool Handles Patterns like callers_of and tests_for in Code-Review-Graph

The graph query tool routes requests through the _QUERY_PATTERNS registry and executes specialized traversal algorithms for each query type, such as traversing CALLS edges for callers_of and combining transitive lookups with naming conventions for tests_for.

The graph query tool in the tirth8205/code-review-graph repository provides a Model-Code-Protocol (MCP) interface for running predefined queries against the code knowledge graph. It validates inputs against a central registry, resolves targets to concrete nodes using multiple resolution strategies, and dispatches to pattern-specific traversal logic. Understanding how it handles distinct patterns reveals how the system performs impact analysis and test discovery across Python, Java, and C++ codebases.

Pattern Registry and Validation

All supported query patterns are centrally defined in the _QUERY_PATTERNS dictionary located at lines 25–42 of code_review_graph/tools/query.py. This registry maps pattern names (such as callers_of and tests_for) to human-readable descriptions, driving both validation and documentation for the tool.

The public entry point query_graph_tool registered in code_review_graph/main.py at line 246 forwards client requests to the internal query_graph implementation. Before executing any traversal, query_graph validates that the requested pattern exists in _QUERY_PATTERNS (lines 56–64). If the pattern is unrecognized, the tool returns an error response listing all valid patterns.

Target Resolution Strategy

For most patterns, the tool attempts to resolve the target parameter to a concrete graph node through a multi-stage process implemented at lines 100–118:

  1. Direct lookup via store.get_node
  2. Path-based resolution for absolute file paths
  3. Java FQN disambiguation using _java_fqn_candidates
  4. General name search via store.search_nodes

If resolution fails—and the pattern is not consumers_of or file_summary—the tool returns a "not_found" status immediately.

Pattern-Specific Traversal Logic

Once the target resolves to a qualified name or node, an if … elif chain selects the specific traversal algorithm. These algorithms utilize the GraphStore API provided by code_review_graph/graph.py to navigate relationships.

Callers of Pattern

The callers_of pattern identifies all functions that invoke the target symbol. The implementation at lines 62–70 performs the following steps:

  • Iterates over edges where the target is the destination using store.iter_edges_by_target(qn)
  • Filters for edges of kind "CALLS" and deduplicates by the caller's qualified name
  • Adds each resolved caller node to the results
  • C++ overload handling: For C++ targets, an additional pass scans edges indexed by the bare function name to handle ambiguous overloads

Tests for Pattern

The tests_for pattern locates test nodes verifying the target through a two-phase approach (lines 25–41):

  1. Transitive test lookup: Calls store.get_transitive_tests(qn) to retrieve tests linked via explicit TESTS edges, marking indirect relationships with indirect: true
  2. Naming-convention fallback: If the target is not a C++ overload set, searches for common test prefixes (test_<name>, Test<name>). Matches found via this heuristic include inferred_by: "naming_convention" in the result metadata

Result Processing and Output

The tool applies result limiting and formatting before returning data to the client.

Capping and Detail Levels

The max_results parameter restricts the total number of logical results, while detail_level controls presentation (lines 65–73). When set to "minimal", the output truncates the visible results list to five items and reports the count of omitted entries in results_omitted.

Response Structure

The function returns a standardized dictionary containing:

  • status: "ok" or error codes
  • pattern, target, and human-readable description from _QUERY_PATTERNS
  • summary: A concise textual description of the query outcome
  • result_count, results_omitted, and the results list
  • edges: Included only when detail_level is "standard"

Usage Examples

The following examples demonstrate how to invoke the graph query tool for the patterns discussed:


# Find all callers of a Python function

await mcp.run_tool(
    "query_graph_tool",
    pattern="callers_of",
    target="my_module.my_function",
    detail_level="standard",
)

# Retrieve tests for a Java class using FQN

await mcp.run_tool(
    "query_graph_tool",
    pattern="tests_for",
    target="com.example.service.UserService",
    detail_level="minimal",
)

These calls return JSON structures matching the format described above, with results containing caller or test node dictionaries.

Summary

  • The graph query tool validates all requests against the _QUERY_PATTERNS registry in code_review_graph/tools/query.py before execution.
  • Target resolution uses a four-stage strategy including direct lookup, path resolution, Java FQN disambiguation, and name search.
  • The callers_of pattern traverses "CALLS" edges from store.iter_edges_by_target() with special handling for C++ overloads.
  • The tests_for pattern combines store.get_transitive_tests() with naming-convention heuristics to locate both explicit and inferred tests.
  • Results are capped by max_results and filtered by detail_level, returning standardized dictionaries with counts, summaries, and optional edge details.

Frequently Asked Questions

How does the graph query tool validate query patterns?

The tool checks the requested pattern against the _QUERY_PATTERNS dictionary defined at lines 25–42 of code_review_graph/tools/query.py. If the pattern is not found in this registry, the function returns an error listing all valid patterns (lines 56–64).

What happens if the target symbol cannot be resolved?

If the target resolution fails after attempting direct lookup, path-based search, Java FQN disambiguation, and general name search, the tool returns a "not_found" status. This applies to most patterns except consumers_of and file_summary, which may operate on unresolved targets.

How does callers_of handle C++ function overloading?

For C++ targets, the implementation performs an additional pass that scans edges indexed by the bare function name. It filters out ambiguous or unresolved overloads to ensure the returned callers actually match the specific target signature, as implemented in the pattern-specific logic at lines 62–70.

What is the difference between transitive tests and naming-convention tests in tests_for?

Transitive tests are discovered via explicit TESTS edges in the graph using store.get_transitive_tests(qn), and are marked with indirect: true when not directly connected. Naming-convention tests are found by searching for prefixes like test_<name> or Test<name> and include inferred_by: "naming_convention" metadata, indicating they were identified by heuristic rather than explicit relationship edges.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →