heliosdb-codekb-mcp
MCP stdio server for code+docs knowledge bases. Embeds
HeliosDB-Nano as a Rust library (code-graph,
graph-rag, mcp-endpoint, code-embed features) and exposes its
LSP-shaped + GraphRAG tools to Claude Code, Cursor, Codex, Aider,
and any other MCP-aware agent — over plain stdio JSON-RPC, no
ports, no auth dance, all local.
What this plugin actually buys you
Measured on a real corpus (see bench/README.md),
the value proposition is not "saves N % tokens on every query."
The honest picture across 10 typical dev questions × multiple trials
with both Haiku 4.5 and Opus 4.7:
| Scenario | What the plugin gives you |
|---|---|
| Q where one Read+Grep nails it | Plain Claude Code is already cheap. MCP adds modest overhead (cache reads for tool descriptions + tool results). Plugin loses 10-30 % on this profile. |
| Q that sends the agent on a multi-turn grep tour | Without the plugin, Opus has hit the per-call budget cap with no answer; Haiku has burned 22-32 turns of Read+Grep. With the plugin, the same question lands in 3-6 turns. This is the catastrophe-prevention value — it stabilises the tail, not the median. |
Cross-modal queries ("which doc section mentions the FastEmbedder symbol?") |
Read+Grep literally can't answer in one shot. The plugin's text → code MENTIONS edges traverse both sides in one tool call. Read+Grep has no equivalent. |
| Time-travel, branch diff, AST diff | helios_ast_diff, heliosdb_branch_*, heliosdb_time_travel answer "what did this symbol look like at commit X / on branch Y" with typed AST deltas. Read+Grep cannot do this at all — you'd need to checkout, build the index against the older state, and grep again. |
| Doc retrieval that returns one section, not the whole file | When the .md ingest used ChunkStrategy::Headings, helios_graphrag_search returns the matching DocSection instead of the full file. Smaller chunks = direct token savings on doc-heavy workflows. |
| Compact one-tool mode | Fresh installs default to helios(action, args), a one-tool gateway that avoids re-advertising every engine schema on every turn. Use action="ask" for a server-routed answer card with compact evidence. |
What the plugin does NOT do well (yet):
- It is not consistently cheaper than Read+Grep on simple symbol lookups with a small model. The bench shows 1.5-2× run-to-run variance and the median is roughly even with no-MCP after three Haiku trials.
helios_lsp_*andhelios_graphrag_searchdefault to returning rich context (neighbouring symbols, full doc-section bodies). The plugin ships an opt-in--max-tool-result-bytestrimmer, but blunt trimming costs more than it saves on this workload — the agent treats the…[truncated]marker as a Read-fallback signal.- The biggest win-back lever — having the engine expose
verbose: falsemodes for each tool — lives engine-side. Tracked inbench/README.md"follow-up hypotheses".
Use the plugin when the cross-modal / time-travel / catastrophe-prevention value matters. Don't deploy it expecting token savings on a Haiku Q&A workload.
Install
Pre-built binary (recommended)
Latest release: v0.1.0
| Platform | Status |
|---|---|
| Linux x86_64 | ✅ available — download from the release page |
| macOS x86_64 (Intel) | planned |
| Linux / macOS aarch64 | planned (rocksdb cross-compile blocker) |
Verify with the matching .sha256 from the release page.
From source (any platform)
# binary: ./target/release/heliosdb-codekb-mcp
Use as a Claude Code plugin
This repo ships a .claude-plugin/plugin.json manifest plus three slash
commands (/codekb-setup, /codekb-ingest, /codekb-status) and a
codekb-pro-features skill. Install for a single Claude Code session:
Or fetch directly from a release/branch URL once distributed via a
plugin marketplace. On first use, run /codekb-setup — it walks you
through the binary install (if needed), asks whether to enable the
optional one-time ~30 MB embeddings download, and indexes the current
project.
The plugin's .mcp.json declares the MCP server with
--source ${CLAUDE_PROJECT_DIR}, so the helios MCP tools follow
whichever project Claude Code is opened in.
What it is
Three things at once:
- A user-level config tool. Run
init --source <PATH> --mode <co-located|global|hybrid>once per source-directory you want indexed. The choice persists in${XDG_CONFIG_HOME:-~/.config}/heliosdb-codekb-mcp/config.toml. - A KB resolver. Given a source path, finds the right KB directory using the persisted config (with longest-prefix match for hybrid setups that span multiple sub-trees).
- The MCP stdio server.
serve --source <PATH>opens anEmbeddedDatabaserooted at that source's KB and runsheliosdb_nano::mcp::McpServer::new(db).run().await. All query tools (helios_lsp_*,helios_graphrag_search,helios_ast_diff, …) come from the engine library — this binary owns transport and config, not tool surface.
KB-location modes
| Mode | Where the KB lives | Use when |
|---|---|---|
co-located |
<source>/.helios-kb (auto-added to .gitignore) |
Single repo, KB travels with the code. |
global |
${XDG_DATA_HOME}/helios-kb/<slug> (slug = source path) |
Many independent projects on one machine. |
hybrid |
An explicit --kb <PATH> you can register many sources to |
Multi-repo aggregate (e.g. ~/Helios/*). |
Document ingestion (default tier — no Docling)
Out of the box, ingestion uses pure-Rust crates. Single static binary, no Python, no Docker. Covers ~80% of real-world content:
| Format | Backend |
|---|---|
.rs / .py / .ts / .tsx / .js / .go / .sql |
tree-sitter via the engine's code-graph |
.md / .txt |
tree-sitter Markdown / generic text |
.pdf (born-digital) |
pdf-extract |
.docx |
docx-rs |
.xlsx |
calamine |
Document ingestion (--features docling)
Build with --features docling and the binary additionally routes:
| Format | Backend (via engine graph_rag::ingest_*) |
|---|---|
| Scanned / OCR-required PDFs | Docling layout + OCR |
| Multi-column scientific PDFs | Docling table & formula extraction |
.pptx / complex Office |
Docling Office pipeline |
Audio (.mp3 / .wav / .m4a) |
Docling Whisper-pipeline |
Images (.png / .jpg / .tiff) |
Docling OCR |
This tier requires a docling-serve HTTP endpoint to be running
(host-managed, or via the helios-code-graph plugin's bundled
compose stack).
Quickstart
# 0. Build
BIN=
# 1. Configure a KB for a source path AND do the first ingest in one shot
# 2. Wire the MCP server into your agent. For Claude Code (.mcp.json):
{
}
# Or HTTP transport (Cursor / Continue / any non-stdio client):
# 3. Inspect / sanity-check
Ingest tiers
Three knobs, picked at init --ingest or ingest time, scaling
quality vs. wall time on the pilot corpus
(~/Helios/Nano, 666 files / 18 k symbols / 115 k refs):
| Tier | Flag | Pilot wall | What lights up |
|---|---|---|---|
| fast (default) | (none) | 26 s | BM25 + hop-distance ranking on helios_graphrag_search |
| quality (blocking) | --with-embeddings |
3 m 15 s | Adds in-process FastEmbedder body vectors → paraphrase queries |
| background-quality | --background-quality |
26 s parent + ~2 m 50 s detached child | User-wait stays at 26 s; paraphrase quality lifts when the child finishes |
Recommended for repos >~1 000 files: --background-quality.
Track via status --source X ("quality phase : running pid X" →
"complete — took Y").
Resume on interrupt
ingest writes <kb_dir>/.ingest-state.json at each phase
transition (walk → code_index → graph_rag). If a process is
killed mid-flight (Ctrl-C, OOM, reboot), the next ingest reads
the file at startup and skips already-completed phases — the
walk is skipped if phase >= code_index. Per-file resume inside
code_index is the engine's content-hash gate. Cleared on
successful completion; surfaced by status --source X as
ingest resume : interrupted at phase = ... until then.
Generated-file skip
Two layers, both honoured during the walk:
@generatedcontent-marker scan of the first 4 KiB (Facebook / Google / Bazel / Go convention).<root>/.gitattributeslinguist-generated globs — patterns flagged withlinguist-generated,linguist-generated=true, orlinguist-generated=setare matched against relative paths and skipped. Long-tail coverage of generated files (*.pb.rs,codegen/**, vendored bundles) that don't carry an in-file marker.
CLI surface
heliosdb-codekb-mcp <SUBCOMMAND>
init [--source PATH] [--mode co-located|global|hybrid] [--kb PATH]
[--ingest] [--include-binary-docs BOOL]
[--force] [--durable-writes]
[--with-embeddings] [--background-quality]
ingest [--source PATH] [--include-binary-docs BOOL]
[--force] [--durable-writes]
[--with-embeddings] [--background-quality]
serve [--source PATH] [--http <ADDR>]
status [--source PATH] [--mcp-url <URL>]
config show | set-default-mode <MODE> | path
Why a separate binary
HeliosDB-Nano is a generic database; baking one specific MCP transport into its binary would adapt the engine to one consumer. This crate keeps that boundary clean: the engine stays generic and publishable to crates.io for any downstream consumer; this binary holds the MCP packaging, transport, and per-source KB-location ergonomics.
License
Apache-2.0.