Skip to content

Repository files navigation

code-index

An MCP server that gives coding agents a pre-built symbol graph of a codebase — find_path, get_dependencies, get_dependents, get_symbol, search_symbols, search_source, get_index_coverage — instead of exploring it blind with grep/cat/read.

Point it at a repo and it indexes automatically (tree-sitter parses every symbol and its call/import/attribute edges into a compact bundle); the agent then queries that graph directly instead of re-deriving it turn by turn from raw file reads. The bundle stays current as the repo changes — incrementally, via a content-hash cache — instead of going stale the moment someone edits code. The server also tells connecting agents (via the MCP instructions field and per-tool descriptions) to prefer these tools over bash/grep/read for any file the graph covers.

Quick start

Requires Node 18+.

git clone <this-repo-url>
cd code-index
npm install
npm run build

Register it with Claude Code, from the code-index directory you just built:

# Per-project — registers code-index for the repo you run this from.
node packages/indexer/dist/cli.js register

# Global — same server, registered once, available in every project you open.
node packages/indexer/dist/cli.js register --scope user

That's it — the server auto-indexes whichever repo your Claude Code session is in on first connect, and the agent now has 7 tools available (see Tools below). Undo with claude mcp remove code-index -s <scope>.

Registration scopes, and how the server picks a repo

register runs claude mcp add for you with one of three scopes:

Scope Stored in Shared? Available in
local (default) ~/.claude.json, keyed to this project No, private to you This project only
project .mcp.json in the repo root Yes, via git This project only (for everyone who clones it)
user ~/.claude.json No, private to you Every project you open

Pass a path as the first argument (e.g. register /path/to/target/repo) to pin the registration to one specific repo regardless of scope — the same effect as an explicit --repo flag on the server.

--repo is optional; when omitted, the server resolves which repo to index in this order: --repo <path> if given, then CLAUDE_PROJECT_DIR (the current session's project root, set by Claude Code for every spawned MCP server — this is what makes a --scope user registration follow whichever project you're actually in), then the server process's working directory as a last resort for clients that don't set CLAUDE_PROJECT_DIR.

Register with any other MCP client

Point it directly at the repo you want indexed:

{
  "mcpServers": {
    "code-index": {
      "command": "node",
      "args": [
        "/absolute/path/to/code-index/packages/server/dist/main.js",
        "--repo", "${CLAUDE_PROJECT_DIR:-.}",
        "--watch"
      ]
    }
  }
}

${CLAUDE_PROJECT_DIR:-.} is Claude Code-specific .mcp.json variable expansion; other clients generally don't support it, so swap in an explicit absolute path for those.

--repo auto-indexes the target repo into <repo>/.code-index/ on first connect and reuses that bundle on later starts if the repo hasn't changed; add --watch to keep it updated in the background for the life of the server process. Prefer a static, separately-managed bundle instead? Index explicitly and point --okf at the output dir (--repo and --okf are mutually exclusive):

node packages/indexer/dist/cli.js index /path/to/target/repo --out ./okf
node packages/server/dist/main.js --okf ./okf

Tools

Tool Purpose
get_index_coverage() What fraction of the repo is covered by the graph — check this before falling back to grep/read.
find_path(source, target) Shortest dependency/call path between two symbols.
get_dependencies(symbol, depth?) What a symbol depends on: its imports and calls (fan-out).
get_dependents(symbol, depth?) What uses a symbol: callers and importers (fan-in).
get_symbol(name) Full source + metadata for one or more named symbols.
search_symbols(query) Search for symbols by name substring.
search_source(pattern) Full-text search across source bodies and raw file text.

Full parameter/response reference: docs/ARCHITECTURE.md.

Keeping the graph current

  • --watch on the server — hot-reloads the in-memory graph after every debounced reindex, no restart needed.
  • code-index watch <repo> — the same watch loop as a standalone process, for keeping a bundle fresh without a server attached.
  • code-index install-hook <repo> — installs a git post-commit hook that reindexes after every commit. uninstall-hook removes it.

All three share the same incremental cache — only changed files get re-parsed. See docs/ARCHITECTURE.md for how it works.

How it works

  1. Indexer (packages/indexer) — parses every supported file with tree-sitter and resolves references (imports, calls, self/this-scoped access) into real edges between symbols.
  2. OKF bundle — one Markdown file per symbol (YAML frontmatter with depends_on/calls/ called_by/dependents edges, plus a source-code body), an index.json manifest, and a meta.json with coverage stats.
  3. Server (packages/server) — loads the bundle into an in-memory graph and answers structural queries over MCP (stdio), hot-reloading the same graph instance as the repo changes.

Full format spec and pipeline details: docs/ARCHITECTURE.md.

Why

An agent exploring a codebase with only bash-style tools pays a traversal tax: it re-derives the same call graph a static analyzer already knows, one exploratory grep/read round-trip at a time. Pre-computing the graph once and exposing it as typed navigation tools turns that rediscovery into direct structural lookups — "what calls this," "what does this depend on," "path from A to B" — answered in a single call instead of several rounds of blind search.

This pays off most on codebases fragmented across many small files, where bash needs many round-trips to piece together what the graph already knows in one. On monolithic, few-large-file codebases it's merely competitive, not a clean win, since bash can often grep its way to an answer in one or two calls — a real, measured limitation, not a hidden one (see Performance).

Performance

Measured against baseline (Claude Code's built-in bash/grep/read tools, no graph) and Graphify, a third-party competing code-graph MCP server — 261 runs, 29 real GitHub-issue-fix instances across django/pytest/requests × 3 reps each, Claude Sonnet:

resolved rate avg cost avg tokens
baseline 78% $0.5749 895,776
Graphify 79% $0.4555 520,726
code-index 74% $0.3096 346,829

code-index vs baseline: −46.1% cost, −61.3% tokens. code-index vs Graphify: −32.0% cost, −33.4% tokens. code-index is the clear cost winner; resolved rate trails by 4-5 points in this pass, concentrated in the requests/pytest repos (django ties at 83% across all three arms) — every below-both-baselines instance was independently re-graded from its exact patch and traced back to genuine model misses on hard instances, not a defect in the tool surface.

Full methodology, per-repo breakdown, and that investigation: docs/BENCHMARKS.md.

Current limitations

  • Languages: Python, TypeScript/JavaScript, Java, and Svelte only — get_index_coverage reports exactly which files that covers for a given repo. Svelte coverage is script-block + template-binding only; the template's own markup/control-flow structure isn't indexed.
  • Bare-name call resolution (e.g. obj.start()) falls back to a repo-wide same-name lookup when nothing more precise is available, preferring same-language candidates first.
  • Cross-language HTTP route links (api_calls/api_called_by) are discovered by matching HTTP method + URL path, scoped to Flask/FastAPI/Express-style backends and fetch/axios frontend calls — no GraphQL, WebSocket, gRPC, or shared-schema matching.
  • TS/JS tsconfig support: paths wildcards work anywhere in a pattern, and a root tsconfig.json's extends chain is followed (string form only). Per-package tsconfig files (one per npm workspace package) aren't discovered yet.
  • Multi-repo: --repo/--okf accept multiple occurrences to merge several repos into one graph, including cross-repo HTTP route linking.

See docs/ARCHITECTURE.md for the mechanics behind each of these.

License

MIT

About

No description, website, or topics provided.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages