Skip to main content

delver - Local-First Code Intelligence MCP Server and CLI

delver is a local-first code-intelligence library, CLI, and MCP server for AI agents and developers.

It parses your codebase with tree-sitter, stores symbols and relationships in a local SQLite graph (WAL + FTS5), resolves cross-file call/type/import edges with a deterministic 3-tier algorithm, ranks repository structure with PageRank, and exposes everything to agents over MCP stdio plus a human-usable CLI.

Same tree + same code = byte-identical index and tool output. No LLM calls anywhere in the pipeline. No summaries. Only what the AST actually says.

Version: 0.1.0. Python 3.12+. Managed by uv. Entry point: delver = "delver.cli:main".


Table of contents

  1. What this does
  2. Why it stands out
  3. Requirements
  4. Install
  5. Uninstall
  6. Commands reference (with examples)
  7. MCP tools reference (with examples)
  8. Supported languages
  9. How it works (for contributors)
  10. Development and tests
  11. Troubleshooting
  12. License

1. What this does

Typical flow:

delver init            # index once
delver explore "..."   # ask about code, get source grouped by file + call path
delver node <symbol>   # symbol details, caller/callee trail
delver callers ...     # who calls it, with file:line
delver install         # wire the MCP server into Claude / OpenCode / Cursor

What you get:

  • A real symbol graph, not grep. Functions, methods, classes, structs, interfaces, traits, enums, type aliases, fields, properties, variables, constants, imports, components, routes. Edges: contains, calls, imports, exports, extends, implements, references, type_of, returns, instantiates, overrides, decorates.
  • Cross-file resolution. Import-based resolution first (most precise), then same-file definitions, then a conservative global fallback. Chained receiver.method() calls resolve via known receiver types with a supertype walk (depth 5). When nothing distinguishes candidates, the reference stays unresolved. A wrong edge is treated as worse than no edge.
  • Agent-first outputs. delver_explore is the primary tool: one call returns verbatim line-numbered source of the relevant symbols grouped by file plus the call path among them. delver_node reads one file or one symbol. The rest (search, callers, callees, impact, repo_map, files, status) answer narrow questions without extra reads.
  • Token-budget aware. Adaptive output budgets by repo size (13K/18K/24K total caps), per-file caps, skeletonization (signatures-only for off-spine files), container outlines instead of concatenated method bodies, overload packing, and a line-folded repo map that fits max_tokens.
  • Repo map. PageRank over the definition/reference graph with focus-file and mentioned-identifier boosts, rendered as a folded tree (kept lines with a vertical-bar marker, collapsed regions as an ellipsis marker) with 100-char line truncation.
  • Hybrid search. FTS5 exact search by default. Optional local embedding re-rank of the FTS5 top-50 via FastEmbed. The model is never auto-downloaded; without it you get pure FTS5 plus a one-line note.
  • CLI parity. Every graph query available over MCP is also available as delver <subcommand> for humans and scripts.

Recoverable conditions ("project not indexed", "symbol not found", "file not in index") return success-shaped text with guidance. Only real malfunctions surface as errors.


2. Why it stands out

Strengths only (no head-to-head claims). Each point is implemented behavior, not marketing:

  • Local-first and private. The index lives outside your repo under ~/.delver/indexed-db/ (Windows: %USERPROFILE%\.delver\indexed-db\). Your repo stays clean. No code leaves the machine for indexing. No API keys.
  • Deterministic, AST-derived. Extraction comes from tree-sitter grammars, not LLM summarization. Re-indexing unchanged code gives the same node IDs (<language>:<relpath>:<kind>:<qualified_name>) and the same output.
  • Multi-language with exact extractors. 12 language dictionaries plus tsx/jsx aliases plus HTML, plus yaml/properties key-only leaves. Each has explicit AST node-type mappings and behavioral hooks (method classification, receiver types, visibility, async/static/const, import/package extraction, C/C++/C# pre-parse blanking for macros and directives).
  • Resolution with confidence, not guessing. Import-resolved symbols short-circuit at 0.90-0.95 confidence. Qualified names, same-file preference, function-as-value rules, proximity narrowing, and word-overlap fallback each have fixed confidence values. Ambiguous names (50+ candidates) stay unresolved.
  • Method-on-type works. Return types and declared variable types are normalized into the index so obj.method() binds to Type::method, including inherited methods via extends/implements edges.
  • Budget engine prevents context blowups. Larger repos get more calls (1/2/3/4/5 by file count), never a bigger single response. Responses are cut at file-section boundaries under the cap and never tell the agent to use Read/Grep; they steer to another delver_explore or delver_node and label returned source as already read.
  • Secret-safe by default. Config/data leaves (yaml/properties) are summarized by key only. Values are never stored in the index and never printed.
  • Safe transport and storage. Pure stdio via FastMCP. Zero HTTP servers, zero ports, zero SSE, zero daemons, zero file watchers. Staleness is on-demand mtime+size delta sync before every query.
  • Surgical installer. Auto-detects Claude Code, OpenCode, and Cursor. Writes only the delver entry, preserves sibling servers, comments, and formatting (including JSONC comments/trailing commas for OpenCode). Re-runs are byte-equal no-ops (unchanged). Uninstall reverses install exactly and prunes emptied wrappers/files/dirs.
  • Operational safety. Filesystem-root and home-directory guard on index/destructive commands. Absolute binary paths in installed MCP entries. WAL mode check with a warning when the filesystem silently refuses WAL. Corrupt JSON configs are backed up before rewrite.

3. Requirements

  • Python 3.12 or newer.
  • uv for install and runs.
  • Supported OS: Windows, Linux/WSL, macOS.
  • Disk locations used (all outside indexed repos):
    • Index DB: ~/.delver/indexed-db/<hash>_<slug>.db (Windows: %USERPROFILE%\.delver\indexed-db\...), plus -wal/-shm sidecars.
    • Embedding models: ~/.delver/models/.
    • Tree-sitter grammar cache: ~/.delver/ts-cache/.

Dependencies (from pyproject.toml): fastmcp, tree-sitter, tree-sitter-language-pack, networkx, grep-ast, fastembed, numpy. Dev group: pytest.


4. Install

4.1 Install the package

From the repo root:

uv sync

This creates the venv and installs delver with the delver console script.

Verify:

uv run delver --help

You should see all subcommands: init index sync status uninit explore node callers callees impact repo-map files search install uninstall serve.

4.2 Index a project

cd /path/to/your-project
uv run delver init

Or from anywhere:

uv run delver init /path/to/your-project

What happens:

  1. Scans the project root, skipping .git/, node_modules/, .venv//venv/, dist//build//target//__pycache__/, .delver/, lockfiles, binaries, minified files, and files over 1 MB.
  2. Parses each recognized file with tree-sitter, inserts nodes/edges/imports, collects unresolved refs.
  3. Runs the 3-tier + chained-call resolution pass.
  4. Prints a tree summary: files indexed, node count, edge count, elapsed time.

init is idempotent. Re-running prints "Already initialized" with a hint to use index or sync.

Other lifecycle commands:

uv run delver status
uv run delver sync
uv run delver index
  • status shows files/nodes/edges, DB size, journal mode, pending unresolved refs, last sync time, and the DB path.
  • sync does an mtime/size delta sync only and prints added/updated/removed counts (or "Already up to date").
  • index forces a full re-extract of every file, then resolves.

All project paths are optional and default to the current directory. Global --path also works:

uv run delver --path /path/to/your-project status

Safety: init, index, sync, and uninit refuse filesystem roots (/ , C:\) and the bare user home directory with exit code 2.

4.3 Install the MCP server into your agents

Zero flags = detected agents + global scope (project repos stay clean):

uv run delver install

Explicit selection:

uv run delver install --agents claude,opencode,cursor --location global
uv run delver install --agents claude --location local
uv run delver install --local
uv run delver install --agents claude --auto-allow

Flags:

  • --agents: comma-separated subset of claude,opencode,cursor. Default: all detected agents. Non-interactive.
  • --location: global (default) or local. --local is shorthand for --location local.
  • --auto-allow: Claude only. Appends mcp__delver__* allow entries to settings.json.

Where entries go:

  • Claude Code:
    • Global: ~/.claude.json under mcpServers.delver = {type: stdio, command: <abs path>, args: [serve]}.
    • Local: <root>/.mcp.json (the only project-level file Claude Code reads; stale legacy entries are migrated out on install and uninstall).
    • Permissions (opt-in): ~/.claude/settings.json (global) or <root>/.claude/settings.json (local).
  • OpenCode:
    • Config dir is $XDG_CONFIG_HOME/opencode if set, else ~/.config/opencode on every platform. Local: project root.
    • File selection: existing opencode.jsonc wins, else existing opencode.json, else create .jsonc.
    • Entry under mcp (not mcpServers): {mcp: {delver: {type: local, command: [<abs path>, serve], enabled: true}}} with $schema seeded for new files. Comments and trailing commas survive round-trips. Legacy %APPDATA%/opencode entries are swept on global install/uninstall.
  • Cursor:
    • Global: ~/.cursor/mcp.json. Local: <root>/.cursor/mcp.json. Same mcpServers shape as Claude plus --path injection (Cursor launches with the wrong cwd and no root URI): local installs get the absolute project path, global installs get ${workspaceFolder}. Final args: ["serve", "--path", <pathArg>]. Restart Cursor after changes.

Report vocabulary per file: created, updated, unchanged (byte-identical re-run, file untouched), removed, not-found.

After install, the server runs over stdio. Manual check:

uv run delver serve

Send a JSON-RPC initialize message over stdin to smoke-test; expect a JSON-RPC initialize response and no port binds.

4.4 Enable semantic re-rank (optional, one-time)

Pure FTS5 is the default. To enable hybrid embedding re-rank:

uv run delver search "login session" --semantic --download

This downloads the embedding model (default bge-small-en-v1.5) into ~/.delver/models/ and exits after printing the path (or continues with the query if one was given). Later runs:

uv run delver search "login session" --semantic

Without a downloaded model, --semantic degrades to pure FTS5 with a one-line success-shaped note. It never auto-downloads.


5. Uninstall

Reverse order: remove agent configs first, then optionally delete the index.

Remove MCP entries:

uv run delver uninstall
  • Without --agents, uninstall sweeps all three targets (reports not-found harmlessly) so it covers agents that are no longer detectable but still have config entries.
  • With --agents, only that subset is touched: uv run delver uninstall --agents cursor --location global.
  • --location / --local select scope the same way as install.
  • Every write is paired: injected keys removed, emptied wrappers (mcpServers/mcp) pruned, empty files deleted, empty config dirs pruned. Sibling servers and unrelated keys are never touched.

Delete the index for a project:

uv run delver uninit
uv run delver uninit -y
uv run delver unindex -y /path/to/project
  • Prompts [!] This will permanently delete the Delver index for <root>. Continue? (y/N) unless -y/--yes is given. unindex is an alias.
  • Deletes every DB file/sidecar for the project by hash-prefix glob (covers both current hybrid names and legacy hash names) plus strips the delver entry from local agent configs in that project.
  • Prints [OK] Removed Delver index for <path>, or a warning when nothing was found (idempotent, exit 0).
  • Other projects' DBs are untouched.

Full removal from a machine: run uninstall (global scope) for each project you installed, run uninit per indexed root, then delete the package checkout. The only leftovers would be ~/.delver/ caches you may delete manually.


6. Commands reference (with examples)

Global: delver [--path <root>] <command> [args] [project]. The trailing project positional overrides --path; both default to . (cwd).

Lifecycle

Command What it does Example
init [path] Create DB, run full index + resolution, print files/nodes/edges delver init / delver init ./my-app
index [path] Force full re-extract of every file, then resolve delver index
sync [path] mtime delta sync only; prints added/updated/removed delver sync
status [path] Files/nodes/edges, DB size, journal mode, pending refs, last sync, DB path delver status
uninit [path] [-y] (alias unindex) Delete index DB + sidecars + local config entries delver uninit -y

Examples:

delver init
# T  Initializing Delver
# *  Scanning files -- 411 found
# *  Parsing code -- done
# *  Resolving references -- done
# -  Done (with bullet: Indexed 411 files (... nodes, ... edges in ...s))

delver status
# Project: D:\projects\my-app
# Files: 411  Nodes: 10023  Edges: 18979  Unresolved (pending): 0
# DB: C:\Users\you\.delver\indexed-db\d2b9342d_D_projects_my-app.db (... bytes)
# Journal mode: wal
# Last sync: ...

delver sync
# T  Syncing Delver ... Already up to date (0 files modified)

delver uninit -y
# [OK] Removed Delver index for D:\projects\my-app

Query

Command What it does Example
explore <query...> Primary. Whole-tail query. Prints budget-capped markdown with source grouped by file + flow/blast-radius delver explore "sync delta indexer"
node <symbol> [--code] Symbol details (signature, location, caller/callee trail). --code adds full body delver node sync_delta / delver node UserService --code
search <query> [--kind] [--limit] [--semantic] [--download] Quick symbol name lookup, locations only delver search login --kind function --limit 10
callers <symbol> Caller list with file:line delver callers sync_delta
callees <symbol> Callee list with file:line delver callees loginUser
impact <symbol> [--depth N] Reverse-edge BFS blast radius delver impact AuthService --depth 2
repo-map [--tokens N] [--focus F...] PageRank-ranked folded repo map delver repo-map --tokens 1024 --focus src/auth.ts
files [--pattern G] [--subpath D] [--format tree|flat|grouped] Indexed file tree with language + symbol counts delver files --pattern "src/**/*.ts" --format tree

Notes:

  • explore takes the whole tail as the query (free-text allowed). Parse happens before argparse, so quote multi-word queries: delver explore "AuthService loginUser session-manager".
  • node defaults to signature + docstring + trail (no body). Containers (class/interface/struct/enum) with --code return a structural outline (member names + signatures + line numbers), never concatenated bodies. Ambiguous names return every matching definition packed under a char budget (12000 chars, hard cap 16 rendered, 20 listed).
  • File mode note: delver_node file view renders <n><tab><line> (cat -n style), default 2000 lines, 38000 char budget, with pagination note and a one-line blast-radius header (used by N files: ...).
  • search --kind accepts: function, method, class, interface, type, variable, route, component.
  • repo-map --tokens defaults to 1024. --focus boosts the files you are already working with.

Setup

Command What it does Example
install [--agents ...] [--location ...] [--local] [--auto-allow] Detect agents, write MCP configs delver install --agents claude,opencode --location global
uninstall [--agents ...] [--location ...] [--local] Reverse install exactly delver uninstall --location local
serve Start FastMCP stdio server delver serve

7. MCP tools reference (with examples)

All tools accept optional projectPath to query a second indexed project. All are read-only. Every read runs the mtime delta sync first.

# Tool Role CLI equivalent
1 delver_explore PRIMARY. Call first for almost any question or before an edit. Bag of symbol/file names or natural language. Returns verbatim source grouped by file + call path. maxFiles clamped 1..20; effective default comes from the budget engine (4/5/8 by repo size) delver explore
2 delver_node SECONDARY. File mode (Read-equivalent with offset/limit) or symbol mode (body + caller/callee trail). includeCode defaults false delver node
3 delver_search Quick symbol lookup, locations only. Optional kind, limit (default 10), semantic (default false) delver search
4 delver_callers Who calls <symbol>, with file:line delver callers
5 delver_callees What <symbol> calls delver callees
6 delver_impact Blast radius of changing <symbol> (BFS over reverse edges, depth default 2) delver impact
7 delver_repo_map PageRank-ranked folded repo map. maxTokens default 1024, focusFiles, mentionedIdents, forceRefresh delver repo-map
8 delver_files Indexed file tree with language + symbol counts. path, pattern, format (tree/flat/grouped), includeMetadata, maxDepth delver files
9 delver_status Index health: files/nodes/edges/DB size/journal mode delver status

Agent guidance baked into outputs: explore output never tells the agent to use Read; it steers to another delver_explore or delver_node and says "treat returned source as already Read".

Minimal MCP config shapes (command is the absolute delver binary on your machine):

Claude (~/.claude.json):

{
  "mcpServers": {
    "delver": { "type": "stdio", "command": "C:\\path\\to\\delver.EXE", "args": ["serve"] }
  }
}

OpenCode (~/.config/opencode/opencode.jsonc):

{
  // your comments survive install/uninstall
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "delver": { "type": "local", "command": ["C:\\path\\to\\delver.EXE", "serve"], "enabled": true }
  }
}

Cursor (~/.cursor/mcp.json, global):

{
  "mcpServers": {
    "delver": { "command": "C:\\path\\to\\delver.EXE", "args": ["serve", "--path", "${workspaceFolder}"] }
  }
}

Prefer delver install over hand-editing; it resolves the absolute path, picks the right file, and keeps formatting.


8. Supported languages

Language key Grammar Extensions
python python .py, .pyi
typescript typescript .ts
tsx tsx .tsx
javascript javascript .js, .mjs, .cjs
jsx jsx .jsx
rust rust .rs
c c .c, .h
cpp cpp .cc, .cpp, .cxx, .hpp, .hh, .h++, .cu, .cuh, .metal
java java .java
csharp c_sharp .cs
go go .go
php php .php
ruby ruby .rb, .erb
lua lua .lua
html html .html, .htm
config leaves n/a .yml, .yaml, .properties, .ini (key-only nodes)

Skipped always: binaries, .git/, node_modules/, venvs, dist//build//target/, __pycache__/, .delver/, lockfiles, minified *.min.js, files over 1 MB.

Node kinds: file, module, class, struct, interface, trait, protocol, function, method, property, field, variable, constant, enum, enum_member, type_alias, namespace, parameter, import, export, route, component.

Edge kinds: contains, calls, imports, exports, extends, implements, references, type_of, returns, instantiates, overrides, decorates.


9. How it works (for contributors)

files -> ExtractionOrchestrator (py-tree-sitter) -> SQLite (nodes/edges/files)
           |
           v
     ReferenceResolver (Tier 1 imports -> Tier 2 same-file -> Tier 3 global)
           |
           v
     Graph queries (callers/callees/impact) + FTS5 search
           |
           v
     MCP tools (delver_*) + CLI + repo map

Package layout:

delver/
  cli.py               # argparse CLI
  server.py            # FastMCP instance + tool registration
  types.py             # NodeKind, EdgeKind vocabularies
  db/
    schema.sql         # DDL (nodes, edges, files, unresolved_refs, FTS, metadata)
    connection.py      # PRAGMA order, WAL check, db_path_for, sidecar cleanup
    indexer.py         # mtime delta sync engine
    queries.py         # prepared statements for tools
  extraction/
    orchestrator.py    # walk + parse + store
    extractors.py      # language dictionaries + hooks
    languages.py       # language key -> grammar + extension map
  resolution/
    __init__.py        # 3-tier resolver
    name_matcher.py
    import_resolver.py
    chained_calls.py   # receiver-type bridges
  tools/
    __init__.py        # 9 tool handlers + register_tools
    budgets.py         # get_explore_budget / get_explore_output_budget
    render.py          # node/file/folding renderers
  repomap/
    __init__.py        # PageRank + folded tree + bounded cache
  search/
    __init__.py        # hybrid FTS5 + FastEmbed re-rank
  installer/
    __init__.py        # detect/run_install/run_uninstall orchestrator
    targets/           # claude.py, opencode.py, cursor.py
  tests/               # pytest suite, one file per phase

Key invariants (violations are bugs):

  1. Transport is pure stdio. No ports, no SSE, no daemons.
  2. Stateless execution. No watchers; every query runs sync_delta first.
  3. DB never lives inside the indexed repo.
  4. MCP tools are delver_*. CLI is delver <subcommand>.
  5. Determinism. Same tree = same index and output.
  6. Recoverable conditions are success-shaped text, never errors.
  7. Explore output never suggests Read/Grep.
  8. All shipped source is ASCII. Fold glyphs are emitted at runtime via escapes.

Budgets (repo size -> per-call caps): total 13K/18K/24K/24K/24K chars, per-file 3800/3800/6500/7000/7000, gap 7/8/12/15/15 lines, header/edge caps 5/6/10/15/15. Larger tiers never get a smaller per-file cap. Larger repos get more calls (1/2/3/4/5 at <500/<5k/<15k/<25k/>=25k files), never a bigger single response.


10. Development and tests

uv sync
uv run pytest delver/tests/ -q
uv run delver --help

Full suite must be green before any phase is considered done. Test files map to build phases: test_skeleton.py, test_db.py, test_extraction.py / test_resolution.py, test_tools.py, test_repomap.py, test_installer.py.

Terminal hygiene for contributions: report exit codes plus one-line summaries; on failure show at most the relevant lines.


11. Troubleshooting

  • Project not indexed. Run: delver init - you queried before indexing. Run delver init [path], then retry.
  • Symbol not found: X - no node with that name exists. Try delver search X for close matches, or check --kind/--limit.
  • No callers found for X. - symbol exists but has no incoming calls/references edges.
  • WARNING: journal mode is '...' (expected 'wal') - the filesystem (network mount, WSL /mnt) silently kept the prior mode. Reads still work; concurrent reads may block.
  • Semantic search falls back to FTS5 with a one-line note - the model is not under ~/.delver/models/. Run delver search --semantic --download once (opt-in).
  • Error: Safety check blocked operation on system root or user home (exit 2) - run from inside a project directory or pass a specific project path.
  • Cancelled - nothing was deleted. - you declined the uninit prompt. Re-run with -y for scripts.
  • Unparseable agent JSON - the installer backs it up to <path>.backup before any rewrite; fix or restore the backup and re-run.
  • Cursor does not see the server - restart Cursor after MCP changes take effect.

12. License

MIT. See root pyproject.toml (license = { text = "MIT" }) and the repository LICENSE if present.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

delver_codebase_mcp-0.1.1.tar.gz (243.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

delver_codebase_mcp-0.1.1-py3-none-any.whl (263.3 kB view details)

Uploaded Python 3

File details

Details for the file delver_codebase_mcp-0.1.1.tar.gz.

File metadata

  • Download URL: delver_codebase_mcp-0.1.1.tar.gz
  • Upload date:
  • Size: 243.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for delver_codebase_mcp-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2c5ab8262c8a7ec0f4067d5497bc013e8b91b48813b505886a2e33583eab1a68
MD5 8d9b88ce9d24b60480c27a8c244ed64e
BLAKE2b-256 ea04de936e5f10441af282809ef7106bffc8bf550e2bf09a9aca006e32e6bd29

See more details on using hashes here.

File details

Details for the file delver_codebase_mcp-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: delver_codebase_mcp-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 263.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for delver_codebase_mcp-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 67c68c63954624db8ea98297e1d1f3f110bd7694dcffec30bb4d0940c0679363
MD5 b7cfea9a15e8dc19cac04f1e1a39719d
BLAKE2b-256 659e0d42bc413c83765bcb1e197443f9ad0f3f5abc653f8f645720620d66fe20

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.2

2 files

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page