关于 mcp-memory-rs
mcp-memory-rs 是面向 Agent 的本地优先 MCP 记忆服务,将长期状态保存在带版本记录的 JSON 文件中,并用可重建的 SQLite 索引搜索。默认离线运行,也可选择在设备间同步。
主要功能
- 01带版本记录的 JSON 分类与备份
- 02BM25 全文及混合搜索
- 03按设备限制分类写入权限
- 04可选的 Merkle 设备群同步
- 05历史记录、追加日志与快照
适用场景
- 01跨会话保存 Agent 身份与项目笔记
- 02无需嵌入服务即可搜索本地记忆
- 03限制设备仅写入自身分类
- 04按需在多台设备间同步记忆
MCP 相关
通过 stdio 向 MCP 客户端提供记忆读取、写入、搜索、历史、诊断和同步工具。相同能力也可通过需身份验证的 HTTP API 使用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-memory-rs
使用纯 Rust 构建的本地优先 MCP 记忆服务。为 AI Agent 提供持久化、版本化、可查询的记忆——由用户掌控,而非平台。
状态以纯 JSON 分类文件的形式保存在本地磁盘,并由 SQLite(FTS5)提供支持。每次写入都会进行版本管理并备份。多台设备可通过可选的 HTTP 端点,使用 Merkle 清单和乐观并发机制进行同步。默认模式下无需云账号、嵌入服务或网络依赖。
为什么选择它
与供应商绑定的 Agent 记忆会随着供应商会话结束而消失。本服务将 Agent 的长期状态——身份、项目、基础设施笔记、各设备的工作流——保存在你可以自行读取、搜索、比较差异和备份的文件中。任何 MCP 客户端(Claude Code、Codex,或任何使用 MCP stdio 的客户端)都能访问相同的记忆;更换模型不会丢失状态。
由此形成的设计选择:
- 本地优先:stdio 服务可完全离线地使用本地存储。同步是单独且明确执行的步骤——绝不会成为隐藏依赖。
- 纯文本存储:每个分类对应一个 JSON 文件,另有一个 SQLite 索引。数据库可以从这些文件重建;文件才是真实数据。
- 默认启用版本管理:每次写入都会保留历史记录;删除前会先创建备份。
memory_history和memory_compact用于管理历史记录。 - 并发安全写入:
expected_hash可将并发 Agent 之间的覆盖竞争转化为明确的冲突。 - 核心不包含 ML:全文搜索使用 SQLite FTS5 和 BM25;
memory_search_semantic可选地添加 TF-IDF 混合搜索。无需下载模型。
**配套服务:**如需检索 语料库(分块文档、BM25 检索、注入原文),请参阅配套服务 mcp-vl-msa-rs。本服务保存经过整理的 Agent 状态;配套服务保存可查询的语料库。
flowchart LR
A["AI agent<br/>(any MCP client)"]
A -->|"curated state<br/>read / write / sync"| M["mcp-memory-rs<br/><i>the notebook</i>"]
A -->|"corpus recall<br/>index / search / fetch"| V["mcp-vl-msa-rs<br/><i>the library</i>"]
M --- D1[("JSON categories<br/>SQLite FTS5")]
V --- D2[("tantivy BM25<br/>collections")]
安装
预编译二进制文件(推荐)——从最新版本下载适用于你平台的压缩包,解压后将 MCP 客户端指向该二进制文件:
tar xzf mcp-memory-rs-x86_64-unknown-linux-gnu.tar.gz
install -m755 mcp-memory-rs-*/mcp-memory-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 上编译,无需签名:
cargo install --git https://github.com/DioNanos/mcp-memory-rs --locked
--locked 使用已提交的 Cargo.lock(确保构建可复现)。
快速开始
cargo build --release
# stdio MCP server, offline mode (default)
./target/release/mcp-memory-rs
Claude Code(~/.claude.json)或任何 MCP 客户端:
{
"mcpServers": {
"memory": {
"command": "/path/to/mcp-memory-rs",
"env": {
"MCP_MEMORY_CONFIG": "/home/me/.config/mcp-memory-rs/config.toml",
"MCP_MEMORY_REQUIRE_CONFIG": "1",
"MCP_MEMORY_MODE": "offline",
"MCP_DEVICE": "my-laptop"
}
}
}
}
Codex(~/.codex/config.toml):
[mcp_servers.memory]
command = "/path/to/mcp-memory-rs"
env = { MCP_MEMORY_CONFIG = "/home/me/.config/mcp-memory-rs/config.toml", MCP_MEMORY_REQUIRE_CONFIG = "1", MCP_MEMORY_MODE = "offline", MCP_DEVICE = "my-laptop" }
# auto-approve read-only tools (memory_read/list/search/…); writes still gated
default_tools_approval_mode = "approve"
配置采用 TOML 格式——将 config/example.toml 复制到
~/.config/mcp-memory-rs/config.toml 并进行调整。服务会自动发现该 XDG 风格路径。环境变量会覆盖文件中的值(MCP_DEVICE、MCP_MEMORY_MODE、MCP_MEMORY_DIR、……);托管部署应设置 MCP_MEMORY_REQUIRE_CONFIG=1,以便在配置缺失时安全地拒绝启动。
记忆模型
记忆按类别组织:命名的 JSON 文档(base、
projects、my-laptop、workflow_my-laptop,……)。读取会返回文档
及其元数据(内容哈希、大小、最后写入者、时间戳)。写入会替换整个类别,或在
merge=true 时按顶层键进行修补。
访问控制
多设备集群使用简单明确的 ACL(配置中的 [acl]):
| 规则 | 效果 |
|---|---|
admin_devices | 列出的设备可以写入所有内容。 |
device_categories | 设备 name 可以写入类别 name 和 workflow_name——仅限其自身命名空间。 |
| agent scope | 设备 foo-agent 可以写入 foo_* 类别。 |
| everyone | 所有设备都可以读取所有内容。 |
非管理员写入者无法访问未知类别——默认拒绝。
集群同步
每个节点都以本地优先的方式运行;一个或多个节点可以将 HTTP API 作为同步远程服务公开。sync_manifest 会为所有类别构建以 Merkle 根为基础的指纹;sync_diff 会比较清单;memory_sync 会推送有更改的类别,或拉取远程更改。节点间的冲突由配置的 conflict_strategy 解决(默认采用最后写入者胜出);expected_hash 前置条件可保护直接写入(MCP 和 HTTP),但不保护同步信封。
HTTP API 是一个管理员/同步平面:持有 bearer token 即可完全访问每个类别。每类别 ACL 仅适用于 MCP stdio 接口,因为设备身份在本地已知;HTTP 调用者只能通过共享令牌识别,因此不会在此强制执行每设备 ACL。
HTTP 服务必须使用 MCP_MEMORY_TOKEN,没有该令牌时拒绝启动。请将其绑定到 loopback(默认设置),并在节点间建立隧道;切勿将其暴露到公共互联网。
MCP_MEMORY_TOKEN=<secret> ./target/release/mcp-memory-rs --http
工具接口
| 工具 | 描述 |
|---|---|
memory_read | 读取类别(可选字段筛选)。 |
memory_write | 替换或合并修补类别;带版本控制;使用 expected_hash 前置条件。 |
memory_append | 向有界、仅追加的日志类别追加带时间戳的条目;根据 max_entries/max_age_days 自动清理。用于事件流/会话日志,避免记忆类别变得臃肿。 |
memory_delete | 删除类别(先创建备份)。 |
memory_list | 列出所有类别及其哈希/大小/上次更新元数据。 |
memory_search | FTS5 全文搜索、BM25 排名、类别/日期/操作者筛选、摘要片段。 |
memory_search_semantic | 混合 TF-IDF + FTS5 搜索。 |
memory_history | 查看类别的版本历史。 |
memory_delta | 获取自已知哈希以来的更改(低开销轮询)。 |
memory_context | 读取多个类别以进行预热,面向令牌预算优化。 |
memory_compact | 清理旧版本和备份。 |
memory_status | 本地优先状态:待处理队列、清单哈希、上次同步时间。 |
memory_doctor | 诊断信息:路径、数据库、类别、同步配置。 |
sync_manifest | 为所有类别生成以 Merkle 根为基础的清单。 |
sync_diff | 比较本地与远程清单:推送/拉取/冲突集合。 |
sync_push / sync_pull | 导出/导入同步信封。 |
memory_sync | 针对已配置的远程服务执行一次同步(push_dirty / pull_remote)。 |
非 MCP 调用方也可通过 HTTP(/api/v1/*)使用相同的接口;/health 无需身份验证,其余接口均需要 bearer token。
AI 客户端兼容性
该服务的设计旨在让能力较弱的客户端模型也能轻松理解:
- 在
initialize时,它会返回一段 instructions 字符串,用于说明记忆模型和入口工具。一些轻量级客户端会忽略此字段;如果客户端从不显示该字段,请改为查看工具描述——其中包含相同的指引(例如,memory_read接受的是category,而不是key)。 - 只读工具带有
readOnlyHint注释,因此 Codex 之类的客户端可以自动批准这些工具。在 Codex 中,unsupported call/user cancelled结果通常表示触发了工具审批关卡,而非服务故障——请设置default_tools_approval_mode = "approve"(见上面的 Codex 示例)。 - 该服务使用标准 MCP 握手。客户端必须像任何 MCP 客户端一样完成
initialize并发送notifications/initialized。
存储布局
未配置且未启用严格模式时,独立运行的 base_dir 仍为 ~/.memory,以保持兼容性。自动发现的示例配置使用 ~/.local/state/mcp-memory-rs(XDG 风格)。配置解析顺序为:显式指定的 MCP_MEMORY_CONFIG、$XDG_CONFIG_HOME、$HOME/.config、旧版当前工作目录下的 memory-config.toml,然后是独立运行的默认值。无论哪种情况,布局如下:
<base_dir>/
├── categories/ # one .json file per category — the source of truth
├── backups/ # automatic pre-delete/pre-overwrite backups
├── memory.db # SQLite: FTS5 index, versions, sync state (rebuildable)
└── memory.db-wal # write-ahead log (WAL mode; do not copy or delete by hand)
并发(多个进程,共用一个存储)
每个写入进程——每个客户端对应一个 stdio 服务,以及可选的 --http 实例——都会在同一个文件上打开各自的 SQLite 连接。自 0.3.2 起,每次修改都在 BEGIN IMMEDIATE 事务中执行:SQLite 充当互斥锁,在多个进程之间串行化写入,因此追加操作(读取 → 修改 → 写入)绝不会丢失其他进程写入的条目。锁获取会在一个总时限内通过带抖动的退避机制重试;时限到期后,调用会返回明确的 Store busy … retry later 错误,而不是一直挂起或损坏任何内容。
[storage]
journal_mode = "wal" # "wal" (default) or "delete"
synchronous = "full" # "full" (default, durable) or "normal"
sqlite_busy_timeout_ms = 200 # per-statement SQLite busy handler
lock_deadline_ms = 10000 # total wait for the write lock per mutation
类别 JSON 文件采用崩溃安全的方式写入:新内容会先暂存到文件旁边(文件名在事务中唯一),SQLite 行提交后,再将暂存文件重命名到位。若进程在此期间退出,暂存文件的去留将在下一次写入锁期间根据其哈希值决定(与已提交的哈希值匹配 → 提升为正式文件;否则 → 丢弃)。读取者绝不会重命名或删除任何内容:它们只会提供与已提交哈希值对应的文件。memory_write merge=true、日志/记忆类型检查,以及可选的 expected_hash 比较并交换,都会在同一把锁内执行。
快照与恢复
仅备份 memory.db 并不完整(还涉及 WAL 和 JSON 文件)。请使用 CLI:
mcp-memory-rs --snapshot /path/to/snap-2026-09-15 --with-backups # db + json + backups + manifest
mcp-memory-rs --restore /path/to/snap-2026-09-15 --stopped
mcp-memory-rs --verify-store # read-only: db vs json, pending files
--verify-store 不会打开 Store(不执行 PRAGMA、模式操作或协调):即使存储仍由另一个二进制程序占用,也可以安全使用。由早于 0.3.2 的版本写入的存储,可能存在类别文件比数据库行更新的情况(SQL 写入失败):--adopt-json --plan out.json 会以只读方式列出这些文件,而 --adopt-json --apply out.json 则会在锁内、满足前置条件后接纳这些文件。恢复的最终切换涉及若干次重命名——可安全复制,但作为整体并非原子操作:RESTORE_IN_PROGRESS 标记会使存储保持关闭,直到手动恢复被中断的切换。
创建快照时,会在整个过程中阻止写入者(读取者仍可继续),并运行 VACUUM INTO、复制类别文件,因此快照的两部分描述的是同一时刻;报告快照前还会先进行验证。覆盖范围会在 manifest.json 中明确说明:不带 --with-backups 时,仅包含当前内容和版本元数据——memory_history 负载(read_version)存放在 backups/ 中,需要使用 --with-backups 才会纳入。恢复前会先验证快照(完整性,以及每个类别都有一个哈希值与记录相符的文件),然后才会修改任何内容;接着替换在线存储,并将之前的存储保存在 <base_dir>/restore-parked-<timestamp>/ 下;必须先停止该存储上的所有 mcp-memory-rs 进程——--stopped 标志就是对此的声明。
构建与测试
cargo build --release # single static-friendly binary
cargo test # unit + integration tests
cargo clippy --all-targets -- -D warnings
构建时无需访问网络,除捆绑的 SQLite 外无其他 C 依赖。
许可证
Apache-2.0。详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。