{"slug": "show-hn-amdb-local-code-context-mcp-server-single-rust-binary", "title": "Show HN: Amdb – Local code context MCP server, single Rust binary", "summary": "Amdb, a zero-runtime, single-binary code context MCP server that indexes codebases entirely on the local machine with combined graph and vector retrieval, has been released as an open-source tool. The Rust-based tool requires no Node or Python runtime and is designed for air-gapped environments, CI containers, and regulated industries where cloud-based codebase indexing is prohibited. In benchmarks against its own 31-file source tree, Amdb achieved 100% precision targeting, 91.5% global efficiency reduction, and 81.7% noise reduction.", "body_md": "**amdb turns your codebase into AI context — entirely on your machine.**\n\namdb is a zero-runtime, single-binary code context MCP server with combined graph + vector retrieval. No code leaves the machine and no Node/Python runtime is required. Built for air-gapped environments, CI containers, and regulated industries where cloud-based codebase indexing is prohibited.\n\n```\ncargo install amdb\n```\n\nOr download a static binary for Linux/macOS from the [Releases page](https://github.com/BETAER-08/amdb/releases) — no toolchain required.\n\n```\namdb init .    # index the repo: AST parse + local embeddings, incremental\namdb serve     # expose the index as an MCP server over stdio\n```\n\nDone. Prefer a file instead of a server? `amdb generate --focus \"auth\"`\n\nwrites a targeted context file to `.amdb/`\n\n.\n\n**VSCode / Cursor** — add `.vscode/mcp.json`\n\nto your project:\n\n```\n{\n  \"servers\": {\n    \"amdb\": {\n      \"command\": \"amdb\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n**Claude Code**:\n\n```\nclaude mcp add amdb -- amdb serve\n```\n\nThe server exposes three tools, all reading from the pre-built local index:\n\n| Tool | What it returns |\n|---|---|\n`amdb_get_context` |\nFull project overview: files, symbols, and the mermaid dependency graph |\n`amdb_focus` |\nContext narrowed to a query via name match + semantic vector search, expanded by `depth` dependency hops |\n`amdb_get_symbol` |\nEvery definition of a symbol name as JSON: file, kind, line, signature, callers, and callees — each callee carries its resolved file and a `resolution` value (`same-file` , `global-unique` , or `unresolved` ) |\n\nIf no index exists the tools respond with an error asking you to run `amdb init`\n\n— the server never indexes on its own.\n\nReal session, 1.0 seconds end-to-end ([scripts/demo.sh](/BETAER-08/amdb/blob/main/scripts/demo.sh)):\n\n``` bash\n$ amdb init .\n INFO Initializing amdb in: .\n INFO Scanning files in ....\n INFO Files: 35 unchanged, 0 changed, 0 added, 0 removed\n INFO Indexing 0 files using 12 threads...\n INFO Embedding calls: 0\n INFO Project indexed successfully at .\n\n$ amdb serve\n  MCP client calls amdb_get_symbol with {\"name\": \"cosine_similarity\"}\n\ncosine_similarity — src/core/vector_store.rs:196\n  signature:  fn cosine_similarity(a: &[f32], b: &[f32]) -> f64\n  visibility: private\n  called by:  search (src/core/vector_store.rs)\n  calls:      iter, map, sqrt, sum, zip\n\nAnswer came from the local index. No network. No code left the machine.\n```\n\nTo record the cast on a host with asciinema: `asciinema rec -c \"AMDB_BIN=./target/release/amdb ./scripts/demo.sh\" demo.cast`\n\n, then `agg demo.cast demo.gif`\n\n.\n\nMeasured by [ benchmark.py](/BETAER-08/amdb/blob/main/benchmark.py) against amdb's own source tree (31 files, 21,887 raw tokens). Full methodology and caveats in\n\n[benchmark.md](/BETAER-08/amdb/blob/main/benchmark.md).\n\n| Metric | Score | Meaning |\n|---|---|---|\n| Precision targeting | 100% (28/28 indexed files) | Query = exact file stem; the file's own section comes back. A retrieval-plumbing test, not a semantic-search-quality test |\n| Global efficiency | 91.5% reduction | Focus output tokens vs. a full-repo dump |\n| Noise reduction | 81.7% compression | Interface tokens vs. raw tokens, top-5 largest files |\n| Graph presence | 100% (28/28) | Output contains real `-->` dependency edges |\n\n3 of 31 files are module-declaration files with no extractable symbols; they are not in the index and are excluded from the denominator, not silently counted.\n\nSymbols and the call graph are extracted for all 16 grammars, but `is_public`\n\nand `signature`\n\nenrichment is AST-accurate for only three languages. The rest fall back to `is_public = true`\n\nand no signature — honest table below, so you know what you get:\n\n| Language | Extensions | Symbols + call graph | `is_public` / `signature` |\n|---|---|---|---|\n| Rust | `.rs` |\n✅ | ✅ AST-accurate |\n| Python | `.py` |\n✅ | ✅ AST-accurate |\n| TypeScript | `.ts` , `.tsx` |\n✅ | ✅ AST-accurate |\n| JavaScript | `.js` , `.jsx` , `.mjs` |\n✅ | fallback (`true` / none) |\n| C | `.c` , `.h` |\n✅ | fallback (`true` / none) |\n| C++ | `.cpp` , `.hpp` , `.cc` , `.cxx` |\n✅ | fallback (`true` / none) |\n| C# | `.cs` |\n✅ | fallback (`true` / none) |\n| Go | `.go` |\n✅ | fallback (`true` / none) |\n| Java | `.java` |\n✅ | fallback (`true` / none) |\n| Ruby | `.rb` |\n✅ | fallback (`true` / none) |\n| PHP | `.php` |\n✅ | fallback (`true` / none) |\n| HTML | `.html` , `.htm` |\n✅ | fallback (`true` / none) |\n| CSS | `.css` |\n✅ | fallback (`true` / none) |\n| JSON | `.json` |\n✅ | fallback (`true` / none) |\n| Bash | `.sh` , `.bash` |\n✅ | fallback (`true` / none) |\n\n`amdb init`\n\nparses every source file with Tree-sitter, extracts symbols and call edges, and embeds each symbol with a local fastembed model — content-hashed, so unchanged files are skipped entirely on re-runs. Everything lands in two SQLite files: a symbol/relationship store and a vector store. Retrieval combines exact name matching, cosine similarity over the vectors, and call-graph expansion, served over MCP stdio or written to a Markdown context file.\n\nSame fixture repo (amdb's own source), same five questions (\"where is symbol X defined, and who calls it?\"), all numbers actually measured by `benchmark.py`\n\n. We did not run competitor indexing tools, so none appear here; the baselines are a raw full-repo dump and a scripted grep-then-read-matched-files agent protocol.\n\n| Strategy | Avg tokens to model | Avg tool calls |\n|---|---|---|\n| Raw full-repo dump | 21,887 | 1 |\n| grep + read matched files | 4,180 | 2.4 |\namdb (`--focus` , depth 1) |\n3,972 | 1 |\n\nOn a 31-file repo, grep is genuinely competitive on tokens — amdb's edge at this scale is one structured call instead of 2–4, with signatures, visibility, and resolver-accurate caller/callee attribution instead of raw text. The token gap widens with repo size: the dump grows linearly, grep grows with match noise, amdb's focus output grows with the size of the relevant interface.\n\n**Daemon mode** — `amdb daemon`\n\nwatches the project and incrementally re-indexes on save, keeping the MCP answers fresh.\n\n**Focus depth** — `amdb generate --focus <query> --depth N`\n\nexpands context N call-graph hops from the matched files (default 1).\n\n**Configuration** — optional `amdb.toml`\n\nin the project root:\n\n```\ndb_path = \".database\"\nignore_patterns = [\"target\", \".git\", \"node_modules\", \".amdb\", \".fastembed_cache\", \"__pycache__\", \".database\"]\n```\n\n`AMDB_DB_PATH`\n\noverrides `db_path`\n\n. Add `.database/`\n\nand `.amdb/`\n\nto your `.gitignore`\n\n.\n\n**Verbose** — `-v`\n\n/ `--verbose`\n\non any command for debug logs.\n\n**Docker** — the repo `Dockerfile`\n\nbuilds a slim image whose entrypoint is `amdb serve`\n\n, so the container speaks MCP over stdio immediately:\n\n```\ndocker build -t amdb .\ndocker run --rm -v \"$PWD:/workspace\" --entrypoint amdb amdb init .\ndocker run -i --rm -v \"$PWD:/workspace\" amdb\n```\n\nThe published `ghcr.io/betaer-08/amdb:1.0.0`\n\nimage predates the serve entrypoint — it runs bare `amdb`\n\n, so pass the subcommand explicitly: `docker run -i --rm -v \"$PWD:/workspace\" -w /workspace ghcr.io/betaer-08/amdb:1.0.0 serve`\n\n. Images published from the next tag serve by default.\n\namdb follows semantic versioning. 1.0.0 freezes the contract below; anything listed as covered changes only in a 2.0 release, and contract tests in `tests/contract_test.rs`\n\nfail loudly if it drifts.\n\n**Covered by the 1.0 promise:**\n\n**CLI**— subcommands`init`\n\n,`daemon`\n\n,`generate`\n\n,`serve`\n\n; flags`--focus`\n\n/`-f`\n\n,`--depth`\n\n/`-d`\n\n,`--verbose`\n\n/`-v`\n\n; the optional path argument to`init`\n\nand`daemon`\n\n. Exit codes: 0 on success, 1 on unrecoverable error.**MCP tools**— exactly`amdb_get_context`\n\n,`amdb_focus`\n\n,`amdb_get_symbol`\n\nwith their current input parameters.`amdb_get_symbol`\n\nresponses keep every current field with its current type:`file`\n\n,`name`\n\n,`kind`\n\n,`line`\n\n,`signature`\n\n,`is_public`\n\n,`callers[]`\n\n(`name`\n\n,`file`\n\n),`callees[]`\n\n(`name`\n\n,`file`\n\n,`resolution`\n\n∈`same-file`\n\n|`global-unique`\n\n|`unresolved`\n\n). New fields and new`resolution`\n\nvalues may be*added*in minor releases; existing ones are never renamed, removed, or retyped.**Config**—`amdb.toml`\n\nkeys`db_path`\n\nand`ignore_patterns`\n\n, and the`AMDB_DB_PATH`\n\nenvironment override. Unknown keys are ignored.**Database upgrades**— the index schema is versioned via`PRAGMA user_version`\n\n. Any database written by amdb ≥ 0.6 opens without error and migrates automatically; the next`amdb init`\n\nrebuilds whatever the migration invalidated. Deleting`.database/`\n\nis a last-resort fallback, never a required upgrade step.**Generated Markdown anchors**— two things in`generate`\n\noutput are stable for scripts: each indexed file gets a heading line of exactly`### <relative/path>`\n\n(forward slashes, relative to the project root), and the dependency graph is a single fenced```` mermaid`\n\nblock containing`graph TD;`\n\nwith`-->`\n\nedge lines.\n\n**Not covered (may change in any release):**\n\n- Every other detail of the Markdown layout: bullet and signature formatting, section ordering, mermaid node-id sanitization, header text.\n- Log and progress text on stdout/stderr.\n- The SQLite table layout and the vector-store file format (only automatic migration is promised, not the bytes).\n- The benchmark harness (\n`benchmark.py`\n\n) and its output format. - Internal Rust APIs — amdb is a binary crate; depending on its modules as a library is unsupported.\n\nMIT. Bug reports and inquiries: [try.betaer@gmail.com](mailto:try.betaer@gmail.com)", "url": "https://wpnews.pro/news/show-hn-amdb-local-code-context-mcp-server-single-rust-binary", "canonical_source": "https://github.com/BETAER-08/amdb", "published_at": "2026-07-24 10:16:53+00:00", "updated_at": "2026-07-24 10:52:38.420071+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models"], "entities": ["Amdb", "Rust", "MCP", "VSCode", "Cursor", "Claude Code"], "alternates": {"html": "https://wpnews.pro/news/show-hn-amdb-local-code-context-mcp-server-single-rust-binary", "markdown": "https://wpnews.pro/news/show-hn-amdb-local-code-context-mcp-server-single-rust-binary.md", "text": "https://wpnews.pro/news/show-hn-amdb-local-code-context-mcp-server-single-rust-binary.txt", "jsonld": "https://wpnews.pro/news/show-hn-amdb-local-code-context-mcp-server-single-rust-binary.jsonld"}}