MemoryFS
MemoryFS 是一个基于「Markdown 文件即数据库」理念的轻量级 AI 记忆系统。作为独立的 MCP (Model Context Protocol) Server,通过 HTTP (JSON-RPC 2.0) 协议为 Claude Code、OpenClaw、Cursor、Windsurf 等 AI Agent 提供持久化记忆读写通道。
核心特性
- 纯文本存储:记忆以含 YAML Frontmatter 的 Markdown 文件存储,天然兼容 Obsidian。
- 多因子评分检索:
grep关键词搜索 + 命中率 × 时间衰减 × 类型权重 × 标签匹配 × 项目匹配,配合 MMR 去重召回。 - 向量语义检索:可选的嵌入向量语义搜索,支持 Ollama / OpenAI / 硅基流动,混合模式效果最佳。
- 严格鉴权:Bearer Token 验权,支持多客户端区分和角色权限控制。
- 依赖图谱:自动追踪
blocks/ref关联,检索时串联依赖注入上下文。 - Web 管理面板:内建现代极简后台,支持 CRUD、索引重建、压缩归档与 JSON 导入导出。
- 速率限制:内置防滥用保护,各端点可配置限流。
架构
┌────────────────────┐ HTTP (JSON-RPC) ┌───────────────┐
│ AI Agent (Claude) │ ◄─────────────────► │ MCP Server │
└────────────────────┘ 鉴权: Bearer └───────┬───────┘
│
┌──────────────┬──────────┴──────────┐
▼ ▼ ▼
┌─────────────┐ ┌──────────┐ ┌────────────┐
│ grep/Scorer │ │ YAML 解析 │ │ Web Admin │
└─────────────┘ └──────────┘ └────────────┘
│
▼ (可选)
┌─────────────┐
│ Vector Store│ ← Ollama / OpenAI / 硅基流动
└─────────────┘
│
▼
/workspace/ (持久化文件系统)检索模式
MemoryFS 支持三种检索模式:
| 模式 | 说明 | 依赖 |
|---|---|---|
grep | 纯关键词匹配(默认) | 无 |
vector | 语义相似度搜索 | 需要嵌入 API |
hybrid | grep + vector 融合(效果最佳) | 需要嵌入 API |
评分算法
最终分数 = 基础分数 × 重要性权重 × 时间衰减 × 类型权重 × 标签匹配 × 项目匹配
| 因子 | 公式 | 说明 |
|---|---|---|
| 基础分数 | grep: 命中率 / vector: 余弦相似度 | 与查询的相关性 |
| 重要性权重 | 0.7 + 0.3 × importance | 用户定义优先级 (0-1) |
| 时间衰减 | 0.5^(天数/半衰期) | 半衰期指数衰减(见下表) |
| 类型权重 | decision: 1.4 / reflection: 1.2 / fact: 1.0 / entity: 0.8 / task: 0.6 | 不同类型权重不同 |
| 标签匹配 | 匹配标签数 / 查询标签数 | 无标签时为 1.0 |
| 项目匹配 | 同项目 ×1.2,否则 ×1.0 | 项目亲和性加成 |
半衰期参数
| 类型 | 半衰期 | 说明 |
|---|---|---|
| decision | 365 天 | 决策,衰减很慢 |
| fact | 180 天 | 事实/知识,较稳定 |
| reflection | 120 天 | 反思,中速衰减 |
| task | 30 天 | 任务,衰减快 |
| entity | ∞ | 永不衰减 |
状态惩罚
| 状态 | 惩罚系数 | 说明 |
|---|---|---|
| active / todo / doing / blocked / valid | 1.0 | 正常权重 |
| done | 0.3 | 已完成任务 |
| superseded / deprecated / inactive | 0.2 | 被替代决策、废弃知识、不活跃实体 |
MMR 去重
使用最大边际相关性算法去重,避免相似内容扎堆占据结果列表。
混合模式融合
当 EMBED_MODE=hybrid 时,grep 和 vector 分数融合计算:
- grep 提供精确关键词匹配
- vector 捕捉语义相似性
- 最终分数 = 两者加权融合
部署(Docker,推荐)
前置要求:VM 上安装 Docker + Docker Compose。TypeScript 编译在容器内完成,无需在宿主机安装 Node.js。
1. 获取代码
git clone /opt/memoryfs
cd /opt/memoryfs2. 配置环境变量
cp .env.example .env
nano .env必改项:
| 变量 | 说明 |
|---|---|
MCP_TOKEN | AI Agent 连接用的 Bearer Token,改为强随机字符串 |
MEMORYFS_DATA | 宿主机数据目录,知识库持久化于此,默认 ./Memory_Data |
ADMIN_PASS | Web 管理面板密码,建议用 bcrypt 哈希(见下方说明) |
HOST_PORT | 对外暴露端口,默认 3333 |
3. 启动
docker compose up -d --build
# 确认运行状态
docker compose ps
curl http://localhost:${HOST_PORT}/health
# 预期:{"status":"ok","workspace":"/workspace"}4. 常用运维命令
docker compose logs -f # 实时日志
docker compose restart # 重启服务
docker compose up -d --build # 更新重建
docker compose down # 停止(数据不丢失)配置参考
所有配置均通过 .env 文件注入,详见 .env.example(含中文注释)。
鉴权
两种方式二选一,不能同时生效:
# 方式一:单 Token(只有一个 Agent 接入时使用)
MCP_TOKEN=your-secret-token
# 方式二:多客户端(多个 Agent 或需要区分角色时使用)
# 启用后 MCP_TOKEN 将被完全忽略,所有 Token 都写进来
# role 支持:admin(可读写)| viewer(只读)
# MCP_CLIENTS='{"your-token-here": {"name": "claude-code", "role": "admin"}, "token-guest": {"name": "guest", "role": "viewer"}}'唯一免鉴权路由:GET /health
嵌入模式
EMBED_MODE=grep # grep(默认,无需外部服务)
# vector(需要嵌入 API)
# hybrid(grep + vector 融合,效果最佳)
EMBED_URL=http://localhost:11434 # Ollama / OpenAI 兼容服务地址
EMBED_MODEL=nomic-embed-text # 硅基流动用 BAAI/bge-m3
EMBED_DIMENSIONS=768 # 需与模型匹配
EMBED_API_KEY= # Ollama 留空;云端服务填 sk-xxx兼容的嵌入服务:
| 服务 | URL 示例 | 模型 | 维度 |
|---|---|---|---|
| Ollama(本地) | http://localhost:11434 | nomic-embed-text | 768 |
| 硅基流动 | https://api.siliconflow.cn/v1 | BAAI/bge-m3 | 1024 |
| OpenAI | https://api.openai.com/v1 | text-embedding-3-small | 1536 |
Web 管理面板
访问地址:http://:/admin
ADMIN_USER=admin
ADMIN_PASS=your-admin-password # 生产环境务必使用 bcrypt 哈希
ADMIN_ENABLED=true # false 则关闭 /admin 路由
COOKIE_SECURE=false # 通过 HTTPS 反向代理时设为 true生成 bcrypt 密码哈希(登录时仍输入原始密码,系统自动比对):
npm install && npm run hash-password
# 按提示输入密码,复制输出的 $2b$... 哈希值填入 ADMIN_PASS注意:Docker Compose 中 .env 的 $ 需转义为 $$:
ADMIN_PASS=$$2b$$10$$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx会话配置
SESSION_TTL=86400000 # 24 小时(默认)
SESSION_CLEANUP_INTERVAL=300000 # 5 分钟(默认)会话以 JSON 文件存储在 /.sessions/,容器重启后登录状态不丢失。
日志
LOG_LEVEL=info # 生产用 info,排查问题临时改 debug
LOG_PRETTY=false # false = JSON(生产);true = 彩色输出(调试)日志级别:fatal > error > warn > info > debug > trace
内置速率限制
| 端点 | 限制 | 时间窗口 |
|---|---|---|
POST /admin/login | 5 次 | 15 分钟 |
| API 写操作 | 30 次 | 1 分钟 |
| API 读操作 | 100 次 | 1 分钟 |
| JSON-RPC | 60 次 | 1 分钟 |
接入 AI Agent
接入方式概览
| 接入方式 | 适用客户端 | 前提 |
|---|---|---|
| HTTP 直连 | OpenClaw、Cursor、Windsurf、Claude Code 1.x+ | 无额外依赖 |
| Stdio 代理 | Claude Code 旧版、其他 Stdio-only 客户端 | 本机 Node.js 18+ |
OpenClaw
OpenClaw 原生支持 HTTP MCP,无需额外依赖,直接写入配置即可。
方式 A:跨机器部署(MemoryFS 在远程服务器)
{
"mcp": {
"servers": {
"memoryfs": {
"url": "http://:",
"transport": "http",
"headers": { "Authorization": "Bearer " }
}
}
}
}方式 B:同 Docker Compose 网络内(MemoryFS 容器名 memoryfs,内部端口 3000)
{
"mcp": {
"servers": {
"memoryfs": {
"url": "http://memoryfs:3000",
"transport": "http",
"headers": { "Authorization": "Bearer " }
}
}
}
}配置文件位置:~/.openclaw/config.json 或项目根目录 openclaw.json,重启 OpenClaw 生效。
Claude Code
方式 A:HTTP 直连(推荐,Claude Code 1.x+)
全局配置:编辑 ~/.claude.json,添加到 mcpServers 对象中:
{
"mcpServers": {
"memoryfs": {
"type": "http",
"url": "http://:",
"headers": { "Authorization": "Bearer " }
}
}
}项目级配置:在项目根目录创建 .mcp.json:
{
"mcpServers": {
"memoryfs": {
"type": "http",
"url": "http://:",
"headers": { "Authorization": "Bearer " }
}
}
}⚠️ 常见错误:~/.claude/mcp.json或~/.claude/mcp_settings.json均为无效配置位置。全局配置请用~/.claude.json,项目配置请用.mcp.json。
方式 B:Stdio 代理(旧版兼容,需本机 Node.js 18+)
先从仓库复制代理脚本:
cp /path/to/memoryfs-mcp/scripts/mcp-proxy.mjs ~/mcp-proxy.mjs项目 .mcp.json 配置:
{
"mcpServers": {
"memoryfs": {
"command": "node",
"args": ["/Users//mcp-proxy.mjs"],
"env": {
"MEMORYFS_URL": "http://:",
"MEMORYFS_TOKEN": ""
}
}
}
}Cursor / Windsurf / 其他兼容 MCP 客户端
参考 Claude Code HTTP 直连格式,核心参数不变:
- 协议:
http(JSON-RPC 2.0) - 鉴权头:
Authorization: Bearer - 端点:
http://:
一键自动配置(让 AI Agent 帮你接入)
把下方 Prompt 直接发给你的 AI Agent,它会自动完成 MCP 配置写入、连接验证和行为规范注入,无需手动编辑任何文件。
发送前将 ` 和 ` 替换为实际值。[MemoryFS 一键接入任务]
请按以下步骤帮我接入 MemoryFS 持久化记忆系统,每步完成后报告结果。
服务地址:
我的 Token:
步骤 1 — 写入 MCP 配置
在当前项目的 .mcp.json(若不存在则新建)中写入以下内容:
{
"mcpServers": {
"memoryfs": {
"type": "http",
"url": "",
"headers": { "Authorization": "Bearer " }
}
}
}
步骤 2 — 验证连接
调用 memory_stats 工具,确认返回知识库统计信息(正常返回即连接成功)。
步骤 3 — 注入行为规范
在当前项目的 AGENTS.md(若不存在则新建)末尾追加以下内容(原样追加,保留格式):
---
# 记忆库使用规范 (MemoryFS)
你已连接 MemoryFS 持久化外部记忆系统,存储了跨项目的架构决策、经验复盘与技术知识。
1. 先回忆,后行动:遇到问题或新任务前先用 memory_recall 搜索关键词,遭遇报错绝不盲目重试,立刻 recall 错误特征。
2. 按场景分类入库(认知循环:fact→decision→task→reflection→fact):
- 稳定技术知识/规范 → fact(importance ≥ 0.7)
- 架构/行为决策 → decision(importance ≥ 0.85)
- 踩坑/调试经验/完成任务复盘 → reflection(importance ≥ 0.8)
- 新项目/服务/人员 → entity
3. 记忆卫生:条目原子化(<500字),title 携带具体特征词,禁止堆栈倾倒。
4. 项目隔离:当前项目存对应 proj,跨项目知识存 global,切换项目调用 project_switch。
5. 决策演进:更新决策时创建新条目并通过 supersedes 指向旧条目,系统自动建立双向链接。
---
完成后,用中文汇报每步操作结果。Agent 行为规范(推荐注入系统提示词)
将以下内容注入 AI Agent 的系统提示词(AGENTS.md / CLAUDE.md / system prompt 均可):
# 记忆库使用规范 (MemoryFS)
你已连接到一个被称为 MemoryFS 的持久化外部记忆系统,存储了跨项目的架构决策、行事偏好、历史踩坑与通用规范。必须遵守以下行为逻辑:
1. 先回忆,后重试 (Recall before Retry)
- 回答问题、生成代码或设计架构前,先用 memory_recall 搜索关键词查阅已有规范。
- 遭遇工具失败、代码报错或异常行为时,绝对不准盲目重试!立刻对错误特征和核心对象执行
memory_recall,找寻历史踩坑记录和解决方案。
2. 分类入库(认知循环: fact → decision → task → reflection → fact)
按以下场景选择类型:
- 稳定技术知识、设计规范、公司规范 → fact(importance ≥ 0.7)
- 架构选型、当触发 X → 必须执行 Y → decision(importance ≥ 0.85)
- 未完成工作、依赖任务 → task
- 踩坑记录、调试经验、任务完成后复盘 → reflection(importance ≥ 0.8)
- 项目/服务/人员/外部系统 → entity
【重要】踩坑记录存 reflection,不存 fact。
3. 记忆卫生 (Hygiene)
- 条目必须短小、原子化(< 500 字)。
- title 应携带高度具体的报错特征、函数名或专有名词,保证关键词搜索高命中率。
- 禁止倾倒原始堆栈、重复结论或对话流水账。
4. 项目隔离与感知 (Scope)
- 当前项目记忆存入对应 proj,跨项目通用知识存 global。
- 对话转移到新项目域时,调用 project_switch 切换工作区并获取阻塞任务列表。
- 不定期调用 memory_stats 审查系统健康度。
5. 决策演进 (Decision Evolution)
- 更新决策时不修改旧条目,而是创建新条目并通过 supersedes 字段指向被替代的旧条目。
- 系统会自动将旧条目标记为 superseded 状态,并建立双向链接。
- 使用 memory_expand 可展开记忆图谱,沿 refs/blocks/supersedes 关系递归追踪依赖链。MCP Tool API
| 工具 | 说明 |
|---|---|
memory_store | 存入新事实、决策、任务,自动管理元数据 |
memory_recall | 基于关键词的多阶段评分检索 |
memory_expand | 展开记忆图谱,沿 refs/blocks/supersedes 关系递归追踪 |
memory_forget | 物理删除废弃记忆(soft/hard 模式) |
memory_compress | 归档低权重/已完成条目,瘦身知识库 |
memory_stats | 知识库统计:容量、阻塞任务、清理建议 |
project_switch | 切换 AI 工作焦点项目 |
index_rebuild | 强制重建全局 _index.md 缓存和向量索引 |
工具参数
memory_store:
{
type: 'decision' | 'task' | 'fact' | 'entity' | 'reflection',
title: string, // 应包含具体关键词便于搜索
content: string, // Markdown 正文,建议 < 500 字
proj?: string, // 项目名,默认 'global'
importance?: number, // 0-1,默认 0.6;踩坑/决策用 0.8+
confidence?: number, // 0-1,默认 0.9;置信度
status?: string, // 状态(按类型,默认自动填充)
tags?: string[], // 可选标签
blocks?: string[], // 阻塞的条目 ID
refs?: string[], // 关联的条目 ID 数组
supersedes?: string, // 被替代的旧条目 ID(用于决策更新)
}memory_recall:
{
query: string, // 关键词或语义描述
limit?: number, // 最大返回数,默认 10
proj?: string, // 按项目过滤
type?: string, // 按类型过滤
force?: boolean // 强制刷新索引
}memory_expand:
{
id: string, // 起始条目 ID
depth?: number, // 展开深度,默认 2,最大 5
}Web Admin API
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /admin/api/entries | 列出条目(可按 type/proj/q 过滤) |
| GET | /admin/api/entries/:id | 获取单条 |
| POST | /admin/api/entries | 创建条目 |
| PUT | /admin/api/entries/:id | 更新条目 |
| DELETE | /admin/api/entries/:id | 删除条目 |
| POST | /admin/api/rebuild | 重建索引 |
| POST | /admin/api/compress | 压缩归档 |
| GET | /admin/api/stats | 获取统计 |
| GET | /admin/api/export | 导出所有条目(JSON) |
| POST | /admin/api/import | 导入条目(JSON) |
工作区文件结构
MEMORYFS_DATA 宿主机目录在容器内挂载为 /workspace:
Memory_Data/ # 宿主机目录(MEMORYFS_DATA)
├── memory.md # 高重要性记忆摘要(热数据)
├── projects.md # 项目注册表
├── user.md # 用户身份与偏好
├── journal/ # 每日操作日志
├── kb/
│ ├── _index.md # 全局知识索引(缓存,自动维护)
│ ├── decisions/ # 架构与技术决策
│ ├── tasks/ # 任务与里程碑
│ ├── facts/ # 稳定技术知识与规范
│ ├── entities/ # 重要实体配置
│ └── reflections/ # 经验复盘与踩坑记录
├── .sessions/ # Web Admin 会话文件(自动管理)
└── .mcp/
└── vector.db/ # LanceDB 向量索引(EMBED_MODE=vector/hybrid 时)开发与测试
# 本地开发(需 Node.js 18+)
npm install
npm run dev # tsx watch 热重载
# 构建
npm run build
# 测试(289 tests / 9 模块)
npm test
npm run test:coverage # 生成覆盖率报告(coverage/index.html)
# 生成密码哈希
npm run hash-password技术栈
- 运行时:Node.js 20 + TypeScript
- 框架:Hono(轻量级 HTTP 框架)
- 日志:Pino(结构化 JSON 日志)
- 鉴权:bcrypt 密码哈希
- 向量库:LanceDB(嵌入式,无需外部服务)
- 测试:Vitest
- 部署:Docker 多阶段构建
