Summary
Five MCP tools in tools/analysis_tools.py raise AttributeError on every invocation in v2.3.2. The path-resolution code passes a str/None into a function that expects pathlib.Path, and additionally assigns a tuple to a variable that's then used as a GraphStore. The combination means none of the affected tools have ever returned a result on this version.
Affected tools
get_hub_nodes_tool
get_bridge_nodes_tool
get_knowledge_gaps_tool
get_surprising_connections_tool
get_suggested_questions_tool
(All *_func implementations in code_review_graph/tools/analysis_tools.py.)
Reproduction
pipx install code-review-graph==2.3.2
cd /path/to/some/git/repo
code-review-graph init --platform claude-code
code-review-graph build
# Then from any MCP client:
get_hub_nodes_tool(repo_root="/path/to/some/git/repo")
# → Error calling tool 'get_hub_nodes_tool': 'str' object has no attribute 'resolve'
get_hub_nodes_tool()
# → Error calling tool 'get_hub_nodes_tool': 'NoneType' object has no attribute 'resolve'
Same crash with both repo_root provided and omitted. Other tools (get_review_context_tool, find_large_functions_tool, list_graph_stats_tool, query_graph_tool) work correctly against the same graph, so this is specific to the five listed.
Root cause
In tools/analysis_tools.py (e.g. get_hub_nodes_func, lines 17–42):
def get_hub_nodes_func(repo_root: str = "", top_n: int = 10) -> dict[str, Any]:
root = _validate_repo_root(repo_root) # <-- bug 1
store = _get_store(str(root)) # <-- bug 2
hubs = find_hub_nodes(store, top_n=top_n)
Bug 1 — wrong type to validator. _validate_repo_root in tools/_common.py:61 is typed as (path: Path) -> Path and immediately calls path.resolve(). Callers here pass a str (or None, after main._resolve_repo_root returns None), triggering AttributeError.
Bug 2 — _get_store returns a tuple. _get_store in tools/_common.py:81 was changed to return tuple[GraphStore, Path]. These five callers assign the tuple to a single name store and pass it to find_*_nodes(store: GraphStore, …) — even after fixing bug 1, the next call would fail with a different AttributeError on the tuple.
Other tools across the package follow the working pattern (store, root = _get_store(repo_root)) which suggests these five analysis_tools.py helpers were missed when the helpers' signatures were tightened.
Suggested fix
Replace the two-line setup in each of the five *_func helpers with the pattern the rest of the codebase uses:
store, _ = _get_store(repo_root)
_get_store already calls _validate_repo_root(Path(repo_root)) internally and falls back to find_project_root() when repo_root is empty/None, so the explicit pre-validation is redundant.
A regression test that calls each of the five tools against a real built graph fixture (the test could just use the package's own repo) would prevent the next reoccurrence. Right now the failure is only visible at MCP-call time.
Environment
code-review-graph 2.3.2 (PyPI)
- Python 3.12.3 / Ubuntu 24.04
- Installed via
pipx install code-review-graph
- Graph: 4521 nodes / 45651 edges / 536 files (JS + bash + Python). Other tools query it without issue.
Summary
Five MCP tools in
tools/analysis_tools.pyraiseAttributeErroron every invocation in v2.3.2. The path-resolution code passes astr/Noneinto a function that expectspathlib.Path, and additionally assigns a tuple to a variable that's then used as aGraphStore. The combination means none of the affected tools have ever returned a result on this version.Affected tools
get_hub_nodes_toolget_bridge_nodes_toolget_knowledge_gaps_toolget_surprising_connections_toolget_suggested_questions_tool(All
*_funcimplementations incode_review_graph/tools/analysis_tools.py.)Reproduction
Same crash with both
repo_rootprovided and omitted. Other tools (get_review_context_tool,find_large_functions_tool,list_graph_stats_tool,query_graph_tool) work correctly against the same graph, so this is specific to the five listed.Root cause
In
tools/analysis_tools.py(e.g.get_hub_nodes_func, lines 17–42):Bug 1 — wrong type to validator.
_validate_repo_rootintools/_common.py:61is typed as(path: Path) -> Pathand immediately callspath.resolve(). Callers here pass astr(orNone, aftermain._resolve_repo_rootreturnsNone), triggeringAttributeError.Bug 2 —
_get_storereturns a tuple._get_storeintools/_common.py:81was changed to returntuple[GraphStore, Path]. These five callers assign the tuple to a single namestoreand pass it tofind_*_nodes(store: GraphStore, …)— even after fixing bug 1, the next call would fail with a differentAttributeErroron the tuple.Other tools across the package follow the working pattern (
store, root = _get_store(repo_root)) which suggests these fiveanalysis_tools.pyhelpers were missed when the helpers' signatures were tightened.Suggested fix
Replace the two-line setup in each of the five
*_funchelpers with the pattern the rest of the codebase uses:_get_storealready calls_validate_repo_root(Path(repo_root))internally and falls back tofind_project_root()whenrepo_rootis empty/None, so the explicit pre-validation is redundant.A regression test that calls each of the five tools against a real built graph fixture (the test could just use the package's own repo) would prevent the next reoccurrence. Right now the failure is only visible at MCP-call time.
Environment
code-review-graph2.3.2 (PyPI)pipx install code-review-graph