内容
# mcp-vl-msa-rs
[](https://github.com/DioNanos/mcp-vl-msa-rs/actions/workflows/ci.yml)
[](https://github.com/DioNanos/mcp-vl-msa-rs/actions/workflows/ci.yml)
[](docs/NEGATIVE_RESULTS.md)
[](LICENSE)
[](https://www.rust-lang.org)
一个用于AI智能体的可搜索的长期记忆, 作为MCP stdio服务器公开。 将文档、笔记和过去的对话索引到集合中;为查询检索top-k相关片段,并将原始文本注入模型;使用`msa_remember` / `msa_forget`添加或删除智能体的记忆。纯Rust实现,使用BM25搜索引擎,基于[tantivy](https://github.com/quickwit-oss/tantivy),默认构建无需任何机器学习依赖;可选的进程内稠密重排。
任何MCP客户端(Claude Code、Codex或任何支持MCP stdio的客户端)都可以访问相同的记忆:一个可查询的语料库,可以跨会话和模型切换生存,无需云账户和嵌入服务。 使用它为智能体提供基于知识库、文档树或聊天历史的持久回忆——检索返回原始文本,而不仅仅是嵌入。
它是两部分记忆中的一部分:这个服务器是**图书馆**(语料库回忆),它的伴侣 [mcp-memory-rs](https://github.com/DioNanos/mcp-memory-rs) 是**笔记本**(精选状态)。 切换模型的智能体不会丢失记忆。
```mermaid
flowchart LR
A["AI 智能体<br/>(任意 MCP 客户端)"]
A -->|"精选状态<br/>读写 / 同步"| M["mcp-memory-rs<br/><i>笔记本</i>"]
A -->|"语料库回忆<br/>索引 / 搜索 / 获取"| V["mcp-vl-msa-rs<br/><i>图书馆</i>"]
M --- D1[("JSON 类别<br/>SQLite FTS5")]
V --- D2[("tantivy BM25<br/>集合")]
```
**名称**:`msa` 是它从Memory Sparse Attention论文(arXiv:2603.23516)中借鉴的检索模式——一种外部近似,而不是神经网络模型;与MiniMax的MSA架构LLM不同,后者是内部(在模型中)生成器。 `vl` 代表Vivling (`codex-vl`),它的第一个采用者——但服务器完全与AI无关,并且不依赖于它。
**状态**:v0.4 — 可选的混合稀疏+稠密。
## 为什么
原始的 [Memory Sparse Attention](https://arxiv.org/abs/2603.23516) 论文(EverMind-AI)描述了一种端到端可训练的稀疏注意力层,适用于分块汇聚的KV缓存。 这是一种神经网络产物,不适用于纯Rust的MCP服务器。 什么是可移植的,以及本仓库旨在交付的是MSA宏模式:
1. **分块存储** 长文本,固定池大小(默认`P=64`字)。
2. **top-k稀疏路由** 在分块上(BM25替代;学习路由超出范围)。
3. **原始文本注入** (论文§4.3,消融-37.1%没有):`msa_search`返回分块,`msa_fetch_doc`返回完整文档。
4. **记忆交织** 作为一种**协议** (计划v0.4):AI客户端通过重复的工具调用与服务器端的光标编织多跳检索。
设计和原理在项目笔记(负面结果,门控方法论)中有详细说明;参见 [`docs/NEGATIVE_RESULTS.md`](docs/NEGATIVE_RESULTS.md)。
## 基准测试
检索更改基于**预注册的成对增量** 和bootstrap置信区间——不是基于绝对分数。 工作负载:HotpotQA(抽取式问答),MLDR-it(长文档检索,意大利语),LongMemEval-S(500个对话记忆问题)。完整的方法论,验收门控和**被驳斥的**假设在 [`docs/NEGATIVE_RESULTS.md`](docs/NEGATIVE_RESULTS.md) 中。
主要测量指标:
- **BM25是引擎,不是占位符。** 三次预注册尝试;没有混合(BM25 + 稠密重排)配置在这些工作负载上击败门控。 稠密重排在默认关闭的情况下仍然可用(`dense_alpha`,默认为关闭),以便重新测试编码器改进。
- **索引时富化胶囊** (确定性丰富,无LLM):**+7至+20 recall@5** 跨每个类别。
- **原始文本注入** (`msa_fetch_doc` 在 `msa_search` 之后):**+14.6 F1** 正好在片段丢失内容的层面上。
- **时间先验丢失** - 在服务时处理时间,而不是在检索分数中。
重现:
```bash
crates/msa-bench/scripts/download-bench-datasets.sh # 获取数据集
scripts/run-baseline-bench.sh # BM25 vs BM25+dense 扫描
# 结果位于 crates/msa-bench/results/ 下作为 JSON
```
## 工具表面
| 工具 | 版本 | 描述 |
|---|---|---|
| `msa_index` | v0.1 | 索引文档;`doc_id` 的现有分块将被替换。 |
| `msa_search` | v0.1 | top-k 分块,分数归一化 0.0–1.0。 |
| `msa_fetch_doc` | v0.1 | 文档的完整原始文本。 |
| `msa_delete` | v0.1 | 删除文档和所有分块。 |
| `msa_list_collections` | v0.1 | 注册表中打开的集合。 |
| `msa_stats` | v0.1 | 每个集合的统计数据(确切的 `num_documents` / `total_tokens`)。 |
| `SearchFilter` | v0.2 | 元数据过滤器(`where_eq`/`where_in`/`created_*`),检索后。 |
| `msa_search_iterative` | v0.3 | 具有服务器端光标的记忆交织;跨轮次重复。 |
| `msa_drop_session` | v0.3 | 在TTL之前强制取消记忆交织会话。 |
| `dense_alpha` 在 `msa_search` 上 | v0.4 | 混合BM25 + 余弦重排。 需要 `--features embeddings` + `[embeddings]` 配置。 |
| `msa_remember` / `msa_forget` | v0.4 | 智能体记忆表面:丰富 + 低信号门控 + 内容哈希重复;标准元数据(`kind` / `source_id` / `created_at`)。 |
| `msa_sync_path` | v0.4 | 将目录镜像到集合中(文件系统源;blake3增量同步)。 |
## 安装
**预构建二进制** (推荐)- 从 [最新发布](https://github.com/DioNanos/mcp-vl-msa-rs/releases/latest) 下载适用于您平台的存档,解压并指向您的MCP客户端:
```bash
tar xzf mcp-vl-msa-rs-x86_64-unknown-linux-gnu.tar.gz
install -m755 mcp-vl-msa-rs-*/mcp-vl-msa-rs ~/.local/bin/
```
预构建目标(Linux + Android):`x86_64-unknown-linux-gnu`,`x86_64-unknown-linux-musl`,`aarch64-unknown-linux-gnu`,`aarch64-unknown-linux-musl` (边缘 / ARM / Termux),`aarch64-linux-android`。
**macOS**:不提供预构建二进制文件(需要Apple代码签名)。 从源代码安装 - `cargo install` 以下命令在您的Mac上编译它, 无需签名:
```bash
cargo install --git https://github.com/DioNanos/mcp-vl-msa-rs \
--locked --features source-fs mcp-msa-server
```
## 构建和测试
```bash
cd mcp-vl-msa-rs
# 默认:纯BM25,无网络依赖
cargo build --release
cargo test
# 混合稀疏 + 稠密(进程内Candle重排,无外部服务)
cargo build --release --features embeddings
cargo test --features embeddings
```
### 混合模式配置
在 `MCP_MSA_CONFIG` 中添加 `[embeddings]` 以激活稠密重排。 如果没有此部分,服务器即使使用 `--features embeddings` 构建也会保持在仅BM25模式。
生产后端是 `candle-modernbert`:编码器在进程内运行(Candle),离线确定性,从本地模型包中运行 - 无需守护进程,无需网络运行时,无需自动下载。 使用 `scripts/prepare-granite-r2-97m.sh` 准备模型包。
```toml
[storage]
storage_dir = "~/.local/state/mcp-vl-msa-rs"
[chunking]
chunk_size = 64
overlap = 0
[embeddings]
backend = "candle-modernbert"
model_dir = "~/.local/share/mcp-vl-msa-rs/models/granite-r2-97m"
dim = 768
model_id = "granite-r2-97m"
```
一种过渡性的 `backend = "ollama"` (到Ollama兼容服务的HTTP)仍然存在,但**已弃用并计划在v0.6中删除** - 不要在此基础上构建新的设置。
AI客户端通过在 `msa_search` 上传递 `dense_alpha` (或任何支持它的未来工具)来选择混合评分。 `dense_alpha = 1.0` (默认)是仅BM25;`0.0` 是仅稠密;中间值是线性混合 `α·bm25 + (1-α)·((cos+1)/2)`。 余弦偏移到 `[0,1]` 以便它与已经最大归一化的BM25分数线性组合。
## 作为MCP_stdio运行
```bash
# 默认存储:~/.local/state/mcp-vl-msa-rs/
./target/release/mcp-vl-msa-rs
# 使用显式配置
MCP_VL_MSA_CONFIG=~/.config/mcp-vl-msa-rs/config.toml \
MCP_DEVICE=my-node \
./target/release/mcp-vl-msa-rs
```
示例 `~/.codex/config.toml` 条目:
```toml
[mcp_servers.vl_msa]
command = "/path/to/mcp-vl-msa-rs/target/release/mcp-vl-msa-rs"
env = { MCP_DEVICE = "my-node" }
# 让模型调用工具而无需每次调用的审批提示
default_tools_approval_mode = "approve"
```
适用于Claude Code的等效 `~/.claude.json` 条目:
```json
{
"mcpServers": {
"vl_msa": {
"command": "/path/to/mcp-vl-msa-rs/target/release/mcp-vl-msa-rs",
"env": { "MCP_DEVICE": "my-node" }
}
}
}
```
### AI 客户端兼容性
- 部分支持MCP的客户端可能不会显示服务器的 `instructions` 文本。 工具描述和请求字段描述是自包含的,因此模型可以仅凭这些信息工作。
- 只读工具(`msa_search`,`msa_fetch_doc`,`msa_stats`,`msa_list_collections`,`msa_manifest`,`msa_search_iterative`,`msa_interleave_round`)带有 `readOnlyHint` 注解,允许 gating客户端自动批准它们。
- 如果模型在Codex上报告“不支持的调用”或“用户取消”,那是审批门控,而不是服务器故障 - 设置 `default_tools_approval_mode` (上面)以便工具调用不会在提示上被阻止。
## 存储布局
```
~/.local/state/mcp-vl-msa-rs/
├── <collection_a>/ ← tantivy 索引目录
├── <collection_b>/
└── ...
```
每个集合都是一个独立的tantivy索引。 集合名称被验证(如果它们包含路径分隔符,`..`等,则拒绝),因此集合不能逃离根目录。
## 路线图
已交付:
- **v0.2** — `SearchFilter` (`where_eq` / `where_in` / `created`范围),检索后。
- **v0.3** — `msa_search_iterative` 具有服务器端光标的记忆交织 + TTL'd `MsaSession` 注册表。
- **v0.4** — 具有功能标志 `embeddings` 的混合BM25 + 稠密重排,Ollama后端,每个调用的 `dense_alpha` ;智能体内存表面(`msa_remember` / `msa_forget`);索引时文件系统源元数据(`created_at` / `source` / `ext` / `dir`);`msa-bench` 可复制的基准测试包;预构建二进制打包。
接下来(尚未构建):
- 查询时间tantivy过滤器(今天`SearchFilter`在检索后运行;对于普通语料库来说很好,但当选择性很高时,对于非常大的索引会有帮助)。
- 多租户集合的ACL。
- 工具描述调优。
## 相关工作
- **MSA论文** ([arXiv:2603.23516](https://arxiv.org/abs/2603.23516)) — 架构灵感(神经网络,内部);本仓库是外部的,纯Rust近似的宏模式。
- **Vivling** (在 `codex-vl` 中)- 第一个下游消费者:该服务器是其长期记忆。
- **[mcp-memory-rs](https://github.com/DioNanos/mcp-memory-rs)** — 配套服务器,用于**精选**智能体状态(命名JSON类别,按设备ACL,舰队同步)。 该服务器执行语料库回忆;它们一起涵盖智能体内存的两个部分:精选的笔记本和可查询的库。
## 许可证
Apache-2.0. 见 [LICENSE](./LICENSE).