「auth.pyを変更したけど、影響範囲はどこまで?」
PRレビューで毎回考えるこの問いに、私はこれまでgrep -rと人力で答えていました。30分かけて関連ファイルを洗い出し、AIレビューにコンテキストとして渡す。多くのエンジニアが同じ作業をしているはずです。
ところが先月、コードベースをナレッジグラフ化してMCP経由でAIレビューに繋いでみたところ、この30分が2秒になりました。しかもAIが読むコンテキストは1/8に減り、レビューの精度は明らかに上がりました。
本記事ではコードKG(Knowledge Graph)×AIコードレビューの実装パターンを共有します。Tree-sitterでASTを抽出し、MCPでAIに渡すまでの最短パスです。
なぜ「全ファイル読ませる」が破綻するのか
まず問題の構造を整理します。AIコードレビューのデフォルトは、変更diff+関連ファイル全部、です。
PRの差分: 200行
+ 念のため関連しそうなファイル: 50個(150,000トークン)
= AIに渡すコンテキスト: 約160,000トークン
Claude 3.5 Sonnetの上限は200Kトークンです。1PRで上限の80%を使い切ります。結果はこうなります。
- レビュー精度が落ちる(情報過多で焦点が散る)
- トークンコストが膨らむ(1PRあたり数十円〜数百円)
- 速度が落ちる(コンテキスト処理に時間がかかる)
「念のため大量に渡す」がAIレビューの最大のボトルネックです。
コードKGが解く問題
コードナレッジグラフは、コード構造を関数・クラス・呼び出し関係のグラフとして持ちます。Tree-sitterでASTを抽出し、グラフDBに格納します。
ノード: 関数、クラス、ファイル、テスト
エッジ: 呼び出し、継承、import、テストカバレッジ
これをMCP経由でAIに公開すると、AIは「この変更の影響範囲」をグラフ探索で2秒で計算します。grep -rと違い、関数の呼び出しチェーンを正確に追えます。
私が試したcode-review-graphの公式ベンチマークでは、レビュー時のトークン消費が6.8倍削減、日常コーディングタスクで49倍削減を記録しています。
私が試した主要OSSはcode-review-graph、CodeGraphContext、Codebase-Memory(arxiv論文)の3つです。Codebase-Memoryは83%の回答品質を維持しつつトークン10倍削減、ツール呼び出し2.1倍削減、と論文で報告しています。
30分で動かす最小実装
最小構成で動くようにする手順を共有します。Pythonプロジェクトを想定します。
Step 1: Tree-sitterでASTを抽出
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
PY_LANGUAGE = Language(tspython.language())
parser = Parser(PY_LANGUAGE)
with open("app/auth.py", "rb") as f:
tree = parser.parse(f.read())
def walk(node, depth=0):
if node.type in {"function_definition", "class_definition", "call"}:
name = node.child_by_field_name("name")
if name:
print(" " * depth + f"{node.type}: {name.text.decode()}")
for child in node.children:
walk(child, depth + 1)
walk(tree.root_node)
これだけで関数定義・クラス定義・呼び出し関係を抽出できます。Tree-sitterは66言語に対応しており、TypeScript/Go/Rustでも同じ構造で書けます。
Step 2: グラフDBに格納
私はSQLiteでまず動かすのを推奨します。Neo4jはオーバーキルです。
CREATE TABLE nodes (
id INTEGER PRIMARY KEY,
kind TEXT, -- 'function' | 'class' | 'file'
name TEXT,
file_path TEXT,
start_line INTEGER,
end_line INTEGER
);
CREATE TABLE edges (
src INTEGER,
dst INTEGER,
kind TEXT, -- 'calls' | 'imports' | 'inherits'
FOREIGN KEY (src) REFERENCES nodes(id),
FOREIGN KEY (dst) REFERENCES nodes(id)
);
ノード数が10万を超えるまではSQLiteで余裕があります。私の社内モノレポ(30万行)でも、グラフサイズは数十MBで収まりました。
Step 3: blast radius関数を実装
「この関数を変更したら、どのファイルが影響を受けるか」を計算する関数です。
def blast_radius(func_name: str, max_hops: int = 3) -> dict:
"""指定関数のblast radiusをBFSで計算"""
visited = {func_name}
frontier = {func_name}
layers = []
for hop in range(max_hops):
next_frontier = set()
for node in frontier:
callers = db.execute(
"SELECT src.name FROM edges e "
"JOIN nodes src ON e.src = src.id "
"JOIN nodes dst ON e.dst = dst.id "
"WHERE dst.name = ? AND e.kind = 'calls'",
(node,)
).fetchall()
for (caller,) in callers:
if caller not in visited:
next_frontier.add(caller)
visited.add(caller)
layers.append({"hop": hop + 1, "nodes": list(next_frontier)})
frontier = next_frontier
if not frontier:
break
return {"target": func_name, "layers": layers}
呼び出しチェーンを逆方向に追います(誰が呼んでいるか)。3ホップ程度で大半の影響範囲をカバーできます。
Step 4: MCPサーバーとして公開
from mcp.server import Server
from mcp.types import Tool, TextContent
server = Server("code-kg")
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="blast_radius",
description="指定関数のblast radius(影響範囲)を返す",
inputSchema={
"type": "object",
"properties": {
"function": {"type": "string"},
"max_hops": {"type": "integer", "default": 3},
},
"required": ["function"],
},
),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "blast_radius":
result = blast_radius(arguments["function"], arguments.get("max_hops", 3))
return [TextContent(type="text", text=json.dumps(result, indent=2))]
最小構成のMCPサーバーです。Claude CodeやCursorに登録すれば、AIが必要に応じてblast_radiusツールを呼び出します。
AIレビューでの実際の変化
導入前と導入後で、私のチームのレビューフローはこう変わりました。
Before(KGなし)
1. PRが上がる
2. レビュアーが diff を読む
3. 「auth.pyの変更って他に影響ない?」と不安
4. 関連ファイルを手動 grep(30分)
5. 全部コピーしてAIレビューに渡す(160Kトークン)
6. AIが情報過多で焦点を外す、汎用コメントが返る
7. 見落としがあり、後日バグ発覚
After(KGあり)
1. PRが上がる
2. AIがblast_radius自動実行(2秒)
3. 影響を受ける7ファイル + リスクスコア7.2/10
4. AIにそれだけ渡す(18Kトークン)
5. 焦点の絞られた具体的なレビューが返る
6. 高リスク箇所を集中レビュー
時間圧縮よりも、レビューの質的変化の方が大きいと私は感じています。AIが「念のため」と「本当に必要」を区別できるようになると、コメントの精度が一段上がります。
既存ツールとの組み合わせ
ゼロから実装しなくても、OSSが充実しています。私が試した3つを紹介します。
| ツール | 特徴 | おすすめ |
|---|---|---|
| code-review-graph | Claude Code/Cursor自動連携、22 MCPツール | ◎ 最初に試すならこれ |
| CodeGraphContext | CLI + MCP、Neo4jベース | 大規模コードベース向け |
| graphify | Claude/Codex/Gemini対応、66言語 | マルチエージェント向け |
# 最短デモ(code-review-graph)
pip install code-review-graph
code-review-graph build ./my-project
code-review-graph install # Claude Code/Cursorを自動検出
Claude Code/Cursor/Windsurf/Zedを自動検出してMCPサーバー設定までやってくれます。3コマンドでAIレビューがblast radius対応になります。
GitHub Actionで自動化する
PRを開くと自動的にblast radiusコメントが投稿される構成も組めます。code-review-graphはdiff-radiusサブコマンドで「base〜head間の影響範囲」を直接出せるので、Actionsから叩いてactions/github-scriptでPRコメント化するだけです。
PR作成と同時に「影響ファイル7件、リスクスコア7.2/10」のコメントが付くと、レビュアーは数値を見て優先度を即決できます。私のチームでは、リスクスコア6以上のPRは「2人レビュー必須」というラベル付けも自動化しています。
落とし穴と対策
私がハマった3つの落とし穴も共有します。
落とし穴1 動的呼び出しが追えない
# 静的解析では追えない
fn = globals()[fn_name]
fn(args)
Pythonのgetattr / globals()、JSのrequire(dynamic)は静的解析では捕まえられません。私は動的呼び出しを警告として記録するルールにしています。完璧を諦め、人間に「ここは確認してね」と渡す方針です。
落とし穴2 マイクロサービス境界
サービスAからサービスBへのHTTP呼び出しは、コードKGでは追えません。OpenAPIスキーマからエッジを補完する仕組みを別途用意する必要があります。
落とし穴3 グラフ更新コスト
毎PRでフルビルドすると遅いです。差分ビルド(変更ファイルだけ再パース)の仕組みは必須です。code-review-graphは差分ビルド対応しているので、私はそれに乗っかっています。
まとめ
コードベースをナレッジグラフ化すると、AIレビューが「念のため大量に読む」から「必要なものだけ正確に読む」に変わります。
- Tree-sitterで66言語のAST抽出が可能
- SQLiteで10万ノードまでなら十分
- MCP経由でAIエージェントに公開すれば自動でツール呼び出し
- code-review-graphなら3コマンドで動作開始
- トークン消費6.8倍削減、レビュー品質が同時に向上
私のチームは導入1ヶ月で、AIレビューのコメント精度が体感で1.5倍以上になりました。30分かけていた手動grepが、2秒のツール呼び出しに置き換わるだけで、レビュー文化が変わります。
あなたのプロジェクトのAIレビューは「全ファイル読ませる」になっていませんか。一度code-review-graph buildを叩いてみると、世界が変わるかもしれません。
コードKGの理論と実装をさらに掘り下げたい方へ。Zenn Book「ナレッジグラフ実践ガイド」の第10章で、本記事のMCP統合からエンタープライズGraphRAGまでを体系的に解説しています。
https://zenn.dev/kenimo49/books/knowledge-graph-practical-guide
参考
- code-review-graph(OSS, Tree-sitter + MCP)
- CodeGraphContext(Neo4jベース)
- graphify(Claude/Codex/Gemini対応)
- Codebase-Memory: Tree-Sitter-Based Knowledge Graphs for LLM Code Exploration via MCP(arxiv, 学術論文)
- code-review-graph公式サイト
