{"slug": "i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs", "title": "I Replaced grep-Based Code Review with a Knowledge Graph + MCP. Here Are 3 Bugs Vector Search Missed.", "summary": "A developer replaced grep-based code review with a knowledge graph integrated via the Model Context Protocol (MCP), uncovering three bugs that vector search had missed. The graph retrieves code by structural relationships, such as dependencies and call flows, rather than semantic similarity, enabling the AI reviewer to identify issues like a schema-breaking change in an audit log handler. The setup reduced context tokens from 150,000 to 18,000 for a typical PR review.", "body_md": "For about a year, my AI code review setup looked like this: AI gets a PR, AI greps for related code, AI reads way too many files, AI says \"looks fine.\"\n\nIt mostly worked. Until the bugs that didn't show up in grep started shipping.\n\nThe problem wasn't the model. It was the retrieval. Vector search and keyword grep are great at finding files that *mention* `auth.py`\n\n. They're terrible at finding files that *depend on* `auth.py`\n\nthrough three import hops, an event bus, and a decorator. That's where the bugs live.\n\nI rewired the retrieval layer with a code knowledge graph plugged in through MCP. Three bugs surfaced in the first week that vector search had been quietly missing. Here's what changed and the bugs themselves.\n\nVector search retrieves by *semantic similarity*. \"Find code about authentication\" finds `auth.py`\n\n, `login.py`\n\n, `password_validator.py`\n\n. Useful.\n\nKnowledge graphs retrieve by *structural relationship*. \"What depends on `auth.py`\n\n?\" returns the call graph -- including `event_handlers/login_event.py`\n\n, which never mentions auth in its variable names but listens to a login event whose payload changes when `auth.py`\n\nchanges.\n\nBoth are valid. They answer different questions. The bugs that ship to production tend to live in the second question.\n\nThe Model Context Protocol (MCP), released by Anthropic in late 2024, lets you expose tools to a model in a standard way. By 2026 it's supported by Claude Code, Cursor, Windsurf, Zed, VS Code, and (as of GA in May 2025) the official MCP Registry hosts hundreds of servers.\n\nI used [code-review-graph](https://github.com/codelayers/code-review-graph), an open-source tool that builds a property graph of your codebase and exposes it as an MCP server. The setup is a three-line ritual:\n\n```\npip install code-review-graph\ncode-review-graph build ./my-project\ncode-review-graph install      # auto-detects Claude Code / Cursor / Windsurf\n```\n\nThe graph contains nodes for files, classes, functions, and tests, with edges for imports, calls, inheritance, decorates, listens-to, and tested-by. Once it's wired in, the AI can call MCP tools like:\n\n| Tool | What it answers |\n|---|---|\n`blast_radius(file)` |\nEvery file that depends on this one (N hops) |\n`flow_trace(func)` |\nWhere a function's output flows |\n`semantic_search(query)` |\nHybrid: vector + graph proximity |\n`community_detect()` |\nTightly-coupled modules |\n`risk_score(diff)` |\nNumerical risk of a change |\n`dead_code()` |\nUnreachable from any entry point |\n\nAnthropic's MCP rollout in 2025 also brought OAuth, prompts, and resource subscriptions, so the graph can push updates when files change instead of being re-queried each turn. That detail matters at scale -- code KGs are not cheap to walk, and stale snapshots are how teams ship bugs.\n\nBefore the graph, my AI reviewer was getting context like this:\n\n``` php\nPR diff: auth.py + 1 file\nReviewer context: grep for \"auth\" -> 50 related files\nTokens: ~150,000\n```\n\nAfter the graph, it gets this:\n\n``` php\nPR diff: auth.py + 1 file\nReviewer context: blast_radius(\"auth.py\", hops=2) -> 7 files\nTokens: ~18,000\n```\n\nThe first time I ran it, the AI answered the review question in two seconds with a 7-file context. I had spent 30 minutes the day before grepping the same answer by hand. That moment of \"what was I doing with my career\" is, I think, the actual product of harness engineering.\n\nBut cheaper context isn't the interesting part. The interesting part is which bugs the graph surfaced that grep + vector had missed.\n\nThe diff was small. `auth.py`\n\nadded a `device_id`\n\nfield to its login event payload.\n\nVector search retrieved `login.py`\n\n, `auth_test.py`\n\n, `password_validator.py`\n\n-- the obvious neighbors. The reviewer approved.\n\nThe graph retrieved one extra file: `event_handlers/audit_log.py`\n\n. It listens to `login_event`\n\nand serializes the payload to a fixed schema in S3. Adding a new field broke the schema validator on every login. Production caught fire 90 minutes after merge.\n\n**Why grep missed it**: `audit_log.py`\n\ndoesn't import `auth.py`\n\n. It listens to an event bus. There's no string match on \"auth\" in the file.\n\n**What the graph saw**: `auth.py --emits--> login_event --consumed-by--> audit_log.py`\n\n. Three hops, zero string matches, but a clean structural path.\n\nA code review pass that doesn't follow event subscriptions is a code review pass that doesn't review event-driven systems.\n\nA teammate refactored `@with_retry`\n\nto add a backoff parameter. The default value was the same, so existing callers were \"unaffected.\" Reviewer approved on the strength of the unit tests.\n\nVector search retrieved files that explicitly imported the decorator. About a dozen.\n\nThe graph retrieved 31 files. The 19 the graph added were files that *applied* `@with_retry`\n\nto functions that, three calls deep, ended up calling a function whose retry behavior had subtly changed under load.\n\nOne of those callers was a payments webhook handler. Under retry, it now waited an extra 800ms before raising. That 800ms put it past the webhook timeout. We started losing about 0.4% of webhook deliveries silently.\n\n**Why grep missed it**: a decorator's effect propagates to every callsite of every decorated function. That's structural, not lexical.\n\n**What the graph saw**: `with_retry --decorates--> {19 functions} --called-by--> {31 files}`\n\n. The caller of a decorated function inherits the decorator's behavior, even if it never mentions the decorator's name.\n\nA migration changed the way one ID was hashed. The PR included a test that asserted the new hash. CI was green.\n\nThe graph showed something the test runner didn't: that test was in a file that *no longer ran in CI* because it had been moved out of the `tests/`\n\ndirectory three weeks earlier and nobody had updated the path glob in the CI config. The test passed because the test file was never executed. The PR landed with a broken hash that corrupted the migration's first 8,000 rows.\n\nThe graph had `dead_code()`\n\nfor unreachable functions and an inverse query for unreachable test files. I'd never asked it. After this PR, I added \"run `dead_code()`\n\non test files\" to the postflight check.\n\n**Why grep missed it**: grep doesn't know what CI runs. A test file's existence and a test file's execution are different facts.\n\n**What the graph saw**: `test_user_id.py`\n\nhad no incoming edge from any CI config and no `tested-by`\n\nedges from production code. It was a green file in a green repo that didn't actually test anything.\n\nI don't want to oversell this. Three things the graph is bad at, and you should keep using vector search or grep for:\n\nThe right setup is hybrid: vector search for \"find related concepts,\" graph for \"find dependents,\" grep for \"find this exact string.\" MCP makes that hybrid trivial because the model picks the tool per question.\n\nThree things have changed since I started doing this in late 2024:\n\n`@workspace`\n\nqueries instead of relying purely on file embeddings.`repomap`\n\nfor project-wide structural context. Not a graph, technically, but the same idea: structural retrieval beats lexical retrieval for cross-file changes.The pattern is converging. By the end of 2026, \"AI code review\" without a structural retrieval layer is going to look the way \"AI code review without a vector store\" looked in 2023. Quaint.\n\nIf you don't already have something like this, the pragmatic order is:\n\n`code-review-graph`\n\nor equivalent.`blast_radius`\n\nto the postflight checkI had the graph for two weeks before the first bug it caught -- the audit log schema break. I don't think I would have shipped that bug without it. I do know I shipped six versions of it across my career before I had this tool.\n\nFor the last decade, code search has meant \"embed the file and find similar embeddings.\" That's a fine answer to half the question. The other half -- \"what does this change *break*?\" -- is structural, and embeddings don't see it.\n\nThe graph sees it. MCP makes the graph addressable. Together they collapse most cross-file retrieval into a single, cheap query. The bugs that used to live in those gaps don't, anymore.\n\nWant the full rationale and more graph patterns?I cover graph schema design, GraphRAG vs vector RAG, and code-as-graph patterns in[Knowledge Graph Practical Guide: From RAG Limits to Graph-Native AI].", "url": "https://wpnews.pro/news/i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs", "canonical_source": "https://dev.to/kenimo49/i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs-vector-search-3djn", "published_at": "2026-08-30 06:41:41+00:00", "updated_at": "2026-08-30 06:52:09.371513+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-agents", "machine-learning", "large-language-models"], "entities": ["Anthropic", "Claude Code", "Cursor", "Windsurf", "Zed", "VS Code", "MCP Registry", "code-review-graph"], "alternates": {"html": "https://wpnews.pro/news/i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs", "markdown": "https://wpnews.pro/news/i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs.md", "text": "https://wpnews.pro/news/i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs.txt", "jsonld": "https://wpnews.pro/news/i-replaced-grep-based-code-review-with-a-knowledge-graph-mcp-here-are-3-bugs.jsonld"}}