{
  "markdown": "# graphlens-mcp\n\n<!-- mcp-name: io.github.Neko1313/graphlens-mcp -->\n\n[![CI](https://github.com/Neko1313/graphlens-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Neko1313/graphlens-mcp/actions/workflows/ci.yml)\n[![Docs](https://img.shields.io/badge/docs-github%20pages-blue)](https://neko1313.github.io/graphlens-mcp/)\n[![Python](https://img.shields.io/badge/python-%E2%89%A53.13-blue)](https://www.python.org/)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n\nA free, MIT-licensed [MCP](https://modelcontextprotocol.io) server that gives coding\nagents (Claude Code, Cursor, and compatible clients) a **semantic code graph** of your\nproject — symbols, cross-file calls, references, imports and cross-language boundaries.\n\nInstead of reading files top-to-bottom or grepping for names, the agent **navigates the\nstructure**: *who calls this function*, *what does it depend on*, *what breaks if I change\nits signature*. It is a thin runtime layer over the\n[`graphlens`](https://github.com/Neko1313/graphlens) analysis engine: `graphlens` provides\nthe mechanisms (parsing, stable node identity, resolvers); `graphlens-mcp` owns the storage,\nfreshness and the agent-facing surface.\n\n📖 **Documentation:** <https://neko1313.github.io/graphlens-mcp/>\n\n> Status: early. The core navigation works; see [Known limitations](#known-limitations).\n\n## Why\n\nCoding agents discover structure the slow way — grep, glob, read one file at a time —\nrebuilding call paths by hand before the real work even starts. The motivation is the same\nas every other code-context tool: **stop the agent from grepping.** The *approach* is what\nsets `graphlens` apart.\n\nMost tools answer this by building their **own** model of your code — an ad-hoc graph\nstitched from heuristics, where every tool maps the codebase a little differently and\nnothing is authoritative. `graphlens` takes the opposite bet: it builds on the **language's\nown real analysis engines** — `rust-analyzer`, `gopls`, the TypeScript compiler, the bundled\n`ty` type engine — the LSP-grade tooling the industry already trusts. That yields a *stable,\nreal* picture of the project (who actually calls what, across files and languages), not a\nbespoke approximation. And a stable foundation is something you can build on: attach context\nto the parts of a change that matter, auto-extract semantic clusters, answer impact\nquestions reliably.\n\nThat foundation is the [`graphlens`](https://github.com/Neko1313/graphlens) engine —\nparsing, stable node identity, and the resolvers. **`graphlens-mcp` is a smart, agent-facing\nlayer over it**, and — honestly — a worked example of how to *use* the engine: it persists\nthe graph (so the whole thing isn't held in memory), adds a semantic + clustering layer on\ntop, keeps it fresh as you edit, and exposes it to agents as navigation tools plus a bundled\nskill. From that example it is growing into a **self-sufficient system** — one that, measured\nagainst the market's giants, aims for **stable, reproducible** results: better in some places,\nworse in others, but honest about which (see [How it compares](#how-it-compares)).\n\n## How it compares\n\n`graphlens-mcp` ships with a reproducible **A/B benchmark** ([`benchmarks/`](benchmarks/README.md))\nthat drives the same agent against three interchangeable code-context MCP servers —\n`graphlens`, `semble` (semantic search), and `codegraph` (graph index) — plus a **no-tools\ncontrol** that measures how much each server adds over the model's own memory. It runs across\nreal **Go / Rust / Python / TypeScript** codebases and grades answers **deterministically\nagainst oracle gold** (no LLM judge), stratified into SIMPLE lookups vs HARD impact /\ncross-file questions, and reports accuracy **alongside** token / tool-call / dollar cost —\nbecause a cheaper arm at equal accuracy wins.\n\n<!-- BENCHMARK-RESULTS:START -->\n> 📊 **Results** (10 repos · 3 models, strong → genuinely weak · ~2,400 graded runs —\n> full breakdown, significance tests and reproduction steps at\n> [**docs: Benchmarks**](https://neko1313.github.io/graphlens-mcp/benchmarks)):\n>\n> | | SIMPLE accuracy | HARD accuracy | HARD tokens (median) | HARD completion |\n> |---|---|---|---|---|\n> | **graphlens** | 0.980 – 1.000 | 0.899 – 0.921 | **22.4k – 34.1k** | **≥ 0.959 on every model** |\n> | codegraph | 0.912 – 0.990 | 0.655 – 0.939 | 23.2k – 70.0k | drops to 0.765 on the weakest model |\n> | semble | 0.647 – 0.961 | 0.555 – 0.850 | 21.6k – 74.9k | drops to 0.688 on the weakest model |\n> | none (control) | 0.366 – 0.681 | 0.453 – 0.685 | 0.1k – 0.9k | — |\n>\n> Accuracy alone hides the number that matters to a bill: **tokens paid per task**. graphlens's\n> HARD-tier token spend stays flat (22k–34k) whether the driving model is strong or weak;\n> codegraph's and semble's balloon past 70k on the weakest model — more than double\n> graphlens's ceiling — for a *worse* answer, not a better one. graphlens is the only arm that\n> stays clearly ahead of the no-tools control **and** keeps completion above 0.95 at every\n> model tier: on the weakest model tested (gpt-oss-20b) it holds 0.900 HARD accuracy at\n> roughly **half the token cost** of codegraph. Pairwise Wilcoxon signed-rank tests (matched by\n> task) confirm the gap is statistically significant on the weaker models, not an artifact of a\n> few outlier tasks — see the notebook for per-model p-values and effect sizes.\n<!-- BENCHMARK-RESULTS:END -->\n\n## Install\n\nRequires **Python ≥ 3.13** (a constraint inherited from `graphlens`).\n\n```bash\nuv tool install graphlens-mcp      # or: pipx install graphlens-mcp\n```\n\nPython language analysis works out of the box (the `ty` type engine ships as a\ndependency). Other languages parse immediately and unlock full cross-file semantics once\ntheir toolchain is present (Node for TypeScript, the Go toolchain, etc.); without it that\nlanguage is reported as `degraded` rather than blocking `init`.\n\n## Quickstart (two commands)\n\n```bash\nuv tool install graphlens-mcp        # 1. install\ncd your-project && graphlens-mcp init  # 2. index + configure your agent\n```\n\n`init` detects the project's languages, indexes the code into a local graph, writes the\nMCP server entry into your agent's config and installs the navigation skill. You do **not**\nrun `serve` yourself — your agent launches it from the config. Restart the agent and ask\nit something like *\"what breaks if I change the signature of `create_order`?\"*.\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `graphlens-mcp init` | Detect languages → toolchain doctor → full index → configure agents → install skill |\n| `graphlens-mcp serve` | Start the MCP server over stdio. **Launched by the agent**, not by you |\n| `graphlens-mcp status` | Show detected languages, toolchain status, and graph size/freshness |\n| `graphlens-mcp reindex` | Force a full rebuild (e.g. after installing a new toolchain) |\n| `graphlens-mcp remove` | Deregister from agents and (with `--purge-db`) delete the local graph |\n\nUseful `init` flags: `--root <dir>`, `--agent claude_code --agent cursor` (repeatable),\n`--no-agent`, `--no-skills`, `--db <path>`.\n\nThe graph lives at `<project>/.graphlens/graph.db` (SQLite). It is a regenerable cache —\nsafe to delete; `reindex` rebuilds it. Add `.graphlens/` to your VCS ignore (the bundled\n`init` flow assumes it is not committed).\n\n## Supported languages\n\n| Language | Engine | Out-of-box |\n|---|---|---|\n| Python | `ty` (bundled) | Full semantics immediately |\n| TypeScript | Node bridge | `degraded` without Node; full semantics with Node installed |\n| Go | Go toolchain | `degraded` without toolchain |\n| Rust | SCIP / rust-analyzer | `degraded` without toolchain |\n| PHP | PHP parser | `degraded` without toolchain |\n\n`graphlens-mcp status` reports the actual resolver status per language. When a toolchain is\nmissing, that language is reported as **degraded** (parsed structure, calls/types not fully\nresolved) with an install hint — it never blocks `init`.\n\n## Agent tools\n\nThree tools — everything a symbol or file needs comes back as a navigable graph **node**,\nnot a dead grep line. Each response carries a graph-quality status (`ok` | `degraded`) so the\nagent never mistakes a partial answer for a complete one, plus an `indexing` flag (`true`\nwhen a background reindex is running, so edges may be temporarily incomplete).\n\n| Tool | Purpose |\n|---|---|\n| `search` | Find code by NAME, CONTENT, or MEANING — **the one way in**. Returns graph nodes with their signature (often enough to answer without a follow-up call). Content is matched literally, not as a regex. Scope with `path_glob` (e.g. `\"tests/*\"`, `\"*.ts\"`, `\"!tests/*\"` to exclude a subtree); set `exhaustive=true` to list every matching file (no cap, no signatures) instead of the ranked top-N |\n| `relations` | A symbol's neighbourhood in one call: callers, callees, implementors/subclasses, and non-call references — each with its signature. **The** impact-analysis tool (\"what breaks if I change X?\", \"what implements X?\") |\n| `info` | Read a specific target: a symbol (node id or name) → source + signature + location; a file path → its symbol outline |\n\n`search` and `relations` accept either a symbol **name** or a node id directly — you don't\nneed to look up a node id first. Both cap their response size (a large hit set is ranked by\nrelevance via a small bundled embedding model, not just truncated) and surface true counts\n(`callers_total`, `references_total`, …) when a list is capped, so the agent sees \"15 shown\nof 22\" instead of guessing. If the embedding model can't be fetched (e.g. a first run with no\nnetwork), search transparently falls back to name/content matching.\n\n## Freshness model\n\nA single mechanism keeps the graph current: a **filesystem watcher** (`serve` starts it by\ndefault; disable with `--no-watch`). When a file changes on disk the server re-indexes the\n**connected set** — the changed file plus the files that import it and the files it imports —\nwith one full analyze, so cross-file edges are rebuilt correctly rather than left partial.\nDeleting a file prunes its symbols and refreshes its importers. There is no polling and no\nstructure-only \"skeleton\" phase: every (re)index produces the full graph the resolver can\ngive. As a backstop, a tool that touches a file the watcher hasn't processed yet triggers the\nsame connected re-index on access.\n\nFiles created, deleted or edited *while the server was down* are invisible to an event-based\nwatcher, so `serve` runs a one-shot **reconcile** at startup: it scans the project, indexes\nnew files, prunes vanished ones, and refreshes any that changed — then hands off to the\nwatcher.\n\n## Known limitations\n\n- **Connected-set re-link, deep ripples:** the watcher re-links the *connected set* of a\n  change (the changed file plus its direct importers and imports), not the entire project. A\n  rename that ripples through many indirection layers may need a full `reindex` for an exact\n  graph. Creating a file that an *unchanged* file already imports is handled — a second\n  importer pass re-links that importer once the new file is indexed.\n- **Cross-language edges on incremental edits:** synthesized `COMMUNICATES_WITH` edges are\n  re-synthesized for every boundary a re-indexed file touches, so a new or moved\n  exposer/consumer is linked without a full `reindex`. A change that leaves a boundary\n  entirely (a file that stops exposing an endpoint others still consume) may still need a\n  full `reindex` for an exact cross-language view; the boundary-based query resolves\n  connections regardless.\n\n## Uninstall\n\n`graphlens-mcp remove` deregisters the server from your agents; add `--purge-db` to also\ndelete the local `.graphlens/` cache.\n\n## Development\n\n```bash\nuv sync --all-groups   # install lint + test tooling\ntask check             # ruff + format-check + ty + bandit + pytest (the CI gate)\ntask docs:serve        # preview the docs site locally (needs Node + pnpm)\n```\n\nSee the [Architecture](https://neko1313.github.io/graphlens-mcp/architecture) and\n[Semantic search](https://neko1313.github.io/graphlens-mcp/design/semantic-search) pages on the\n[documentation site](https://neko1313.github.io/graphlens-mcp/) for the design and invariants.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 12260,
  "sha": "19a6f5e6e6585eaa691c7dd7a1465adbdb0c9b40878bd285d2fcb7378fbdd773",
  "repo_slug": "neko1313/graphlens-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_neko1313_graphlens_mcp_46520197/readme"
}