内容
# amdb
<p align="left">
<img src="amdb.png" alt="amdb logo" width="60">
</p>



**amdb 将您的代码库转化为 AI 上下文 — 完全在您的机器上运行。**
amdb 是一个零运行时、单二进制代码上下文 MCP 服务器,结合图 + 向量检索。无需代码离开机器,也无需 Node/Python 运行时。适用于空气隔离环境、CI 容器和受监管行业,禁止基于云的代码库索引。
## 安装
```bash
cargo install amdb
```
或从 [Releases 页面](https://github.com/BETAER-08/amdb/releases) 下载适用于 Linux/macOS 的静态二进制文件 — 无需工具链。
## 快速开始
```bash
amdb init . # 索引仓库:AST 解析 + 本地嵌入,增量
amdb serve # 通过 stdio 将索引暴露为 MCP 服务器
```
完成。更喜欢文件而不是服务器?`amdb generate --focus "auth"` 将目标上下文文件写入 `.amdb/`。
## 连接您的编辑器
**VSCode / Cursor** — 在您的项目中添加 `.vscode/mcp.json`:
```json
{
"servers": {
"amdb": {
"command": "amdb",
"args": ["serve"]
}
}
}
```
**Claude Code**:
```bash
claude mcp add amdb -- amdb serve
```
服务器暴露三个工具,均从预建的本地索引中读取:
| 工具 | 返回内容 |
| :- | :- |
| `amdb_get_context` | 项目概览:文件、符号和 mermaid 依赖图 |
| `amdb_focus` | 通过名称匹配 + 语义向量搜索将上下文缩小到查询,扩展 `depth` 依赖跳跃 |
| `amdb_get_symbol` | 每个符号名称的定义作为 JSON:文件、类型、行、签名、调用者和被调用者 — 每个被调用者携带其解析文件和 `resolution` 值(`same-file`、`global-unique` 或 `unresolved`) |
如果不存在索引,工具将返回错误,要求您运行 `amdb init` — 服务器永远不会自行索引。
## 演示
真实会话,1.0 秒端到端([scripts/demo.sh](scripts/demo.sh)):
```console
$ amdb init .
INFO 初始化 amdb 在: .
INFO 扫描文件在 ....
INFO 文件:35 不变,0 更改,0 添加,0 删除
INFO 使用 12 个线程索引 0 个文件...
INFO 嵌入调用:0
INFO 项目成功索引在 .
$ amdb serve
MCP 客户端调用 amdb_get_symbol,参数为 {"name": "cosine_similarity"}
cosine_similarity — src/core/vector_store.rs:196
签名: fn cosine_similarity(a: &[f32], b: &[f32]) -> f64
可见性:私有
调用者: search (src/core/vector_store.rs)
调用: iter, map, sqrt, sum, zip
答案来自本地索引。无网络。无代码离开机器。
```
要使用 asciinema 在主机上记录广播:`asciinema rec -c "AMDB_BIN=./target/release/amdb ./scripts/demo.sh" demo.cast`,然后 `agg demo.cast demo.gif`。
## 基准测试
通过 [`benchmark.py`](benchmark.py) 针对 amdb 自己的源代码树(31 个文件,21,887 个原始令牌)进行测量。完整的方法论和注意事项在 [benchmark.md](benchmark.md)。
| 指标 | 分数 | 含义 |
|--------|-------|---------|
| 精确度 | 100% (28/28 索引文件) | 查询 = 确切文件茎;文件自己的部分返回。检索管道测试,而不是语义搜索质量测试 |
| 全局效率 | 91.5% 减少 | 焦点输出令牌与全仓库转储相比 |
| 噪声减少 | 81.7% 压缩 | 接口令牌与原始令牌,top-5 最大文件 |
| 图存在 | 100% (28/28) | 输出包含真实 `-->` 依赖边 |
31 个文件中的 3 个是模块声明文件,没有可提取的符号;它们不包含在索引中,被排除在分母之外,而不是被默默计数。
## 语言支持
符号和调用图为所有 16 种语法提取,但 `is_public` 和 `signature` 丰富度对于只有三种语言的 AST 准确。其他语言则降级为 `is_public = true` 和没有签名 — 下表诚实,您知道自己得到了什么:
| 语言 | 扩展名 | 符号 + 调用图 | `is_public` / `signature` |
|----------|-----------|:---:|:---|
| Rust | `.rs` | ✅ | ✅ AST-accurate |
| Python | `.py` | ✅ | ✅ AST-accurate |
| TypeScript | `.ts`, `.tsx` | ✅ | ✅ AST-accurate |
| JavaScript | `.js`, `.jsx`, `.mjs` | ✅ | fallback (`true` / none) |
| C | `.c`, `.h` | ✅ | fallback (`true` / none) |
| C++ | `.cpp`, `.hpp`, `.cc`, `.cxx` | ✅ | fallback (`true` / none) |
| C# | `.cs` | ✅ | fallback (`true` / none) |
| Go | `.go` | ✅ | fallback (`true` / none) |
| Java | `.java` | ✅ | fallback (`true` / none) |
| Ruby | `.rb` | ✅ | fallback (`true` / none) |
| PHP | `.php` | ✅ | fallback (`true` / none) |
| HTML | `.html`, `.htm` | ✅ | fallback (`true` / none) |
| CSS | `.css` | ✅ | fallback (`true` / none) |
| JSON | `.json` | ✅ | fallback (`true` / none) |
| Bash | `.sh`, `.bash` | ✅ | fallback (`true` / none) |
## 工作原理
`amdb init` 使用 Tree-sitter 解析每个源文件,提取符号和调用边,并使用本地 fastembed 模型嵌入每个符号 — 内容哈希,因此在重新运行时跳过不变文件。所有内容都存储在两个 SQLite 文件中:符号/关系存储和向量存储。检索结合精确名称匹配、向量上的余弦相似度和调用图扩展,通过 MCP stdio 提供服务或写入 Markdown 上下文文件。
## 比较
相同的装置仓库(amdb 自己的源代码),相同的五个问题(“符号 X 在哪里定义,谁调用它?”),所有数字实际上由 `benchmark.py` 测量。我们没有运行竞争对手索引工具,因此此处没有显示;基准线是原始的全仓库转储和脚本的 grep-then-read-matched-files 代理协议。
| 策略 | 平均令牌到模型 | 平均工具调用 |
|----------|--------------------:|---------------:|
| 原始全仓库转储 | 21,887 | 1 |
| grep + 读取匹配文件 | 4,180 | 2.4 |
| amdb (`--focus`,深度 1) | 3,972 | 1 |
在 31 个文件的仓库中,grep 在令牌上确实具有竞争力 — amdb 在此规模上的优势是一个结构化的调用,而不是 2-4 个,具有签名、可见性和解析器准确的调用者/被调用者属性,而不是原始文本。令牌差距随着仓库大小而增加:转储线性增长,grep 随着匹配噪声增长,amdb 的焦点输出随着相关接口大小增长。
## 更多
**守护进程模式** — `amdb daemon` 监视项目并在保存时增量重新索引,保持 MCP 答案新鲜。
**焦点深度** — `amdb generate --focus <query> --depth N` 从匹配的文件扩展上下文 N 调用图跳跃(默认 1)。
**配置** — 项目根目录中的可选 `amdb.toml`:
```toml
db_path = ".database"
ignore_patterns = ["target", ".git", "node_modules", ".amdb", ".fastembed_cache", "__pycache__", ".database"]
```
`AMDB_DB_PATH` 覆盖 `db_path`。将 `.database/` 和 `.amdb/` 添加到您的 `.gitignore`。
**详细模式** — 任何命令上的 `-v` / `--verbose` 以获取调试日志。
**Docker** — 仓库 `Dockerfile` 构建一个精简镜像,其入口点是 `amdb serve`,因此容器立即通过 stdio 讲话 MCP:
```bash
docker build -t amdb .
docker run --rm -v "$PWD:/workspace" --entrypoint amdb amdb init .
docker run -i --rm -v "$PWD:/workspace" amdb
```
已发布的 `ghcr.io/betaer-08/amdb:1.0.0` 镜像在 serve 入口点之前 — 它运行裸 `amdb`,因此显式传递子命令:`docker run -i --rm -v "$PWD:/workspace" -w /workspace ghcr.io/betaer-08/amdb:1.0.0 serve`。从下一个标签发布的镜像默认情况下提供服务。
## 稳定性
amdb 遵循语义版本控制。1.0.0 冻结以下合约;任何列为涵盖的内容更改仅在 2.0 版本中更改,`tests/contract_test.rs` 中的合约测试如果漂移,将大声失败。
**涵盖的 1.0 承诺:**
- **CLI** — 子命令 `init`、`daemon`、`generate`、`serve`;标志 `--focus`/`-f`、`--depth`/`-d`、`--verbose`/`-v`;`init` 和 `daemon` 的可选路径参数。退出代码:成功时 0,无法恢复的错误时 1。
- **MCP 工具** — 确切 `amdb_get_context`、`amdb_focus`、`amdb_get_symbol` 及其当前输入参数。`amdb_get_symbol` 响应保留每个当前字段及其当前类型:`file`、`name`、`kind`、`line`、`signature`、`is_public`、`callers[]` (`name`、`file`)、`callees[]` (`name`、`file`、`resolution` ∈ `same-file` | `global-unique` | `unresolved`)。新字段和新的 `resolution` 值可能在小版本中 *添加*;现有字段永远不会被重命名、删除或重新键入。
- **配置** — `amdb.toml` 键 `db_path` 和 `ignore_patterns`,以及 `AMDB_DB_PATH` 环境覆盖。未知键将被忽略。
- **数据库升级** — 索引架构通过 `PRAGMA user_version` 版本化。任何 amdb ≥ 0.6 编写的数据库都无需错误即可打开并自动迁移;下一个 `amdb init` 将重建迁移无效的内容。删除 `.database/` 是一个最后的备用方案,永远不是必需的升级步骤。
- **生成的 Markdown 锚点** — `generate` 输出中的两项内容对脚本稳定:每个索引文件都有一行确切的 `### <relative/path>`(正斜杠,相对于项目根目录),依赖图是一个单独的围栏 ` ```mermaid ` 块,包含 `-->` 边线。
**未涵盖(可能会在任何版本中更改):**
- Markdown 布局的其他所有细节:项目符号和签名格式、章节排序、mermaid 节点 ID 清理、标题文本。
- stdout/stderr 上的日志和进度文本。
- SQLite 表布局和向量存储文件格式(仅承诺自动迁移,而不是字节)。
- 基准测试框架 (`benchmark.py`) 及其输出格式。
- 内部 Rust API — amdb 是一个二进制 crate;不支持将模块作为库依赖。
## 许可证
MIT。错误报告和查询:try.betaer@gmail.com