关于 Mnemon — Persistent Layered Memory for AI Agents
Mnemon 是面向 AI Agent 的本地优先记忆服务,将情景、语义、程序和资源记忆存储在 SQLite 中。它结合可搜索记忆与事实版本管理,并可选用向量检索。
主要功能
- 01按四个层次组织记忆
- 02使用 FTS5 和 BM25 搜索
- 03支持可选向量及混合检索
- 04通过替代链管理事实版本
- 05导入 Markdown 知识库
- 06将记忆导出为 JSON 或 Markdown
适用场景
- 01在 Agent 会话间保留上下文
- 02按主题或日期搜索记忆
- 03追踪不断变化的事实
- 04将 Markdown 笔记导入记忆
MCP 相关
Mnemon 通过 stdio 或 HTTP 向兼容 MCP 的客户端提供记忆工具、资源和提示词。其工具支持记忆存储、搜索、更新、会话管理、导出和诊断。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y mnemon-mcpMNEMON_DB_PATHPath to SQLite database file (default: ~/.mnemon-mcp/memory.db)MNEMON_EMBEDDING_PROVIDEREmbedding provider for vector search: 'openai' or 'ollama' (default: disabled)MNEMON_EMBEDDING_API_KEY密钥API key for embedding provider (required for OpenAI)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mnemon-mcp
为 AI Agent 提供持久化的分层记忆。 本地优先。零云端。单个 SQLite 文件。
你的 AI Agent 每次会话结束后都会忘记一切。Mnemon 解决了这个问题。
它为任何兼容 MCP 的客户端——OpenClaw、Claude Code、Cursor、Windsurf 或你自己的客户端——提供由你机器上的单个 SQLite 数据库支持的结构化长期记忆。无需 API 密钥,无需云端,无遥测。只需 npm install,你的 Agent 就能记住信息。
为什么要使用分层记忆?
扁平的键值存储会把“昨天发生了什么”和“提交前绝不跳过测试”一视同仁。这是不合理的——不同类型的知识有不同的生命周期和访问模式。
Mnemon 将记忆组织成四个层级:
| 层级 | 存储内容 | 访问方式 | 生命周期 |
|---|---|---|---|
| Episodic | 事件、会话、日志条目 | 按日期或时间段 | 逐渐衰减(半衰期为 30 天) |
| Semantic | 事实、偏好、关系 | 按主题或实体 | 稳定 |
| Procedural | 规则、工作流、约定 | 启动时加载 | 很少变化 |
| Resource | 参考资料、读书笔记 | 按需 | 缓慢衰减(90 天) |
上周二的日志条目和永不更改的编码规则属于不同层级——因为它们理应如此。
检索质量
检索质量基于真实的 797 条记忆双语(RU/EN)语料库,通过实际的 MCP 服务(而非重新实现)在 50 个黄金测试用例上进行评估。当前数据(方法与历史):
| 指标 | 仅 FTS | 仅向量 | 混合(RRF) |
|---|---|---|---|
| 综合得分 | 88.9 | 89.2 | 91.7 |
| Recall@5 | 0.907 | 0.898 | 0.919 |
| MRR | 0.817 | 0.832 | 0.878 |
| nDCG@5 | 0.816 | 0.828 | 0.869 |
| 负例精确率 | 1.000 | 1.000 | 1.000 |
混合检索优于两种单独的检索方式,这正是融合它们的全部意义:词法搜索的原始召回率更高,向量搜索的排序更好,而 RRF 能兼顾两者,而不是将它们平均掉。
评估文档也记录了失败情况——语料库增长时的得分漂移、评估发现的 BM25 字段权重错误、融合效果仍不如纯词法搜索的两个案例,以及黄金测试集未涵盖的内容。无法审计的数据只是营销;了解这些数据是如何得出的。
架构
flowchart LR
C["MCP client<br/>Claude Code · Cursor · …"] -- "stdio / HTTP" --> T["10 tools · 4 resources · 3 prompts"]
T --> R["retrieval pipeline<br/>FTS5 · vector · RRF fusion"]
T --> M["memories + supersede chains"]
I["KB import pipeline<br/>markdown → memories"] --> M
M -- triggers --> F["FTS5 index (stemmed EN+RU)"]
R --> F
R --> V["sqlite-vec (optional, BYOK)"]
单个 SQLite 文件存储记忆、FTS5 索引和可选的向量索引。写入通过事务进行,以维持 supersede-chain 不变量;读取则运行搜索部分所述的分阶段检索流程。
完整说明——包括模块边界、读写路径、不变量和已知限制——请参阅docs/ARCHITECTURE.md。设计决策记录在 ADR 中:SQLite+FTS5 核心、混合 RRF 检索、同步驱动、分层记忆模型。
快速开始
安装
npm install -g mnemon-mcp
或者从源代码安装:
git clone https://github.com/nikitacometa/mnemon-memory-mcp.git
cd mnemon-memory-mcp && npm install && npm run build
配置 MCP 客户端
OpenClaw
openclaw mcp register mnemon-mcp --command="mnemon-mcp"
或者添加到 ~/.openclaw/mcp_config.json:
{
"mnemon-mcp": {
"command": "mnemon-mcp"
}
}
Claude Code
添加到 ~/.claude/mcp.json:
{
"mcpServers": {
"mnemon-mcp": {
"command": "mnemon-mcp"
}
}
}
Cursor / Windsurf / Other MCP clients
添加到客户端的 MCP 配置中:
{
"mcpServers": {
"mnemon-mcp": {
"command": "mnemon-mcp"
}
}
}
从源代码运行?
使用编译后入口点的完整路径:
{
"mnemon-mcp": {
"command": "node",
"args": ["/absolute/path/to/mnemon-mcp/dist/index.js"]
}
}
验证
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | mnemon-mcp
你应该会在响应中看到 10 个工具。数据库(~/.mnemon-mcp/memory.db)会在首次运行时自动创建。
就是这样。现在,你的 Agent 拥有了持久记忆。
功能介绍
10 个 MCP 工具
| 工具 | 功能 |
|---|---|
memory_add | 存储记忆,并设置层、实体、置信度、重要性和可选的 TTL |
memory_search | 全文或精确搜索,可按层、实体、日期、范围和置信度筛选 |
memory_update | 原地更新,或创建带版本的替代项(替代链) |
memory_delete | 删除记忆;如有前序版本,则重新激活该版本 |
memory_inspect | 获取各层统计数据,或追踪单条记忆的版本历史 |
memory_export | 按筛选条件导出为 JSON、Markdown 或 Claude-md 格式 |
memory_health | 运行诊断:检查过期条目、孤立链和陈旧记忆;可选择执行 GC |
memory_session_start | 开始 Agent 会话 — 返回用于归组记忆的会话 ID |
memory_session_end | 结束会话,可选提供摘要;返回持续时间和记忆数量 |
memory_session_list | 列出会话,可按客户端、项目或活动状态筛选 |
MCP 资源与提示词
资源 — Agent 可读取的实时数据:
| URI | 返回内容 |
|---|---|
memory://stats | 各层的汇总统计数据 |
memory://recent | 过去 24 小时内创建或更新的记忆 |
memory://layer/{layer} | 某一层中的所有有效记忆 |
memory://entity/{name} | 关于某个实体的所有有效记忆 |
提示词 — 预构建工作流:
| 提示词 | 用途 |
|---|---|
recall | “告诉我你所了解的关于 X 的所有信息” |
context-load | 开始任务前加载相关上下文 |
journal | 创建结构化日志条目 |
搜索
四种模式均支持按层 / 实体 / 范围 / 日期 / 置信度筛选:
FTS 模式(未配置嵌入时的默认模式)— 使用 BM25 排名的分词全文搜索。多词查询使用 AND;结果过少时,会以 OR 补充并施加分数惩罚。渐进式 AND 放宽会先尝试最具体的前 3 个词,再回退到完整 OR。
混合模式(配置嵌入后的默认模式)— 通过 Reciprocal Rank Fusion 结合 FTS5 和向量搜索。会检测查询中的带引号实体(例如 'Essentialism'),并运行加权子查询以检索交叉引用。
向量模式 — 对嵌入执行纯余弦相似度搜索。
精确模式 — 使用 LIKE 子串匹配精准查找短语。
分数:bm25 × (0.3 + 0.7 × importance) × decay(layer) × recency
近期度加成:1 / (1 + daysSince / 365) — 轻微提升近期创建的记忆,不会惩罚较旧的记忆。
词干提取
Snowball 词干提取器会在索引时和查询时应用于英语和俄语。这意味着 "running" 可匹配 "runs",而 "книги" 可匹配 "книга"。查询中的停用词会被过滤,以提高精确度。
事实版本管理
知识会不断演变。Mnemon 不会删除旧事实,而是将它们串联起来:
v1: "Team uses React 17" → superseded_by: v2
v2: "Team uses React 19" → supersedes: v1 (active)
搜索只会返回最新版本。使用 include_history: true 调用 memory_inspect 可查看完整链条。memory_delete 会重新激活前序版本 — 不会丢失任何内容。
向量搜索(可选,BYOK)
提供自己的嵌入 API,即可启用语义相似度搜索:
# OpenAI
MNEMON_EMBEDDING_PROVIDER=openai MNEMON_EMBEDDING_API_KEY=sk-... mnemon-mcp
# Ollama (local, free)
MNEMON_EMBEDDING_PROVIDER=ollama mnemon-mcp
这会解锁两种额外的搜索模式:
mode: "vector"— 纯余弦相似度搜索mode: "hybrid"— 通过 Reciprocal Rank Fusion 合并 FTS5 和向量搜索
需要 sqlite-vec(作为可选依赖安装)。添加新记忆时会生成嵌入;现有记忆可批量补全嵌入。
嵌入配置
| 变量 | 默认值 | 描述 |
|---|---|---|
MNEMON_EMBEDDING_PROVIDER | — | openai 或 ollama(未设置 = 已禁用) |
MNEMON_EMBEDDING_API_KEY | — | API 密钥(OpenAI 必需) |
MNEMON_EMBEDDING_MODEL | text-embedding-3-small / nomic-embed-text | 模型名称 |
MNEMON_EMBEDDING_DIMENSIONS | 1024 / 768 | 向量维度 |
MNEMON_OLLAMA_URL | http://localhost:11434 | Ollama 端点 |
导入知识库
有一组 Markdown 文件?可以批量导入:
cp config.example.json ~/.mnemon-mcp/config.json # edit this first
npm run import:kb -- --kb-path /path/to/your/kb # incremental (skips unchanged files)
配置会将 glob 模式映射到记忆层:
{
"owner_name": "your-name",
"extra_stop_words": [],
"mappings": [
{
"glob": "journal/*.md",
"layer": "episodic",
"entity_type": "user",
"entity_name": "$owner",
"importance": 0.6,
"split": "h2"
},
{
"glob": "people/*.md",
"layer": "semantic",
"entity_type": "person",
"entity_name": "from-heading",
"importance": 0.8,
"split": "h3"
}
]
}
配置字段
| 字段 | 类型 | 描述 |
|---|---|---|
owner_name | string | 您的姓名 — 用于在 entity_name 中替换 $owner |
extra_stop_words | string[] | 从 FTS 查询中过滤的词语(例如您的姓名形式) |
glob | string | 匹配的文件模式 |
layer | string | 目标记忆层 |
entity_type | string | user / person / project / concept / file / rule / tool |
entity_name | string | 字面名称、"$owner" 或 "from-heading"(从 H2/H3 中提取) |
split | string | "whole"(每个文件作为一条记忆)、"h2" 或 "h3"(按标题拆分) |
importance | number | 0.0–1.0,会影响搜索排序 |
confidence | number | 0.0–1.0,可在搜索中筛选 |
scope | string | 可选命名空间 |
HTTP 传输
适用于远程或多客户端配置:
MNEMON_AUTH_TOKEN=your-secret MNEMON_HOST=0.0.0.0 MNEMON_PORT=3000 npm run start:http
| 端点 | 描述 |
|---|---|
POST /mcp | MCP JSON-RPC(设置令牌后使用 Bearer 身份验证) |
GET /health | {"status":"ok","version":"..."} |
默认绑定到 127.0.0.1。绑定到其他主机时必须设置 MNEMON_AUTH_TOKEN — 否则服务会拒绝在未经身份验证的情况下向网络公开记忆存储(在可信网络中可通过 MNEMON_ALLOW_INSECURE_HTTP=1 覆盖)。默认限流为每个 IP 每分钟 100 个请求;CORS 需选择启用;请求正文限制为 1MB;身份验证采用计时安全比较;收到 SIGTERM 时会优雅关闭。
配置参考
| 变量 | 默认值 | 描述 |
|---|---|---|
MNEMON_DB_PATH | ~/.mnemon-mcp/memory.db | 数据库路径 |
MNEMON_KB_PATH | . | 导入时使用的知识库根目录 |
MNEMON_CONFIG_PATH | ~/.mnemon-mcp/config.json | 导入配置路径 |
MNEMON_AUTH_TOKEN | — | HTTP 传输的 Bearer 令牌 |
MNEMON_HOST | 127.0.0.1 | HTTP 传输绑定地址 |
MNEMON_PORT | 3000 | HTTP 传输端口 |
MNEMON_CORS_ORIGIN | — | CORS Access-Control-Allow-Origin(未设置时不发送 CORS 标头) |
MNEMON_RATE_LIMIT | 100 | 每个 IP 每分钟的最大请求数(0 = 关闭) |
工具参考
memory_add — 完整参数列表
| 参数 | 类型 | 必填 | 描述 |
|-----------|------|----------|-------------|
| `content` | string | 是 | 记忆文本(最多 100K 个字符) |
| `layer` | string | 是 | `episodic` / `semantic` / `procedural` / `resource` |
| `title` | string | 否 | 简短标题(最多 500 个字符) |
| `entity_type` | string | 否 | `user` / `project` / `person` / `concept` / `file` / `rule` / `tool` |
| `entity_name` | string | 否 | 用于筛选的实体名称 |
| `confidence` | number | 否 | 0.0–1.0(默认值为 0.8) |
| `importance` | number | 否 | 0.0–1.0(默认值为 0.5) |
| `scope` | string | 否 | 命名空间(默认值为 `global`) |
| `source_file` | string | 否 | 源文件路径 — 会触发对匹配条目的自动取代 |
| `ttl_days` | number | 否 | N 天后自动过期 |
| `valid_from` / `valid_until` | string | 否 | 时效事实的有效期(ISO 8601) |
memory_search — 完整参数列表
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
query | string | 是 | 搜索文本 |
mode | string | 否 | fts(默认值)、exact、vector、hybrid |
layers | string[] | 否 | 按层筛选 |
entity_name | string | 否 | 按实体筛选(支持别名) |
scope | string | 否 | 按作用域筛选 |
date_from / date_to | string | 否 | 日期范围(ISO 8601) |
as_of | string | 否 | 时效事实筛选 — 筛选在此日期有效的事实 |
min_confidence | number | 否 | 最低置信度 |
min_importance | number | 否 | 最低重要性 |
limit | number | 否 | 最大结果数(默认值为 10,最大值为 100) |
offset | number | 否 | 分页偏移量 |
memory_update — 完整参数列表
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
id | string | 是 | 记忆 ID |
content | string | 否 | 新内容 |
title | string | 否 | 新标题 |
confidence | number | 否 | 新置信度 |
importance | number | 否 | 新重要性 |
supersede | boolean | 否 | true = 创建带版本的新条目以取代原条目;false(默认值)= 原位更新 |
new_content | string | 否 | 用于取代条目的内容 |
memory_delete
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
id | string | 是 | 记忆 ID。如果该记忆属于取代链,则重新激活其前置条目 |
memory_inspect
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
id | string | 否 | 记忆 ID(省略则显示汇总统计) |
layer | string | 否 | 按层筛选统计数据 |
entity_name | string | 否 | 按实体筛选统计数据 |
include_history | boolean | 否 | 显示取代链 |
memory_export
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
format | string | 是 | json / markdown / claude-md |
layers | string[] | 否 | 按层筛选 |
scope | string | 否 | 按作用域筛选 |
date_from / date_to | string | 否 | 日期范围 |
limit | number | 否 | 最大条目数(默认值为全部,最大值为 10K) |
memory_health
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
cleanup | boolean | 否 | true = 清理过期条目(默认仅报告) |
返回:状态(healthy / warning / degraded)、各层统计数据、过期条目、孤立链、过时/低置信度条目数,以及当 cleanup=true 时的已清理条目数。
memory_session_start
| 参数 | 类型 | 必填 | 描述 |
|-----------|------|----------|-------------|
| `client` | string | 是 | 客户端标识符(例如 `claude-code`、`cursor`、`api`) |
| `project` | string | 否 | 此会话的项目范围 |
| `meta` | object | 否 | 其他会话元数据 |
返回:id(会话 UUID)、started_at(ISO 8601)。
memory_session_end
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
id | string | 是 | 要结束的会话 ID |
summary | string | 否 | 已完成事项的摘要(最多 10K 个字符) |
返回:id、ended_at、duration_minutes、memories_count。
memory_session_list
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
limit | number | 否 | 会话数量上限(默认 20,最大 100) |
client | string | 否 | 按客户端筛选 |
project | string | 否 | 按项目筛选 |
active_only | boolean | 否 | 仅返回尚未结束的会话(默认 false) |
返回:包含 id、client、project、started_at、ended_at、summary、memories_count 的会话数组。
对比
| mnemon-mcp | mem0 | basic-memory | Engram | Anthropic KG | |
|---|---|---|---|---|---|
| 架构 | SQLite FTS5 + 向量 | 云 API + Qdrant | Markdown + 向量 | SQLite FTS5 | JSON 文件 |
| 记忆结构 | 4 个类型化层 | 扁平 | 扁平 | 扁平 + 会话 | 图 |
| 搜索 | FTS5 + 混合 RRF | 语义 | 混合 | FTS5 | 精确 |
| 事实版本管理 | 替代链 | 部分支持 | 不支持 | 不支持 | 不支持 |
| 词干提取 | EN + RU(Snowball) | 仅 EN | 仅 EN | 无 | 无 |
| 嵌入 | BYOK(OpenAI / Ollama) | 内置 | FastEmbed | 无 | 无 |
| 依赖项 | 无必需项 | Qdrant、Neo4j | Python 3.12 | Go 二进制文件 | 无 |
| 需要云服务 | 否 | 是 | 否 | 否 | 否 |
| 费用 | 免费 | $19–249/月 | 免费 | 免费 | 免费 |
| 安装 | npm install -g | Docker + API 密钥 | pip + 依赖项 | Go install | 内置 |
| 许可证 | MIT | Apache 2.0 | AGPL | MIT | MIT |
扩展版竞品分析及其来源见:docs/COMPETITORS.md。
开发
npm run dev # run via tsx (no build step)
npm run build # TypeScript → dist/
npm run lint # eslint (flat config)
npm test # vitest — unit + integration + MCP dispatch + HTTP transport + hybrid RRF
npm run bench # performance benchmarks
npm run db:backup # backup database
CI 会在 Node 20 和 22 上运行构建、代码检查和测试,然后通过真实 JSON-RPC 执行编译后服务的冒烟测试(tools/list 必须与确切的工具集一致)。
技术栈: TypeScript 5.9(严格模式)、better-sqlite3、@modelcontextprotocol/sdk、Snowball 词干提取器、Zod、vitest。
代码规范请参阅 CONTRIBUTING.md。
设计原则
- 默认支持物理隔离环境——始终零遥测。开箱即用时不会有任何数据离开设备;唯一会连接网络的组件是可选的嵌入器,且只连接到你配置的提供方(包括本地 Ollama)。
- 单文件——一个 SQLite 数据库,无需运维,通过复制文件即可即时备份。
- 确定性搜索——默认使用 FTS5,而非嵌入。结果可解释、可复现,无需 GPU。
- 结构化优于扁平化——分层结构编码访问模式;替代链编码时间。
- 精简——4 个生产依赖项。可在 Node 运行的任何环境中使用。
- 以测量为依据,而非空口断言——根据黄金集评估检索变更,其中也包括回归测试。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。