关于 marm-mcp-server
marm-mcp-server 为 AI Agent 提供跨会话共享的本地记忆,并包含代码图谱与概念图谱能力。它支持 HTTP 和 STDIO,可用于个人项目或多 Agent 共享场景。
主要功能
- 01保存对话、笔记和摘要
- 02语义检索与记忆去重
- 03索引代码库并查找符号
- 04关联记忆中的实体与概念
- 05提供本地 Web 控制台
适用场景
- 01在不同会话间保留项目决策
- 02让多个 Agent 共享项目上下文
- 03查询代码符号及调用路径
- 04浏览记忆、概念和代码关联
MCP 相关
提供 16 个 MCP 工具,涵盖记忆、代码图谱和概念图谱,并支持 HTTP 与 STDIO 传输。Agent 可连接同一运行时,共享跨会话记忆。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
16收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | integer | 否 | |
| query | string | 是 | |
| detail | integer | 否 | |
| project | any | 否 | |
| platform | any | 否 | |
| exact_mode | string | 否 | |
| search_all | boolean | 否 | |
| include_logs | boolean | 否 | |
| session_name | string | 否 |
详细介绍
marm-memory v2.60.1 - 60 秒内为你的 AI Agent 提供永久记忆
欢迎贡献!浏览待处理议题参与贡献,或加入 MARM Discord,分享工作流、获取设置帮助并与其他构建者交流。
重要说明
项目状态:短暂的个人休整
我暂时离开了活跃开发,专注处理项目之外的事务。本项目仍在持续维护,我计划很快回来,继续开发和完善项目。
感谢你的耐心、支持和持续关注。我很快会恢复工作,并随着进展分享最新动态。
目录
- 快速开始
- 为什么选择 MARM Memory
- MARM 控制台
- 性能与扩展基准测试
- MCP 客户端设置
- 运行时 CLI 命令
- 完整 MCP 工具套件
- 使用 MARM:直接对话,无需调用工具
- 了解 MARM Memory
- 知识图谱:代码与概念
- 架构与内部机制
- 故障排除
- 参与贡献
- 项目文档
快速开始
- 使用你偏好的 Agent 配置文件进行安装和初始化:
pip install marm-mcp-server
marm-memory init --g-claude --g-codex --g-antigravity
另有以下选项:--g-cursor、--g-grok、--g-hermes、--g-opencode、--g-devin、--g-cline、--g-qwen、--g-kiro 和 --g-zed。不带标志运行时,会安装到当前项目文件夹,而不是主目录
- 将任务交给你的 AI 伙伴。告诉你的 Agent:
“使用 marm-init 技能来设置 MARM。”
- 开始互动:你的 Agent 会直接在聊天中以交互方式处理整个设置过程(Python/Docker、HTTP/STDIO、密钥和客户端配置)。
手动设置
更喜欢自行配置:
将“agent”替换为客户端的 CLI 命令(例如 claude、agy 或 qwen)。对于 Codex,请改用 codex mcp add marm-memory --url http://localhost:8001/mcp。
| 如果你是…… | 启动服务 | 连接 MCP 客户端 |
|---|---|---|
| 个人开发者 / 研究人员 | marm-memory start | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp |
| 使用私有本地 STDIO 的用户 | marm-mcp-stdio | "agent" mcp add --transport stdio marm-memory-stdio marm-mcp-stdio |
| 多个 Agent 共享记忆 | marm-memory start --profile swarm | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp |
| 私有高吞吐量 Agent 集群 | marm-memory start --profile swarm-max | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp |
| 可信的私有实验室 / 服务端 | marm-memory start --profile trusted | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp |
- ⚡ **最快的 HTTP 启动方式:**运行 marm-memory fast-start-http,即可启动本地运行时、打开控制台并立即在浏览器中访问。
- 🖥️ **Web 控制台:**运行 marm-memory console,即可立即查看本地 UI 应用(无需 Node.js)。
- ⚙️ **生命周期管理:**使用 status、logs --follow、restart 和 stop 管理后台守护进程。
- 💡 **快速标志:**使用 --no-console 或 --no-browser 限制启动行为。运行 marm-memory --help 查看完整命令列表。
为什么选择 MARM Memory
你的 AI 会忘记一切。MARM Memory 不会。
marm-memory 为你的 Agent 提供私有共享记忆,用于保存通常会在不同聊天之间丢失的上下文:决策、研究、修复、笔记和项目历史。切换到 Codex 或 Gemini,告别 Claude Code,也不会丢失已收集的上下文。
它整合了三项功能:
- 🧠 **核心记忆(8 个工具)**用于存储对话、笔记、笔记本条目和摘要,方便随时搜索。
- 💻 **代码图谱(6 个工具)**用于映射代码仓库,让 Agent 查找符号、追踪代码路径并理解项目,而不必重新通读所有代码。只需指定一次代码仓库,它就会在你工作时持续更新。
- 🧩 **概念图谱(2 个工具)**用于关联已存储记忆中的人物、决策、错误和想法,并在可能时链接到相关代码。随着记忆的存储,它会自动构建。
全部 16 个工具均支持 HTTP 和 STDIO。你的 Agent 可以跨会话共享同一本地记忆,而不必每次都从头开始。随附的控制台应用提供本地控制面板,可用于管理记忆、图谱、代码上下文、提炼、运行时控制和集成终端。为代码仓库建立索引后,会创建独立的代码图谱;即使尚未存储任何记忆,也可以通过“知识图谱”→“代码浏览器”探索该图谱。
工作原理
| 层 | 功能 | 重要性 |
|---|---|---|
| 记忆模型 | 会话、结构化日志、笔记本、摘要和语义记忆 | 让项目历史可供搜索,而不是困在一段聊天中 |
| 扩展层 | SQLite WAL 模式、连接池、串行写入队列和 HTTP 速率限制预设 | 让一台服务支持个人使用、多 Agent 协作以及蜂群式突发负载 |
| 智能层 | FTS 筛选、语义重排、有界语义回退、自动分类、写入时整合和压缩候选项 | 随着记忆增长,让回忆依然有效,而不是任由重复内容堆积 |
| 代码图谱层 | 仓库索引、符号查询、调用追踪、架构概览和变更影响分析 | 无需重新阅读整个代码库,即可让 Agent 了解项目结构 |
| 概念图谱层 | 从已存储的记忆中提取实体和关系,并链接回代码图谱 | 跨会话关联决策、错误、工具和人员,而不是将它们留作纯文本 |
| Token 层 | 轻量级 8 工具核心接口(包含捆绑的图谱工具时共 16 个工具)、检索前进行语义重排,以及写入时去重 | 减少每次回忆时发送给模型的 Token 数量,并让记忆扩展后的成本保持可预测 |
| 部署层 | Pip、Docker、STDIO、HTTP,以及托管的 swarm、swarm-max 和 trusted 配置 | 使用相同的 MCP 接口,运行私有本地记忆或共享的多 Agent 记忆 |
如需了解检索延迟、并发和写入成本数据,请参阅性能与扩展基准测试;如需了解各层背后的机制,请参阅架构与内部机制。
MARM 控制台:您的本地控制平面
运行 marm-memory console,即可在 http://127.0.0.1:8002 打开捆绑的 Web 应用。它随 MARM 一同提供,无需安装 Node.js,始终运行在您的机器上,并使用与 Agent 相同的本地存储和 MCP 运行时。
| 工作区 | 提供的功能 |
|---|---|
| 记忆与知识图谱 | 浏览、筛选、编辑和清理记忆、日志、笔记本、提取出的概念、重复项、概念构建和代码链接。 |
| 已索引项目与项目浏览器 | 为本地仓库建立索引,检查架构、影响、覆盖率、决策、运行时追踪、符号搜索和代码图谱拓扑。 |
| 代码上下文 | 构建一个有界视图,其中包含按任务排序的符号、源代码和相关记忆。可选的本地模型可以基于相同上下文作答,并对其引用进行检查。 |
| 提炼 | 将转录内容转化为持久记忆提案。查看、应用或丢弃这些提案,并查看重复内容的证据。 |
| 系统与终端 | 管理运行时健康状态、索引、本地模型设置、备份、诊断和维护。停靠式终端提供真正的本地 Shell,支持持久会话和可搜索的 MARM 命令菜单。 |
| 连接 | 在一个位置完成 MARM 的端到端设置。设置通过 HTTP、STDIO 或 Docker STDIO 连接 Claude Code、Claude Desktop、Cursor、VS Code、Codex CLI、Grok Build、Hermes Agent、OpenCode、Cline、Antigravity、Qwen Code、Devin、Kiro 和 Zed,测试每个连接,并将服务设置保存到 ~/.marm/settings.json。Docker 拉取、启动和停止 MARM 容器,并写入 compose 文件。手动为每个客户端和操作系统提供可直接复制的配置、所有 CLI 命令和所有 HTTP 端点。 |
运行时 CLI 命令
marm-memory 是随 Python 软件包安装的本地运行时管理器。这些是常用的运维命令;如需查看标志和特定命令示例,请使用 marm-memory <command> --help。
日常运行时操作
marm-memory fast-start-http # start HTTP, Console, and open the browser
marm-memory fast-start-http --client cursor # also connect one client (add --transport stdio for STDIO)
marm-memory start # start or reuse the managed HTTP runtime
marm-memory start --profile swarm # shared multi-agent preset
marm-memory stop # stop the managed runtime safely
marm-memory restart # restart the managed runtime
marm-memory status # inspect runtime, database, queue, and graph status
marm-memory logs --follow # follow bounded runtime logs
marm-memory console # start or reuse the bundled local Console
传输方式与设置
marm-memory http # run HTTP in the foreground
marm-memory stdio # run the strict local MCP STDIO transport
marm-memory init # install the MARM skill into detected agents (project scan)
marm-memory init --g-claude # install the skill into the home-folder claude directory
marm-memory doctor # diagnose the local install
marm-memory key init # create or reuse ~/.marm/.env without displaying the key
marm-memory key path # print the managed key-file path
marm-memory key reveal # explicitly display the managed key
marm-memory console --import-key # open an authenticated local Console session
marm-memory upgrade --check # compare the installed package with PyPI
marm-memory uninstall # preview package removal; always preserves ~/.marm
知识、项目与维护
marm-memory knowledge status # Indexers, models, and how far behind automatic indexing is
marm-memory knowledge build --all # Rebuild the whole concept graph (new memories index themselves)
marm-memory knowledge auto off # Stop indexing memories automatically (on, off, status)
marm-memory projects list # List all tracked workspaces
marm-memory projects index <path> # Add a repo to the code graph (kept current after that)
marm-memory projects status # Inspect target repo graph readiness
marm-memory projects auto off # Stop re-indexing repos automatically (on, off, status)
marm-memory maintenance status # Check internal database optimization state
marm-memory maintenance embeddings migrate # Upgrade old 384-dim vectors to 512-dim
marm-memory maintenance chunks rechunk # Recalibrate long memory text splits
Docker 命令单独记录在下文,因为它们需要明确选择数据挂载、网络暴露方式和密钥处理方式。
性能与扩展性基准测试
MARM 优先针对快速回忆进行调优,即使记忆不断增长,并在幕后将长记忆分块,也能保持快速回忆。
这些测量使用由 fastembed 提供支持的 jinaai/jina-embeddings-v2-small-en 编码器和临时本地 SQLite 数据库。每条计时路径都调用已发布的 MARMMemory 代码,而非基准测试专用的重新实现。第 1 至第 4 节的数据来自在本地硬件上单次运行 scripts/benchmarking/performance/bench_hotpath.py 的计时结果;绝对毫秒数因机器而异,因此应关注扩展趋势。第 5 节是单独的准确率基准测试(run_eval.py),衡量的是检索效果而非速度;其中最新一行是受控的前后对比,具体说明见该节。
1. 检索延迟扩展性
端到端 recall_similar 延迟(包括查询编码)。
| 会话大小($N$) | 最低延迟 | 中位延迟 | p95 延迟 |
|---|---|---|---|
| N = 100 | 7.4 ms | 7.9 ms | 9.4 ms |
| N = 250 | 11.9 ms | 13.5 ms | 15.4 ms |
| N = 500 | 10.9 ms | 11.8 ms | 13.4 ms |
| N = 1,000 | 13.3 ms | 13.5 ms | 15.6 ms |
| N = 2,000 | 17.5 ms | 18.2 ms | 19.6 ms |
| N = 4,000 | 23.8 ms | 25.9 ms | 30.9 ms |
在较小的 $N$ 下,不同运行之间的波动大于相邻规模之间的差异,因此这里 N = 250 的耗时高于 N = 500。应将 N = 1,000 及以上的趋势视为真实信号。
2. 编码器与并发
- 冷启动模型加载:
893ms - 热启动编码: 中位数
3.8ms,p954.3ms - 并发回忆: 10 次汇集执行的回忆耗时
151.5ms,而串行执行耗时176.0ms(gather/serial = 0.86)。不要将其解读为并行执行:同一基准测试的多次运行结果介于0.63到0.86之间,因此该比率不够稳定,不能据此宣称提速。按照设计,这条路径会在共享编码器和 SQLite 操作处串行执行;任何看似的提升都是测量噪声。
3. 写入时的摄取开销
- 关闭整合: 中位数
6.5ms,p957.6ms - 开启整合: 中位数
58.1ms,p95106.5ms - 权衡: 写入时去重/聚类会增加
9.0x的中位开销,以确保回忆速度快,并让存储内容随时间推移保持整洁。整合默认关闭。
4. 回忆扩展性:全量扫描与生产混合方案
回忆为何能在记忆增长时保持稳定:生产环境中的回忆不会扫描每个向量,而是先通过 FTS 关键词预筛选缩小候选池,再使用语义 + BM25 + 时间的混合评分重新排序。基准测试的两列都代表真实的异步代码路径,并使用预先计算的向量,以便将检索速度与原始编码开销分离。测试交替执行,以确保缓存条件完全无偏。
| 会话大小($N$) | 全量语义扫描 | 生产混合方案 | 提速倍数 | FTS 候选项 |
|---|---|---|---|---|
| N = 100 | 3.3 ms | 6.6 ms | 0.5x | 85 / 200 |
| N = 500 | 16.3 ms | 11.6 ms | 1.4x | 200 / 200 |
| N = 1,000 | 31.1 ms | 14.7 ms | 2.1x | 200 / 200 |
| N = 2,000 | 63.5 ms | 19.0 ms | 3.3x | 200 / 200 |
| N = 4,000 | 127.2 ms | 29.1 ms | 4.4x | 200 / 200 |
| N = 10,000 | 316.7 ms | 53.8 ms | 5.9x | 200 / 200 |
全量扫描的耗时随 $N$ 大致线性增长,而混合方案的回忆耗时增长慢得多,因此会话规模越大,优势仍会进一步扩大。在非常小的 $N$ 下,预筛选带来的收益不足以抵消开销,因此混合方案反而更慢。
5. LoCoMo 检索准确率
通过 marm_log_entry 导入全部 10 段 LoCoMo 对话(5,882 条记忆),然后将 marm_smart_recall 的前 5 条结果与 1,977 个带有证据标注的问题进行评分。不涉及答案生成模型或大模型评判,因此衡量的是能否检索到正确记忆,而不是 Agent 能否据此正确作答。
| 配置 | 命中任一证据 | 命中全部证据 | 平均证据召回率 |
|---|---|---|---|
| MiniLM 基线 | 37.5% | 29.5% | 未公布 |
| Jina v2 Small(v2.29.0) | 53.0% | 43.4% | 47.6% |
| v2.33.1 至 v2.44.3 | 62.9 - 63.5% | 53.1 - 53.5% | 57.4 - 57.9% |
| v2.44.4(日志通道修复) | 69.1 - 69.6% | 58.2 - 58.6% | 63.0 - 63.5% |
最后一行是受控对比:使用相同构建和数据,唯一变量是日志通道。该通道此前会将整个查询与日志主题和摘要进行子串匹配,因此自然语言问题永远无法匹配,在全部 1,977 个问题上的得分为 0.0%。现在它会对查询进行分词,单独运行时得分达到 53.3%。结果以范围而非单一数值呈现,因为语义通道在不同运行之间会有约半个百分点的波动,因此小于一个百分点的差异并不能说明问题。
多跳类别仍然最弱,得分为 44.9%;单跳证据召回率为 36.6%,而命中任一证据的比率为 66.2%,因此该通道经常只能检索到问题所需证据的一部分。使用 run_eval.py 重现结果。该脚本还会报告排序后语义通道的 MRR 和 nDCG@k;请在服务端设置 MARM_RECALL_REFERENCE_TIME,确保两次运行对相近的结果采用相同排序。
6. 与竞品对比:架构
MARM 面向特定细分场景:为连接 MCP 的编码 Agent 提供本地优先记忆,而不是通用个性化记忆或完整的 Agent 运行时。以下是它在架构上与 AI Agent 记忆领域知名产品的区别:
| MARM | Mem0 | Letta(MemGPT) | Zep / Graphiti | agentmemory | |
|---|---|---|---|---|---|
| 类型 | 记忆引擎,原生支持 MCP | 记忆层 API | 完整的 Agent 运行时 | 时序知识图谱 | 记忆引擎,原生支持 MCP |
| 所需基础设施 | 无需独立数据服务(内嵌 SQLite) | 向量数据库(Qdrant/pgvector) | Postgres + 向量数据库 | Neo4j | 独立的 iii-engine 运行时 |
| 部署方式 | 默认本地优先;共享/远程场景使用 Docker | 云 API 或自托管 | 自托管或云端 | 云端或自托管 | 本地优先 |
| 检索模型 | 混合式:FTS5 BM25 精确匹配通道 + 语义重排 | 向量 + 图 + 键值 | 向量归档存储 + Agent 管理的核心记忆 | 时序知识图谱(事实有效时间范围) | BM25 + 向量 + 图(RRF 融合) |
| 写入采集 | 由连接的 Agent 显式调用工具 | 显式调用 add()(部分集成会自动提取) | Agent 自行编辑其记忆 | 显式 API 调用 | 基于钩子,自动处理(无需显式调用) |
| 代码结构感知 | 内置代码图谱 + 概念图谱,并与记忆融合 | 未内置 | 未内置 | 未内置 | 未内置(需搭配独立项目) |
| 框架绑定 | 无(支持任何 MCP 客户端) | 无 | 高(必须在 Letta 内运行) | 无 | 无(支持任何 MCP 客户端) |
免责声明与准确性: 竞品格局变化迅速。上表反映的是截至 2026 年第三季度的核心架构特征,依据公开文档和 README 编制,并非对每个系统进行内部测试后的结论。如果任何关于其他框架的数据有所变化或表述有误,请提交 issue 或 Pull Request 更新此表。我们非常欢迎同行维护者提出更正。
MCP 客户端 HTTP 和 STDIO 配置
手动 pip 安装
pip install marm-mcp-server
使用以下经验法则选择配置方式
- 本地 HTTP/STDIO = 单机配置最快捷。
- Docker HTTP = 共享/常驻服务(需要密钥)。
- Docker STDIO = 私有容器化本地使用(无需 HTTP 密钥)。
**Swarm / 多 Agent 说明:**写入队列默认启用,通过一个工作进程串行处理记忆写入。对于共享的 HTTP 部署,请使用
marm-memory start --profile swarm(200 RPM)或--profile swarm-max(600 RPM)。--profile trusted会完全禁用速率限制,适用于私有部署。私有的单 Agent / 本地使用场景仍以 STDIO 为佳。完整表格请参见 Swarm 和多 Agent 预设。
本地 pip HTTP
“agent”指 claude、gemini(agy)、grok、qwen 或任何 MCP 客户端。Codex 使用 --url 而非 --transport 来添加 MCP 工具。
pip install marm-mcp-server
marm-memory start
# Stuck on client setup? Open a Q&A thread: https://github.com/Lyellr88/marm-memory/discussions
# most agents use this --transport command
"agent" mcp add --transport http marm-memory http://localhost:8001/mcp
codex mcp add marm-memory --url http://localhost:8001/mcp
默认的 pip / 本地启动无需配置:MARM 会绑定到 localhost,除非通过 SERVER_HOST=0.0.0.0 将其公开,否则无需密钥。
本地 pip STDIO
pip install marm-mcp-server
python -m marm_mcp_server.server_stdio
# most agents use this --transport command
"agent" mcp add --transport stdio marm-memory-stdio marm-mcp-stdio
codex mcp add marm-memory-stdio -- marm-mcp-stdio
如果使用虚拟环境或基于路径的设置,请将 marm-mcp-stdio 替换为 python -m marm_mcp_server.server_stdio。适用于 Claude Code、Cursor、VS Code、Qwen 和 Antigravity。STDIO 仍是单个本地进程,无需端口和 API 密钥,并提供与 HTTP 相同的 16 个工具。
本地 Python Swarm 模式(HTTP 和 STDIO)
多个 Agent 需要共享一个运行中的 MARM 服务时,请使用 HTTP。私有的单 Agent 使用场景仍以 STDIO 为佳,因为每个客户端都拥有自己的本地进程。
# HTTP shared server, normal multi-agent use
marm-memory start --profile swarm
# HTTP shared server, heavier private swarm
marm-memory start --profile swarm-max
# HTTP trusted private lab/server, rate limiting disabled
marm-memory start --profile trusted
# STDIO remains keyless/private and does not use swarm flags
marm-mcp-stdio
Docker HTTP(需要密钥)
Docker HTTP 会将 MARM 暴露为网络服务,因此需要 API 密钥;STDIO 仅在客户端进程本地运行,无需密钥。
如果你通过 pip 安装了 MARM,可以安全地使用产品 CLI 预览或运行相同的设置。它默认使用环回端口,保留 ~/.marm,将生成的密钥存储在 ~/.marm/.env 而非 shell 历史记录中,并且不会替换现有容器。
marm-memory docker command # preview the exact HTTP command
marm-memory docker run # create the managed HTTP container
marm-memory docker stdio-command # print a Docker STDIO client command
marm-memory docker status
marm-memory docker logs --follow
marm-memory docker stop
# Optional: mount repositories read-only for code indexing.
marm-memory docker run --repo /absolute/path/to/repository
# Optional: preview or explicitly write a Compose configuration.
marm-memory docker compose
marm-memory docker compose --yes
HTTP 的 run、command 和 compose 命令接受相同的操作标志:
| 标志 | 用途 |
|---|---|
--data-dir <absolute path> | 挂载到 /home/marm/.marm 的持久化主机目录。默认为 ~/.marm;其中存放记忆、索引、日志和受管理的密钥文件。 |
--env-file <path> | 指定 Docker 环境变量文件。该文件必须已包含 MARM_API_KEY;未使用此标志时,MARM 会使用 ~/.marm/.env,并且仅在 docker run 或 docker compose --yes 需要时才在其中创建密钥。 |
--port <number> | 主机 HTTP 端口。默认值:8001。 |
--expose-network | 将主机端口绑定到 0.0.0.0 而非环回地址。这会主动将服务暴露到网络;请配置防火墙和 TLS 代理。 |
--profile standard|swarm|swarm-max|trusted | 选择与原生 HTTP 启动相同的写入队列和速率限制预设。 |
--rate-limit-rpm <number> | 覆盖所选预设的 HTTP 速率限制。0 表示禁用速率限制。 |
--repo <absolute path> | 可重复使用的只读代码仓库挂载,用于代码索引。MARM 会报告容器内相应的 /workspace/repo-N 路径,以便进行索引。 |
--tag <tag> | 官方镜像标签。默认值:latest。 |
--pull | 创建新的 HTTP 容器前拉取所选镜像。 |
--name <name> | 受管理的容器名称。MARM 不会替换同名的现有容器。 |
--memory <limit> / --cpus <limit> | 可选的 Docker 资源限制。 |
--dry-run | 仅适用于 docker run:打印计划执行的命令,不创建容器或密钥文件。docker command 始终仅供预览。 |
例如:
# Shared local server with a custom data path and two repositories for indexing.
marm-memory docker command \
--profile swarm \
--data-dir /srv/marm-data \
--repo /srv/projects/api \
--repo /srv/projects/web
# Execute the reviewed command, pulling the image first.
marm-memory docker run --profile swarm --data-dir /srv/marm-data --pull
Docker STDIO 与 Docker HTTP 相互独立:marm-memory docker stdio-command 使用 docker run -i --rm,不需要端口或 bearer 密钥,但仍会挂载数据目录,因此短生命周期容器退出后,SQLite 内存数据仍会保留。需要时,可将 --data-dir 和 --tag 与该命令一起使用。没有单独的 docker key 或 docker mount 命令;--env-file 和 --data-dir 会在生成的 HTTP 命令中明确体现这些选项。
marm-memory docker pull 只会下载镜像。marm-memory docker maintenance embeddings migrate 会使用同一个数据挂载,并在受管理的 HTTP 容器运行时拒绝执行。此辅助工具仅适用于通过 pip 安装的 marm-memory 命令;仅使用 Docker 的用户可以使用以下原始命令。
# Step 1: generate key (do not add < > around the key)
docker run --rm lyellr88/marm-mcp-server:latest --generate-key
# Step 2: run server
docker pull lyellr88/marm-mcp-server:latest
docker run -d --name marm-mcp-server \
-p 127.0.0.1:8001:8001 \
-e SERVER_HOST=0.0.0.0 \
-e MARM_API_KEY=your-generated-key \
-v ~/.marm:/home/marm/.marm \
lyellr88/marm-mcp-server:latest
# Step 3: connect client
"agent" mcp add --transport http marm-memory http://localhost:8001/mcp --header "Authorization: Bearer your-generated-key"
# PowerShell: set this before starting/restarting Codex
$env:MARM_API_KEY="your-generated-key"
codex mcp add marm-memory --url http://localhost:8001/mcp --bearer-token-env-var MARM_API_KEY
# Quick auth smoke test
curl -i -H "Authorization: Bearer $env:MARM_API_KEY" http://127.0.0.1:8001/mcp
--bearer-token-env-var 接受环境变量名称,而不是原始密钥。设置 $env:MARM_API_KEY 后,请在同一个 shell 中启动或重启 Codex。对于本地 Docker 冒烟测试,使用 MARM_API_KEY=test 即可,这样可以避免 shell 转义问题;实际部署时请使用生成的密钥。冒烟测试中,GET /mcp 返回 406 Not Acceptable 表示身份验证请求已到达 MCP 端点;返回 401 Unauthorized 则表示密钥缺失或不匹配。
Docker HTTP swarm 模式
# --swarm: write queue on, 200 RPM - recommended for multi-agent shared servers
docker run -d --name marm-mcp-server \
-p 127.0.0.1:8001:8001 \
-e SERVER_HOST=0.0.0.0 \
-e MARM_API_KEY=your-generated-key \
-v ~/.marm:/home/marm/.marm \
lyellr88/marm-mcp-server:latest --swarm
Docker 图索引:挂载仓库
Docker 图工具在容器内运行,因此除非在 docker run 时挂载主机路径,否则无法访问这些路径。
$env:MARM_API_KEY="test"
# The second -v line mounts your repo; adjust the host path to your project
docker run -d --name marm-mcp-server `
-p 127.0.0.1:8001:8001 `
-e SERVER_HOST=0.0.0.0 `
-e MARM_API_KEY=$env:MARM_API_KEY `
-v ~/.marm:/home/marm/.marm `
-v C:\Users\lyell\Desktop\marm-memory:/workspace/marm-memory `
lyellr88/marm-mcp-server:latest
然后请索引容器路径,而不是 Windows 主机路径:
marm_graph_index(repo_path="/workspace/marm-memory")
图工具必须使用容器路径。运行中的容器无法添加挂载;要使用 Docker 图索引,请停止容器,并在重新启动时挂载仓库。
Docker STDIO(无需 HTTP 密钥)
Docker STDIO 包含相同的内置 marm-graph 工具;无需额外的镜像或安装步骤。
docker run --rm -i \
-v ~/.marm:/home/marm/.marm \
--entrypoint python \
lyellr88/marm-mcp-server:latest \
-m marm_mcp_server.server_stdio
支持说明
- Docker HTTP 需要密钥;Docker STDIO 不需要。
- 如果收到
401,请确认密钥匹配,并在环境变量更改后重启客户端。 - 有关密钥设置、轮换和故障排查的完整说明,请参阅:INSTALL-DOCKER.md
连接客户端
启动服务(python -m marm_mcp_server),然后按照下文配置客户端。每个代码块都假设使用默认本地安装(无需密钥)。对于 Docker 或已公开的服务,请添加每个客户端折叠内容中所示的 Authorization: Bearer 标头。
Claude Code
claude mcp add --transport http marm-memory http://localhost:8001/mcp
Claude Code 通过 claude mcp add 支持 HTTP、SSE 和 STDIO;MARM 请使用 HTTP。对于 STDIO:claude mcp add --transport stdio marm-memory-stdio marm-mcp-stdio。
VS Code / GitHub Copilot Agent
在工作区的 .vscode/mcp.json 中添加配置。直接通过 Python 安装时使用 marm-memory-local;使用 Docker 或公开服务/密钥模式时使用 marm-memory-docker。
{
"inputs": [
{
"type": "promptString",
"id": "marm-api-key",
"description": "MARM API Key for Docker or exposed server mode",
"password": true
}
],
"servers": {
"marm-memory-local": {
"type": "http",
"url": "http://localhost:8001/mcp"
},
"marm-memory-docker": {
"type": "http",
"url": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer ${input:marm-api-key}"
}
}
}
}
打开 .vscode/mcp.json,点击所需服务上方的 启动,然后使用 Copilot Agent 或任何使用 VS Code 原生 MCP 注册表的扩展。
Cursor
在工作区的 .cursor/mcp.json 中添加配置。Cursor 使用 mcpServers,而不是 VS Code 的 servers 根字段。
{
"mcpServers": {
"marm-memory-local": {
"type": "http",
"url": "http://localhost:8001/mcp"
},
"marm-memory-docker": {
"type": "http",
"url": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer ${env:MARM_API_KEY}"
}
}
}
}
对于 Docker/密钥模式,请在设置了 MARM_API_KEY 的环境中启动 Cursor。
Codex CLI
Codex 使用 codex mcp add,或使用 ~/.codex/config.toml 中的 TOML 配置(Windows 上为 %USERPROFILE%\.codex\config.toml)。
# Direct Python install - no key needed
codex mcp add marm-memory --url http://localhost:8001/mcp
# Docker or SERVER_HOST=0.0.0.0 - key required (set MARM_API_KEY in your shell first)
codex mcp add marm-memory --url http://localhost:8001/mcp --bearer-token-env-var MARM_API_KEY
[mcp_servers."marm-memory"]
url = "http://localhost:8001/mcp"
enabled = true
bearer_token_env_var = "MARM_API_KEY"
Grok Build
Grok Build(grok)是 xAI 的终端编码 Agent,支持 STDIO 和 HTTP MCP 服务,并读取 ~/.grok/config.toml。MARM 会设置 bearer_token_env_var,因此密钥会保留在环境中,不会写入文件。
# Direct Python install - no key needed
grok mcp add --transport http marm-memory http://localhost:8001/mcp
Docker 或使用 SERVER_HOST=0.0.0.0(需要密钥)时:设置 MARM_API_KEY,然后将以下内容添加到 ~/.grok/config.toml(如果仅用于一个项目,则添加到 .grok/config.toml):
[mcp_servers.marm-memory]
url = "http://localhost:8001/mcp"
bearer_token_env_var = "MARM_API_KEY"
Grok Build 还会从 ~/.claude.json、.cursor/mcp.json 和项目 .mcp.json 读取 MCP 服务,因此如果 Claude Code 或 Cursor 已配置 MARM,它可能已经加载。运行 grok mcp list 查看已加载的服务。
Hermes Agent
Nous Research 的 Hermes Agent(hermes)会从 config.yaml 中的 mcp_servers 读取 MCP 服务:macOS 和 Linux 上为 ~/.hermes/config.yaml,原生 Windows 上为 %LOCALAPPDATA%\hermes\config.yaml,如果设置了 $HERMES_HOME,则为 $HERMES_HOME/config.yaml。它支持 STDIO 和 HTTP,并会展开请求头中的 ${VAR},因此密钥会保留在环境中或 ~/.hermes/.env 中,不会写入文件。
# STDIO - no key needed
hermes mcp add marm-memory --command marm-mcp-stdio
# HTTP, direct Python install - no key needed
hermes mcp add marm-memory --url http://localhost:8001/mcp
Docker 或使用 SERVER_HOST=0.0.0.0(需要密钥)时:设置 MARM_API_KEY,然后将以下内容添加到 config.yaml 的 mcp_servers 下:
mcp_servers:
marm-memory:
url: "http://localhost:8001/mcp"
headers:
Authorization: "Bearer ${MARM_API_KEY}"
在 Hermes 中运行 /reload-mcp,或启动新会话,以加载该服务。
OpenCode
OpenCode(opencode,使用 npm install -g opencode-ai 安装)会从 opencode.json 或 opencode.jsonc 中的 mcp 读取 MCP 服务:所有平台(包括 Windows)上均为 ~/.config/opencode/(Windows 上为 %USERPROFILE%\.config\opencode);如果设置了 $XDG_CONFIG_HOME,则为 $XDG_CONFIG_HOME/opencode/;仅用于一个项目时,则为项目根目录中的 opencode.json。它支持 STDIO(type: local)和 HTTP(type: remote),并会展开请求头中的 {env:VAR},因此密钥会保留在环境中,不会写入文件。远程服务默认会尝试使用 OAuth,因此 MARM 会写入 oauth: false。OpenCode 2 会将服务嵌套在 mcp.servers 下,同时仍能读取下方所示的布局;MARM 会写入文件现有的布局。从控制台连接会将文件重写为纯 JSON,因此 .jsonc 文件中的注释不会保留,原文件会另存为同目录下的 .marm-backup。启动新的 OpenCode 会话以加载服务,并运行 opencode mcp list 进行检查。
STDIO,无需密钥:
{
"mcp": {
"marm-memory": {
"type": "local",
"command": ["marm-mcp-stdio"]
}
}
}
HTTP,直接通过 Python 安装(无需密钥):
{
"mcp": {
"marm-memory": {
"type": "remote",
"url": "http://localhost:8001/mcp",
"oauth": false
}
}
}
Docker 或使用 SERVER_HOST=0.0.0.0(需要密钥)时:设置 MARM_API_KEY,然后添加相同的 HTTP 条目,并附带一个请求头:
{
"mcp": {
"marm-memory": {
"type": "remote",
"url": "http://localhost:8001/mcp",
"oauth": false,
"headers": {
"Authorization": "Bearer {env:MARM_API_KEY}"
}
}
}
}
Devin
Devin CLI(`devin`)和 Devin Desktop 中的 Devin Local Agent(这款 IDE 曾名为 Windsurf)从同一个 `mcp_config.json` 读取 MCP 服务:macOS 和 Linux 上的 `~/.config/devin/mcp_config.json`(如果设置了 `$XDG_CONFIG_HOME`,则为 `$XDG_CONFIG_HOME/devin/mcp_config.json`);Windows 上的 `%APPDATA%\devin\mcp_config.json`。连接一次即可同时用于两者。Devin Desktop 中较早的 Cascade Agent 将 MCP 服务保存在 `~/.codeium` 下自己的文件中,MARM 不会写入该文件。Devin CLI v3000.3 或更高版本会读取这个专用文件,较早的版本会将 `mcpServers` 保存在 `config.json` 中,并在启动时迁移。`devin mcp add` 会保存到一个被 git 忽略的项目文件中,除非你传入 `-s user`。# STDIO - no key needed
devin mcp add -s user marm-memory -- marm-mcp-stdio
# HTTP, direct Python install - no key needed
devin mcp add -s user marm-memory http://localhost:8001/mcp
Docker 或 SERVER_HOST=0.0.0.0(需要密钥):MARM 尚未确认 Devin 是否会展开标头中的环境变量,因此请使用 STDIO,或手动将密钥添加到该文件的 mcpServers 下:
{
"mcpServers": {
"marm-memory": {
"url": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer your-generated-key"
}
}
}
}
Zed
Zed 从用户 settings.json 中的 context_servers 读取 MCP 服务:macOS 和 Linux 上的 ~/.config/zed/settings.json(Linux 上也可以是 $XDG_CONFIG_HOME/zed/settings.json);Windows 上的 %APPDATA%\Zed\settings.json。从命令面板运行 zed: open settings file 即可打开该文件。Zed 没有添加命令,而且 MARM 尚未确认 Zed 是否会展开标头中的环境变量,因此需要密钥的配置请使用 STDIO。从 Console 连接时,只会以文本形式编辑 marm-memory 条目,因此注释和其余设置会保持原样;如果其他内容发生变化,MARM 会恢复该文件。Zed 会在 Settings、AI、MCP Servers 下列出该服务,运行时会显示绿点。通过 Console 安装 MARM 技能后,Zed 自带的 Agent 会从 ~/.agents/skills 读取它。
STDIO,无需密钥:
{
"context_servers": {
"marm-memory": {
"command": "marm-mcp-stdio",
"args": []
}
}
}
HTTP,直接安装 Python(无需密钥):
{
"context_servers": {
"marm-memory": {
"url": "http://localhost:8001/mcp"
}
}
}
Docker 或 SERVER_HOST=0.0.0.0(需要密钥):请使用 STDIO,或手动将密钥粘贴到条目中。Zed 会在 settings.json 中以纯文本形式保存密钥:
{
"context_servers": {
"marm-memory": {
"url": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer your-generated-key"
}
}
}
}
Cline CLI
Cline CLI(cline,通过 npm install -g cline 安装)从 ~/.cline/data/settings/cline_mcp_settings.json 读取 MCP 服务;VS Code 和 JetBrains 中的 Cline 扩展也使用同一个文件(Windows 上位于 %USERPROFILE%\.cline,如果设置了 $CLINE_DATA_DIR,则位于 $CLINE_DATA_DIR/settings)。Cline 自带的 MCP 页面仍写着 ~/.cline/mcp.json,但 CLI 从不读取该文件。HTTP 条目需要 "type": "streamableHttp":如果省略 type,则会选择旧版 SSE 传输。VS Code 和 JetBrains 中的扩展会在其 MCP Servers 面板中显示该服务。Cline 4.x 或更高版本会共享此文件,并在首次启动时将 VS Code 扩展存储中的旧文件迁移到该文件中。较早版本仍会读取各自的文件,因此请先升级 Cline。
# STDIO - no key needed
cline mcp install marm-memory --yes -- marm-mcp-stdio
# HTTP, direct Python install - no key needed
cline mcp install marm-memory --yes --transport http http://localhost:8001/mcp
Docker 或 SERVER_HOST=0.0.0.0(需要密钥):MARM 尚未确认 Cline CLI 是否会展开标头中的环境变量,因此请使用 STDIO,或手动将密钥添加到该文件的 mcpServers 下:
{
"mcpServers": {
"marm-memory": {
"type": "streamableHttp",
"url": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer your-generated-key"
}
}
}
}
Antigravity CLI
Antigravity CLI(agy)于 2026 年 6 月取代 Gemini CLI。它支持 STDIO 和 HTTP MCP 服务。MARM 请使用 HTTP。Antigravity IDE 和 2.0 应用也会读取同一个文件(在 IDE 中,打开“...”→ MCP Servers → Manage MCP Servers)。Antigravity 2.x 或更高版本会读取该文件。较早的 IDE 版本使用 ~/.gemini/antigravity/mcp_config.json,只有在该文件是唯一存在的配置文件时,MARM 才会写入它。
# Direct Python install - no key needed
agy mcp add marm-memory --type http http://localhost:8001/mcp
# Docker or SERVER_HOST=0.0.0.0 - key required
agy mcp add marm-memory --type http http://localhost:8001/mcp --header "Authorization: Bearer your-generated-key"
等效配置文件为 ~/.gemini/config/mcp_config.json(用户范围)或项目中的 .agents/mcp_config.json。Antigravity 读取的是 serverUrl,而不是 url 或 httpUrl,且不会展开此文件中的 ${VAR},因此请粘贴真实密钥:
{
"mcpServers": {
"marm-memory": {
"serverUrl": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer your-generated-key"
}
}
}
}
Qwen Code
# Direct Python install - no key needed
qwen mcp add --transport http marm-memory http://localhost:8001/mcp
# Docker or SERVER_HOST=0.0.0.0 - key required
qwen mcp add --transport http marm-memory http://localhost:8001/mcp --header "Authorization: Bearer your-generated-key"
等效配置文件为 .qwen/settings.json(项目范围)或 ~/.qwen/settings.json(用户范围):
{
"mcpServers": {
"marm-memory": {
"httpUrl": "http://localhost:8001/mcp",
"headers": {
"Authorization": "Bearer your-generated-key"
}
}
}
}
Grok app and API
Grok 应用(grok.com、iOS、Android)支持自定义 MCP 服务:打开 grok.com/connectors,点击 **New Connector**,选择 **Custom**,然后输入你的 MARM URL。xAI API 仅支持通过 Streamable HTTP 或 SSE 使用远程 MCP 工具。两者都运行在 xAI 的基础设施上,因此 localhost 无法使用。请通过 HTTPS(隧道或你自己的域名)公开 MARM,并设置 MARM_API_KEY。尚未通过应用的连接器表单测试 MARM。对于 API,请发送以下工具载荷:
{
"type": "mcp",
"server_url": "https://your-marm-domain.example.com/mcp",
"server_label": "marm-memory",
"authorization": "Bearer your-generated-key"
}
完整的平台操作指南、密钥设置和特定操作系统的说明:Windows · macOS · Linux · Docker/密钥模式 · 其他平台
使用的客户端不在列表中?提交问题并告诉我们;客户端适配器是我们优先考虑的功能请求。
系统要求、数据位置与备份
要求
- Python:3.10 或更高版本
- SQLite3:随 Python 附带(无需单独安装)
- 存储空间:初始设置至少需要约 100MB,随记忆数据库大小而增长
- RAM:至少 512MB(视并发客户端数量和数据库大小而定)
- 操作系统:Windows、macOS、Linux
数据位置
- 位置:
~/.marm/(Linux/macOS)或%USERPROFILE%\.marm\(Windows) - 内容:包含所有记忆、会话和笔记本的 SQLite 数据库;概念图存储在独立的
~/.marm/index/数据库中 - 备份:复制整个
~/.marm/目录以保留所有数据 - 隐私:所有数据都保留在你的设备上,不会同步到云端或存储在外部
- 了解哪些记忆未被使用:每条记忆都会记录召回返回该记忆的次数及时间,Console 会列出冷门记忆(
GET /api/memories/cold?days=30),方便检查较旧且从未被召回的条目。计数不会拖慢或导致召回失败,也不会改变排名 - 存储前会对凭据进行脱敏:在写入记忆、日志、笔记本或审核队列的任何内容,以及发送给本地模型的每条提示词中,API 密钥、令牌、私钥和
NAME=value格式的机密(会读取元数据字段及其名称,带引号的值可以包含空格)都会被替换为[redacted:<kind>];名称和模板会保留。若写入内容中有信息被脱敏,响应会指出这一点,格式为redacted: {count, kinds},但不会包含实际值。若标识符包含凭据(例如会话、项目或平台名称、Session:标记、笔记本条目名称),系统会拒绝该标识符而不是对其脱敏,因为重命名后的标识符将无法再次查找。这项保护针对常见凭据格式,精度较高,但不保证能捕获所有机密;且仅适用于新写入的数据:现有数据不会被扫描或重写
验证安装
使用 MCP 服务健康检查端点可最快进行实时检查:
curl http://localhost:8001/health
预期输出包括服务版本、功能可用性(语义搜索状态)、数据库连接状态和服务健康状态。
完整 MCP 工具套件(16 个工具)
💡 专业提示: 无需手动调用这些工具!只需用自然语言告诉你的 AI Agent 你想做什么:
- “Claude,将此会话记录为‘Project Alpha’,并将此对话添加为‘database design discussion’”
- “将这段代码片段记到你的笔记本里,以便以后使用”
- “搜索我们昨天关于身份验证的讨论内容”
AI Agent 会自动使用相应的工具。希望直接控制的高级用户也可以手动调用工具。
🧠 核心记忆(8 个工具)
| 工具 | 功能 | 关键参数 |
|---|---|---|
marm_smart_recall | 混合记忆检索;如果存在兼容的图,则附加有界的概念/代码图 | query、limit、session_name、search_all、detail=1/2/3、project、platform、exact_mode |
marm_log_entry | 添加结构化会话日志条目;每个条目也会嵌入语义记忆,以便 marm_smart_recall 找到 | entry、session_name、project(可选;默认为服务检测到的项目) |
marm_log_show | 显示所有条目和会话,并支持筛选 | session_name |
marm_delete | 删除日志会话、日志条目或笔记本条目 | type、target、session_name、project、platform |
marm_summary | 可缓存、可直接粘贴的会话摘要,并支持智能截断 | session_name |
marm_notebook | 会话专属的临时记录区,并可将内容提升为永久的图关联文档 | action="add"|"use"|"show"|"status"|"clear"|"save"、name、data、session_name、project、platform |
marm_compaction | 借助 Agent 清理记忆,并保留可供审核的审计记录 | action="status"|"candidates"|"review"|"stage"|"apply"|"discard" |
marm_distill | 将原始对话转化为记忆提案,并对照存储中的内容,将每条提案标记为 new、duplicate 或 near。默认逐字选取句子;启用 use_llm=true 和本地生成后,则改用本地模型编写自包含事实,同时保留其来源的原文片段。提案会暂存以供审核;只有在 review_mode="guardrails" 且操作员开启自动应用开关时,才会在无人值守的情况下应用,并且仅应用通过所有确定性检查的提案 | action="propose"|"review"|"apply"|"discard"、text、session_name、proposal_id、use_llm、review_mode(manual|guardrails) |
🕸️ 代码图(6 个工具)
| 工具 | 功能 | 关键参数 |
|---|---|---|
marm_graph_index | 将代码库编入代码结构图索引、检查状态、列出项目,或开启和关闭自动重新索引 | repo_path、project、action |
marm_code_lookup | 查找符号、文本模式或符号源码;可替代 grep/glob | kind="auto"|"symbol"|"text"|"snippet" |
marm_code_context | 一次调用即可为任务汇集上下文:按个性化 PageRank 排序的符号、从磁盘读取的符号源码,以及记忆中与这些符号相关的记录 | task、project、cwd、budget、detail(0-3;0 使用 MARM_CODE_CONTEXT_DETAIL,即服务默认值)、include_graph(默认为 false)、answer(默认为 false)、analyst_mode(read_only|manual_review|guardrails) |
marm_graph_trace | 追踪函数的调用路径和数据流 | direction、mode |
marm_graph_architecture | 架构概览:模块、节点/边细分和架构 | project |
marm_graph_impact | 代码变更的影响范围:git diff → 受影响的符号 + 风险 | since、base_branch、depth |
🧩 概念图谱(2 个工具)
| 工具 | 功能 | 关键参数 |
|---|---|---|
marm_concept_build | 重建图谱,或为自动索引前存储的记忆建立索引。新记忆会自动建立索引 | session_name、project 或 search_all=True(必须指定一个) |
marm_concept_recall | 显式查询实体、关系和关联的代码符号 | query、depth(1-5)、direction、project、platform |
全部 16 个工具均可通过 HTTP 和 STDIO 使用。在工具接口背后,服务会自动处理生命周期设置、协议刷新、文档索引、日期上下文、摘要缓存维护、写入队列处理、概念索引、代码随代码库变化而重新索引、项目/平台归属以及健康检查;这些操作都不会占用 Agent 的注意力或 token。两个图引擎会在首次使用时按需启动,即使启动失败,也不会阻塞 8 个核心记忆工具。有关这些机制,请参阅架构与内部机制。
使用 MARM:直接交流,不必调用工具
MARM 会在内部处理生命周期相关工作。文档和会话状态会在首次实际调用工具时初始化,随附的文档会索引到 marm_system 记忆命名空间,并跟踪源文件哈希,因此 Agent 可以直接从记忆中回答 MARM 使用相关的问题。
示例工作流:跨 AI 研究项目
通过一个实际工作流展示 MARM 的运作方式。**场景:**你正在使用多个 AI 客户端,为一个新项目研究身份验证模式。
阶段 1:路由会话(Claude)
You: "Claude, create a MARM session called 'auth-research-2025-01'"
Claude calls: marm_log_entry(entry="Session: auth-research")
Result: Session routed to auth-research-[today]. MARM lifecycle/docs initialize automatically.
阶段 2:记录研究内容(Claude)
You: "Summarize OAuth2 vs JWT for API authentication and save it"
Claude calls: marm_log_entry(entry="Research: OAuth2 is token-based with refresh cycles, better for delegated access. JWT is stateless, good for microservices...", session_name="auth-research-2025-01")
Result: Research captured in the active session log and marked for summary-cache refresh
阶段 3:添加可复用参考资料(Claude)
You: "Save a JWT validation code snippet to my notebooks as 'jwt-validation-pattern'"
Claude calls: marm_notebook(action="add", name="jwt-validation-pattern", data="def verify_jwt(token):\n # validation logic...")
Result: Reusable snippet stored for future projects
阶段 4:回忆上下文(Gemini)
You: "Gemini, what authentication approaches did we research? Activate the JWT pattern."
Gemini calls: marm_smart_recall("authentication patterns", search_all=True)
Gemini calls: marm_notebook(action="use", names="jwt-validation-pattern")
Result: Gemini sees previous research + has JWT code available as context
阶段 5:综合与总结(Qwen)
You: "Qwen, pull everything from the auth research and create a summary"
Qwen calls: marm_smart_recall("authentication", session_name="auth-research-2025-01", limit=20)
Qwen calls: marm_summary(session_name="auth-research-2025-01")
Result: Qwen generates an implementation guide from all captured research
阶段 6:结束会话(Claude)
You: "Log final decision - we're using JWT for APIs, and OAuth2 for user auth"
Claude calls: marm_log_entry(entry="DECISION: JWT for API auth, OAuth2 for user flows. Rationale: stateless APIs + delegated user access", session_name="auth-research-2025-01")
Result: Decision logged and searchable by all future AI clients
结果:三个不同的 AI 客户端协作研究了一个主题、分享见解并记录决策,全程无需向每个新 AI 重复介绍项目情况。
高级模式
项目记忆架构与知识库开发
Project Structure:
├── project-name-planning/ # Initial design and requirements
├── project-name-development/ # Implementation details
├── project-name-testing/ # QA and debugging notes
├── project-name-deployment/ # Production deployment
└── project-name-retrospective/ # Lessons learned
知识库循环:
- 记录:使用
marm_log_entry结构化记录会话中的经验 - 整理:为不同知识领域创建主题会话
- 综合:定期使用
marm_summary整合知识 - 应用:将摘要转换为
marm_notebook(action="add", ...)条目
多 AI 协作:每个 AI 在专属会话中发挥各自所长,使用 marm_smart_recall 借鉴彼此的成果,然后通过协作会话整合见解。
专业技巧与最佳实践
- 会话命名:加入 LLM 名称,便于交叉引用
- 策略性记录:聚焦关键决策、解决方案、发现和配置
- 全局搜索:使用
search_all=True搜索所有会话 - 自然语言搜索:「使用 JWT 令牌时的身份验证问题」比「身份验证错误」更有效
- 分层回忆深度:
detail=1返回简短摘要视图(约 200 个字符),detail=2返回更丰富的上下文视图(约 500 个字符),detail=3返回完整记忆内容 - 笔记堆叠:组合多个条目,以支持复杂工作流
- 压缩:让 MARM 提出可压缩项,然后使用
marm_compaction暂存、审查、应用或丢弃摘要 - 会话生命周期:开始 → 工作 → 引用 → 按 MARM 提示审查暂存的压缩内容
两次搜索,两种截然不同的问题,一个工具:
User: "I discussed machine learning algorithms yesterday"
MARM Search: Finds related memories about "ML models", "neural networks", "AI training"
User: "What was the COMPACTION_TRIGGER_COUNT setting?"
MARM Search: Finds the exact config memory even if the rest of the text differs
第一个查询关乎含义,因此 MARM 使用本地向量嵌入对候选结果重新排序——采用 RAG 风格的语义搜索,无需托管向量数据库。第二个查询具有语法特征(配置键),因此 MARM 会自动识别,并将其路由到确定性的精确匹配。这个精确检索通道,正是能在演示中奏效的记忆系统与能回答开发者实际问题的记忆系统之间的区别:配置键、CLI 标志、文件路径、API 名称、错误字符串。纯语义记忆系统恰恰无法处理这些查询。
召回流水线的内部工作原理
MARM 使用过滤→重排混合召回,并提供一个精确检索通道:
- 精确通道(
exact_mode="auto",默认值):检测配置键、CLI 标志、文件路径、API/工具名称、点分命名空间、HTTP 路由、URL 和带引号的命令字符串,并通过确定性的 FTS5 BM25 进行路由,且支持 LIKE 回退。不涉及嵌入,因此结果稳定且精确。 - 过滤→重排通道:自然语言查询首先从 FTS 索引中提取有界候选集(
FTS_CANDIDATE_LIMIT,默认值为 200),然后通过语义嵌入按含义对这些候选项重新排序。当匹配结果接近时,保守的时间权重会适度提升较新的记忆。 - 有界语义回退:当 FTS 覆盖不足或无法使用时,MARM 会回退到有界语义扫描(
RECALL_SCAN_LIMIT)。如果响应中包含recall_scan_truncated=true,说明回退扫描已达到上限;对于更大的存储,请缩小会话/查询范围,或调高环境变量的值。 - 感知分块的评分:较长的记忆(约 180 个字以上)会在内部以重叠的分块行形式生成嵌入,召回时则根据得分最高的匹配分块,将各分块得分合并回一条父记忆。重排通道和回退通道都能感知分块。
这就是为什么随着存储内容增长,召回延迟仍几乎保持不变(参见基准测试):语义重排始终只对有界集合评分,而不是扫描所有嵌入。
**精确召回控制:**通常使用 exact_mode="auto" 即可。查询必须匹配 RECALL_SCAN_LIMIT、--generate-key 或 settings.py 等字面文本时,请使用 exact_mode="exact"。如果具有语法特征的查询仍应按含义进行召回,请使用 exact_mode="semantic"。
记忆类型与分类
- 上下文日志 - 自动分类的对话记忆
- 手动条目 - 明确保存的重要信息
- 笔记本条目 - 可复用的指令和知识
- 会话摘要 - 压缩后的对话历史
MARM 会在写入时自动对内容分类:代码(编程片段和技术讨论)、项目(工作对话和规划)、书籍(文学作品、学习材料、研究)和通用(其他所有内容)。
项目与平台归属
MARM 会在记忆、日志条目和笔记本条目中存储可为空的 project 和 platform 列。项目根据工作目录检测,平台根据连接的客户端(Claude Code、VS Code、Cursor,……)检测;MARM_PROJECT 和 MARM_PLATFORM 可覆盖检测结果。marm_smart_recall(project=..., platform=...) 可限定召回范围,同时不改变默认的无筛选行为,因此一个共享服务可以存储多个项目,且彼此不会相互干扰。
将对话提炼为记忆
存储记忆是一种明确的行为,因此值得保留的内容,都是有人记得要保留的内容。marm_distill 则反其道而行:将一段原始对话交给它,它会从中提议值得长期保存的事实。
marm_distill(action="propose", session_name="release-notes", text="<the conversation so far>")
marm_distill(action="review") → the staged proposals and their verdicts
marm_distill(action="apply", proposal_id="...") → writes that one as a memory
marm_distill(action="discard", proposal_id="...") → rejects it, permanently
每条提议都会与已存储的内容进行比对,并附带一个判定:new、duplicate 或 near。near 是需要人工处理的情况:它与某条已存储的记忆足够相似,可能有关联,但相似度分数无法判断它是在补充这条记忆、与之矛盾,还是仅仅相关。提议会与它相似的记忆并列显示,供审核者决定如何处理。
默认情况下,它只提出建议,不会写入。 propose 会将提议放入审核队列,只有 apply 才会创建记忆;唯一的可选例外是开启操作者的自动应用开关后使用 review_mode="guardrails",此时只有所有确定性检查都通过,才会应用提议。这与 marm_compaction 的设计有意保持一致,原因也相同:相似度分数不足以作为无人值守写入记忆的依据,而仅凭这种分数就写入的任何机制,都会让存储中充斥似是而非的内容,速度远快于积累事实的速度。已丢弃的提议绝不会再次出现,这一点由唯一性约束强制保证,而不是靠约定——再次提供审核者已经否决的内容,会让审核队列变得无人问津。这样一来,对同一段文本重复运行 propose 也不会产生任何操作,因此可以安全地在每次会话结束时调用它。
文本的编写方式。 如果无法连接本地模型,它会筛选本身就像长期事实的句子并将其规范化,而不是编写新句子——因此,分散在三轮对话中的事实,或有所暗示但从未明确说出的内容,都不会成为提议。它会找出明确说出的内容,而非言外之意。这是一个实际的限制,同时也算合理的取舍:MARM 记忆是一条标题,而标题通常就是某人已经写下的句子。若启用本地生成且模型可访问,并指定 (use_llm=true),它就会改为编写事实,同时保留对应的原文片段;提议的 mode 会显示实际采用了哪种方式。请参阅可选的本地生成。
提议尚未审核时,MARM 可以在工具响应中附带审核请求,而不必等用户提出要求。请求会指定一条提议,并要求对其作出决定——apply 或 discard;每个冷却窗口内,全服务器最多附带一条请求,因此一批提议不会导致每个响应都附带请求。设置 MARM_DISTILL_NUDGE=0 可关闭此功能;冷却时间和预算可在配置参考中调整。
知识图谱:代码与概念
MARM 附带两个与记忆存储互补的图谱系统:一个理解代码库结构的代码图谱,以及一个理解已存储记忆主题的概念图谱。为同一项目同时建立索引后,概念实体会与代码符号交叉链接。
代码图谱:代码库索引与代码查询
marm-graph 已集成到两种传输方式中。它只需对代码库建立一次索引,之后 Agent 就能询问代码结构相关的问题,无需反复扫描文件:
Use marm_graph_index to index this repository.
Then use marm_code_context when the question is how something works or what a change would touch.
Use marm_code_lookup when you need a specific symbol, file, or source snippet.
Use marm_graph_trace for call paths, marm_graph_architecture for an overview, and marm_graph_impact for change-risk checks.
推荐的 Agent 工作流:先建立一次索引,然后针对具体任务使用 marm_code_context,在大范围读取文件前使用 marm_code_lookup,在调用方/被调用方或数据流上下文很重要时使用 marm_graph_trace,使用 marm_graph_architecture 了解整体情况,并在高风险重构前使用 marm_graph_impact。一次图谱查询可以取代数十轮 grep/读取操作,节省的 token 就来自这里。
组合上下文:marm_code_context
其余 5 个工具各回答一个问题,Agent 通常会将它们串联起来:搜索名称、追踪调用者、读取每个文件,然后查找记忆中记录的相关内容。marm_code_context 会在服务端执行这条调用链,并将结果作为一个数据包返回:
marm_code_context(task="how does the write queue serialise concurrent writes?")
共 6 个步骤:先通过词法和语义搜索播种,再沿着调用者和被调用者关系扩展,接着用个性化 PageRank 对该子图进行排名,然后从磁盘读取排名靠前的源码,召回与它们关联的记忆和“记忆→符号”链接,最后将结果压缩到字符数上限以内,并把关键内容放在前面。
第三步是普通搜索无法做到的。词法搜索回答的是“哪些符号提到了这些词”,但这并不是 Agent 要问的问题;一个既无人调用、也无人引用的符号,即使同样提到了这些术语,其排名也会低于相关邻域中心的符号。第五步则是纯代码索引在结构上无法做到的——它保留了代码为何如此的原因,而不只是代码写了什么。
detail 用大小换取结构。1(默认值)返回 Markdown 和说明:提供 Agent 所需内容,不重复。2 会添加符号和记忆元数据——名称、文件、行号、分数,以及记录符号是从任务中播种还是沿调用边引入的 provenance——但不会重复 Markdown 中已有的源码。3 还会将源码和记忆文本作为结构化字段添加,这正是渲染器所需的内容,也是 Console 的请求方式。MARM_CODE_CONTEXT_DETAIL 可以一次性更改所有 Agent 的默认值。include_graph 是另一个维度上的独立开关,默认关闭:它会返回用于可视化的排名边列表,其他功能都不会读取该列表。
需要了解的一项限制:追踪会按限定名称解析。如果一个裸名称匹配两个符号,返回结果会是 status: "ambiguous",且不包含任何边,而不是猜测一个结果。这样一来,排名就无内容可处理,最终结果会退化为普通搜索顺序。
answer=true 更进一步,仅根据组合后的上下文用文字回答任务——参见可选本地生成。
仓库建立索引后,MARM 会自动保持索引最新。文件系统监视器会检测保存、提交、分支切换或合并,并在短暂延迟后重新建立索引;它会进行防抖处理,将一连串更改合并为一次处理,而不是每个文件处理一次。定期协调任务会捕获监视器事件遗漏的更改,也是非 git 仓库的唯一触发方式。要改为仅按需建立索引:
marm-mcp-server projects auto off
Agent 也可以通过 marm_graph_index(action="auto_off") 执行相同操作,而 action="auto_status" 会报告正在监视的内容,以及每个项目上次建立索引的时间。此开关会跨重启保留,且优先级高于 GRAPH_AUTO_INDEX 环境变量。
底层引擎是 codebase-memory-mcp(MIT),这是一个零依赖静态二进制程序,通过 tree-sitter 解析 158 种语言,并为主要语言提供 Hybrid LSP 类型解析。它可在数秒内为平均规模的仓库建立索引,并在远低于 1 秒的时间内完成符号搜索和调用追踪。在 MARM 持有的持久连接上,对包含 149,107 个节点的图进行测量:符号搜索耗时 146ms,调用追踪耗时 67ms,完整架构概览耗时 1.23s;只有这项查询超过了 1 秒。MARM 固定使用特定版本,启动时会验证其工具架构,并将上游工具集路由到 6 个专用 MCP 工具,使模型接口保持精简。图后端会在首次使用图工具时延迟启动,因此记忆、日志记录、笔记本和摘要工具仍能快速启动。在 Docker 中,引擎二进制文件已打包进镜像;本地 pip 安装会在首次使用图功能时下载该文件(约 269MB,仅需一次)。
**降级模式:**如果图引擎启动失败(首次下载时没有网络、磁盘已满、架构漂移),或设置了 GRAPH_ENABLED=false,图工具会返回 {"status": "error", "message": "graph backend unavailable"},而其他 10 个工具仍可正常工作。图功能故障绝不会导致记忆功能中断。
概念图谱:记忆的内容
MARM 会从你存储的记忆中提取知识图谱,生成带类型的实体(概念、决策、模式、错误、工具、人员、组织),并通过带类型的关系(修复、实现、依赖于、使用、导致、替换、扩展)将它们连接起来。整个过程会自动进行:存储记忆后,系统会将其加入队列,后台工作进程约 30 秒后将其添加到图谱中。marm_concept_build 仍可用于完整重建或按范围重建。图谱构建完成后,marm_smart_recall 会以 graph_context 附加信息的形式,添加数量受限的相关实体、关系和关联代码,同时不改变主要记忆的排序。你仍可使用 marm_concept_recall 显式探索图谱:
marm_concept_recall(query="write queue") → the entity, its relationships, linked code symbols
marm_concept_recall(query="related to SQLite", depth=3) → multi-hop traversal of everything connected
使用方法:
- 默认自动运行:新记忆无需调用工具即可进入图谱。设置
CONCEPT_AUTO_INDEX=false可恢复为仅手动构建;这会停止工作进程,但仍会记录队列行,因此重新启用后,会处理关闭期间写入的所有内容;CONCEPT_INDEX_DEBOUNCE_SECONDS(30)和CONCEPT_INDEX_BATCH_SIZE(20)用于控制处理速度。 - 同时适用于两种传输方式,安全可靠:记忆数据库中的租约锁可防止一个进程重建时删除图谱表,而另一个进程正在写入这些表。如果图谱正忙,构建会说明情况,而不会发生冲突。
- 失败绝不会影响你的记忆:索引在写入路径之外通过持久化队列运行。提取出错时会重试;多次失败的记忆会连同错误信息一起搁置,而记忆本身始终可以正常存储和召回。
- 关联代码会显示变更状态:每个关联符号都会带有
freshness状态。当代码与 MARM 首次建立关联时的代码不同时,状态为changed,表示相关记忆可能已过时;代码未变时为unchanged;无法安全获取指纹时为unknown。指纹计算会忽略空格、空行和重新缩进,因此它是一种实用的源码变更信号,而非语义等价判断;changed表示代码可能已有变化,不代表记忆有误。只有重新索引完成后才会计算关联项的指纹,并且只有在索引开始后文件未被保存过时才会计算;状态一旦变为changed,便会保持不变。 - 清空积压队列会降低一些召回速度:实体提取受 CPU 限制,因此工作进程处理队列期间,在真实的 768 条记忆语料库上测得的召回中位数会从约 8ms 增至约 16ms。写入不受影响。只有在积压队列清空期间才会出现这种情况;对大多数人来说,这通常只会在升级后重建时发生一次。可通过
scripts/benchmarking/performance/bench_concept_worker.py --from-live复现。 - 为积压内容构建索引:对
session_name、project限定范围,或设置search_all=True的marm_concept_build,会为自动索引功能推出前存储的记忆建立索引,并在升级需要时重建索引。 - 目前已升级两次:在支持平台归属之前,或在以压缩来源取代摘要作为索引行之前构建的图谱,需要运行
marm_concept_build(search_all=True)。完整构建会备份并重置仅包含派生数据的概念数据库;定向构建则不会擅自推断平台归属。 - 旧名称会被标记,而不会被改写:在提取流程停止保留 Markdown 之前构建的图谱,仍可能包含
**apply**之类的名称。Concept Graph Manager 会通过只读检查统计这些名称,并提供 Rebuild graph 选项,该选项会执行常规重置,然后进行全局构建。不会就地重命名任何内容。 - 完整范围,分页读取:构建会读取范围内的每条记忆。
CONCEPT_BUILD_ROW_CAP(默认值为 500)是每页大小;降低该值会让构建读取更多更小的页面,而不是跳过剩余内容。 - 已压缩的会话:原始记忆会建立索引,生成的摘要则不会,因此概念仍会归属于实际表述它们的位置。
- 召回遇到问题时会继续运行:缺失、为空、不兼容或不可用的概念图谱都不会阻止正常记忆召回。响应会单独报告图谱状态。
- 代码交叉关联:当代码图谱已为同一项目建立索引时,与代码符号匹配的概念实体会被关联起来,将“我们做出的决定”与“它在代码中的位置”连接起来。
- 内置提取运行时:spaCy 运行时和英文提取模型随 MARM 一同提供,但只有在首次提取时才会加载;现在,首次提取会在存储第一条记忆后不久自动发生,而不是等到运行构建时才发生。如果安装损坏或不完整,导致无法使用这两者,概念工具会平稳降级,而核心记忆功能仍可使用;运行
marm-memory knowledge status,然后在需要时重新安装 MARM。 - 存储隔离:概念图谱存储在独立的 SQLite 数据库(
~/.marm/index/marm_index.db)中,并使用独立的连接池,因此概念图谱写入绝不会阻塞或损坏生产记忆数据库。 - 控制台图谱:Knowledge Graph 会打开一个紧凑且确定性的连通样本,便于快速导航。需要完整图谱时,选择 Render all N nodes。完整图谱模式会隐藏后台关系线,直到你悬停或选择某个节点;这样无需一次性绘制整张蜘蛛网,也能清晰查看该节点的直接连接。 这弥补了扁平记忆搜索留下的跨会话结构缺口:会话用于组织记忆,而概念图则将它们连接起来,因此即使答案涉及来自 3 个不同 Agent 的 5 个会话,也能回答“写入队列依赖什么?”
架构与内部机制
以上所有功能都基于少数经过深思熟虑的机制运行。本节提供完整概览,让你(或你的 Agent)无需猜测服务在做什么。
存储引擎
- 采用 WAL 模式的 SQLite,数据库位于
~/.marm/marm_memory.db,并使用连接池(5 个连接)。WAL 可在写入期间避免阻塞读取;当多个 Agent 同时检索记忆、而其中一个 Agent 正在写入时,这一点很重要。 - FTS5 全文索引(
memories_fts)作为记忆表上的外部内容表进行维护,为精确通道(BM25)和混合检索的筛选阶段提供支持。 - 分块存储:超过约 180 个词的记忆会被拆分为重叠的 150 个 token 分块(重叠 50 个 token),存储在
memory_chunks表中,每个分块都有自己的嵌入。检索会为分块评分,再将结果归并到父记忆。 - 嵌入由基于 fastembed 的
jinaai/jina-embeddings-v2-small-en编码器生成:参数量为 33M,维度为 512,上下文窗口为 8,192 个 token,并采用 Apache-2.0 许可证。它不需要单独的查询或文档文本前缀。编码器会在首次进行语义处理时延迟加载,并通过锁进行串行化,以防并发编码导致数据损坏。如果编码器不可用,写入仍会成功;在编码器加载前,记忆会以无嵌入的形式存储。语义评分通过单次 NumPy 批处理(矩阵余弦计算)运行,而非使用 Python 循环。 - 概念图拥有独立数据库(
~/.marm/index/marm_index.db)和独立连接池,复用相同的连接池实现,但绝不与记忆存储共享连接。这种隔离是经过刻意设计的:实验性图构建绝不能阻塞生产环境的 WAL。唯一的例外是索引队列;它按设计存放在记忆数据库中,以便记忆及其索引任务能够一同提交;概念图本身仍然是派生且可丢弃的。
写入路径
- 序列化写入队列(默认启用):所有记忆写入都会经过一个内部异步工作器,消除多 Agent 负载下 SQLite 写入器的争用。该队列是通用的;压缩操作也会经过同一工作器,因此无论哪个子系统执行写入,都只有一个写入器。
MAX_QUEUE_SIZE用于限制队列大小。 - 写入时整合(可选,
CONSOLIDATION_ENABLED=1)会在记忆写入前执行两层处理:- 第 1 层,精确去重:在会话内检查规范化内容的 SHA-256 哈希;命中哈希后会与实际内容进行比对再去重,因此发生哈希冲突时会存储新行,而不是悄然合并不同内容。
- 第 2 层,语义合并:余弦相似度超过
CONSOLIDATION_THRESHOLD的近重复项会被合并,而非不断累积。这不会阻塞写入;如果编码器不可用,写入会继续进行,但不执行整合。 - 这一权衡经过测量并已公布:写入成本中位数约为原来的 9 倍(58ms,而非 6.5ms),换来的是更整洁的存储,因为记忆工作负载以读取为主。请参阅上文基准测试的第 3 节。
- 概念索引采用持久化发件箱:写入会在与记忆相同的事务中记录索引任务,因此记忆不可能在没有对应任务的情况下存在。后台工作器会处理该队列并写入概念图谱。写入路径上的任何操作都不必等待提取完成;即使进程在提取期间被终止,也不会丢失任务,因为任务以行的形式存储,而非仅存在于内存中的作业。两种传输方式都会运行工作器,因此它们通过记忆数据库中的租约锁进行协调,而不是使用无法跨传输方式生效的进程内锁。
- 压缩(可选,
COMPACTION_ENABLED=1)是第 3 层:会话中的写入达到一定数量后,后台处理会检测彼此复述的记忆簇:每对记忆都必须达到余弦相似度阈值并共享大部分词语,同时还要满足最小簇大小、最短存续时间和活动会话宽限期要求,以免压缩进行中的工作。随后,MARM 会注入一条有界请求,要求已连接的 Agent 总结每个记忆簇:candidates→stage→review→apply或discard。应用后会保留源记忆 ID,因此压缩后的摘要仍可追溯到原始记忆。暂存的摘要会过期(COMPACTION_STAGING_TTL_HOURS),提醒次数有限且受冷却时间限制,注入内容也有字节预算。该设计清楚界定了 LLM 的作用:MARM 负责检测,Agent 负责总结,并通过可供人工审核的暂存/应用/丢弃流程把关破坏性步骤。
召回路径
详见了解 MARM 记忆:精确通道(FTS5 BM25 + LIKE 回退)、筛选→重排(有界 FTS 候选项 → 批量语义重排 → 时间混合)、带明确截断标志的有界语义回退,以及分块折叠评分。召回深度(detail=1/2/3)决定返回每条记忆的详细程度;每个 MCP 响应都会经过 1MB 响应限制器,由它智能截断内容,而不是破坏协议。
代码图子进程协议
捆绑的图引擎作为受监管的子进程运行,而不是作为导入项:
- 传输:通过子进程的标准输入输出传输以换行符分隔的 JSON-RPC 2.0,并进行经过验证的握手(initialize → 捕获服务端版本 → initialized 通知)。
- 信封处理:扫描响应,选取第一个可解析为 JSON 的内容项,而不假定其位于索引 0,因为上游二进制文件可能会在前面插入更新通知。工具错误通过
result.isError返回,而不是 JSON-RPC 错误,并会转换为简洁的{"status": "error"}字典,同时附上上游提供的修复提示。 - 序列化:使用一个锁保护单个标准输入管道上的每次写入与读取往返;异步调用通过
asyncio.to_thread执行,因此事件循环不会因子进程 IO 而阻塞。 - 崩溃恢复:后台线程会持续读取标准错误,检测子进程 EOF 或崩溃,并在下次调用时自动重新启动进程。超时会被有意地视为非崩溃情况;长时间运行的索引任务可能仍在处理中,终止它会破坏进行中的工作。
- 监管:一个惰性单例监管器会在进程的整个生命周期内管理客户端。首次调用图工具,或在引擎二进制文件已下载时由自动索引工作器触发启动;启动失败不会向 MCP 层抛出异常,并会验证固定版本二进制文件的工具架构,以便在启动时而非调用中途发现上游变更。
- 自动重新索引通过文件系统监视,并结合 git 内容签名和协调回退机制:捆绑的监视器会在文件保存、提交、分支切换或合并时唤醒工作器;匹配的事件会经过防抖处理,使一连串事件只触发一次重新索引。对于 git 仓库,触发条件会通过计算与
HEAD的差异哈希,以及未被忽略的未跟踪文件指纹来确认;此计算在引擎外进行,因此空闲检查不会占用引擎锁,并且能够区分同一个已修改文件的两次不同编辑,而不是将它们误认为相同内容。定期协调检查会捕获遗漏的监视器事件,覆盖无法监视的文件系统,并且是非 git 仓库目录的唯一触发方式。运行 git 时会禁用core.fsmonitor并清理环境,因为该设置会指定一个程序,而 git 否则可能会从受监视的仓库中执行该程序。 - 所有存储变更都经过同一个闸门:所有三个接口上的手动索引、自动索引工作器和项目删除,都会通过内存数据库中的同一条带租约记录。HTTP 和 STDIO 是两个独立进程,各自拥有一个引擎子进程,但共用一个引擎存储,因此进程内锁无法覆盖它们。租约会在引擎调用实际返回时释放,而不是在调用方停止等待时释放:已取消的请求无法在引擎仍在写入存储时,就将存储交给另一个进程。
可选的本地生成
MARM 从未内置生成模型。概念提取使用 spaCy,搜索使用句子编码器,两者都在本地运行,因此 marm_distill 会选择句子,而不是撰写句子。这不会改变默认行为——只有在操作员启用生成功能(切换 Console 中的 System → Controls 开关,或设置 MARM_LLM_ENABLED=1)并且本地服务可访问时,才会使用生成。仅仅发现正在运行的模型永远不够,没有模型时一切照常运行。
有两项功能会使用它,但都只在每次调用时明确请求后才会启用,而且两者都会降级处理,而不是失败:
marm_distill(use_llm=true)会撰写独立完整的事实,而不是提取句子,并保留每条事实所依据的原文片段。提案的mode会说明实际发生了什么:generated表示模型已作答,selected表示模型未作答。marm_code_context(answer=true)会完成整个流程,用文字回答任务,且仅以其刚刚整理出的上下文为依据——因此,排序决定了答案可以涉及什么。Console 会通过内部路由流式传输答案,因此在其余内容仍在生成时,文本就会逐步显示。该流就是唯一一次请求:它的第一个事件context就是整理结果(marm_code_context返回的负载,或其no_project/unavailable状态),答案也恰好基于该整理结果生成,因此 Console 显示的内容与答案所依据的内容来自同一次检索。每次调用都受操作员配置文件的限制:如果模型未能在令牌上限或时间限制内完成回复,或流连接中断,都不会重试并放宽限制;done会携带truncated,截断的答案永远不会通过验证。
强制限制为回环地址,而非仅作说明。 如果主机不是回环地址,系统会直接拒绝,而不是发出警告,因为配置错误将其指向托管端点,会在没有任何其他迹象的情况下,悄悄把对话记录和源代码发送出机器。可使用覆盖项,但必须完整声明意图(MARM_LLM_ALLOW_REMOTE=i-understand-this-leaves-my-machine),拒绝信息中也会指出该设置项。
所有失败都会返回 None,绝不会抛出异常。 模型未就绪、GPU 繁忙、容器已停止或回复格式错误,都会降级为“本次没有模型答案”。调用方会根据 None 分支处理,而不是捕获异常。内存工具不能因为无关的容器被重启就停止工作。
本地证据分析器
marm_code_context(answer=true) 是一个有界的只读分析器。MARM 负责检索;本地模型只读取 MARM 检索到的内容;确定性代码会在返回任何结果前对其进行判断。模型不会搜索、获取更多上下文、写入记忆或调用工具。
-
一份证据包。 组合内容会固化为一个证据包,包含可引用的句柄(符号使用
S1…,记忆使用M1…)和内容哈希packet_id。无论调用方请求的budget是多少,配置文件都会限制证据包的内容;answer_packet会报告证据包的大小及限制导致的遗漏。 -
由操作员选择的配置文件。
general会像以前一样生成一条自由格式答案。small会通过 5 次调用执行 5 项范围明确的操作:摘要、带有逐字quote的有依据事实、调用和记忆关系、缺失的证据,以及低风险的后续步骤(读取、比较、验证或询问)。large会在一次调用中执行相同的 5 项操作。每项操作都会返回固定架构的 JSON;在支持的情况下,会向服务请求json_schema格式,并且无论是否支持都会进行验证;不符合要求的条目会被丢弃并计数,绝不会修补。可在 System > Controls 中设置配置文件,也可使用MARM_ANALYST_PROFILE设置,绝不会根据模型推断。 -
硬性限制。 每次调用都会请求配置文件所设的上限,以及答案令牌数和任何推理额度,并且绝不会以更宽松的限制重试。超过时间限制后不会开始任何调用,也不会有调用超时继续运行。
answer_model_info会报告上限、调用次数、耗时以及运行是否提前停止;被截断的答案绝不会经过验证。 -
逐项验证每条结果。 如果被引用的句柄不在证据包中,就会被拒绝。只有当事实的引文在其引用的条目中逐字出现时,该事实才算有依据;只有当证据包中存在对应边时,调用关系才算成立;只有当记忆绑定到符号或提及该符号时,记忆关系才算成立;只有当每项声明所断言的内容都出现在其引用的证据中时,该声明才算成立。若一项声明没有任何可供检查并判定失败的内容,就不算通过验证。只有每项实质性结果都通过验证且所有操作均已完成,答案才标记为
verified;否则标记为uncertain,并在answer_status中报告为ok、unverified或rejected。answer_items会携带每项结果、其状态以及支持它的依据。 -
代码与记忆不一致。 如果某条记忆描述的调用与证据包图谱相矛盾,或图谱未显示该调用,就会将其列入
answer_disagreements,而不询问模型。 -
三种模式(
analyst_mode),每种模式只负责一件事。默认模式read_only仅根据证据包作答,不做其他任何事:不检索、不暂存、不写入。manual_review会将已验证答案中的结果作为marm_distill提案暂存,并标记origin: "analyst",供人员应用或丢弃。guardrails会以相同方式暂存这些结果,并允许 MARM 机械地应用可证明的结果,但仅限操作员已开启自动应用时。模型绝不会应用任何内容,审核过程也绝不会向模型询问任何内容:只有验证结果为verified的答案才会被暂存,因此不确定的答案无法通过重新表述变为已验证。 仅对可通过机械方式验证的声明自动应用。 每项暂存结果都会标明其声明类型。MARM 会应用call_edge(由 MARM 根据数据包调用边写入)、identifier_in_range(MARM 自行说明所引用符号的定义位置)、quoted_span或verbatim_statement(引用来源或记忆中的完整句子或整行,绝不使用片段,因为片段可能会漏掉对其起限定作用的否定词),并在作出决定前重新检查类型是否与存储的类型一致。其他任何内容,包括引用再充分的转述,都会返回review_required。其他检查包括:操作员已开启自动应用开关;作出决定时会重新解析提案,且其状态仍为new;内容为一行,长度为 12 到 300 个字符;内容中没有任何看起来像凭据的内容,无论是带标签的(api_key=),还是采用已知令牌格式的(提供商密钥、Bearer 值、JWT、带密码的 URL)。对marm_distill设置review_mode="guardrails"后,系统会对提炼出的提案作出相同决定;这类提案的片段必须逐字出现在源文本中。每项决定,无论是否应用,都会在任何写入发生前记录到提案中;如果之后写入未能完成,状态会变为apply_failed,并附上错误信息。已应用的提案会报告为applied,不再计入待审核项。
JSON 响应和流共用同一套实现,并返回相同的验证结果。读者关闭流后,生成也会停止。scripts/eval-analyst.py 会在任意配置下,使用运行中的本地模型运行 tests/fixtures/analyst_eval.json 中的评估矩阵。
这就是 marm_code_context(answer=true) 的行为约定;如果模型不可达或未返回任何内容,它会返回 "answer": null。Console 的流式路由无法使用它,因为生成失败时流已经开始:该路由会发出一个 SSE error 事件,其 JSON data 中包含 message;如果完全没有可用模型,还会包含 hint。两种情况的结果都一样——排名后的上下文仍然保留,只是缺少答案——但读取流的客户端会根据事件分支,而不是根据 null 值分支。
端点按以下顺序解析:在 Console 中保存的运行时选项,然后是 MARM_LLM_URL,接着是自动发现,最后是内置默认值。自动发现会扫描常见本地运行时使用的环回地址端口,并报告实际“作出响应”的服务,而不是通常使用该端口的服务,因此 MARM 无需重启或更改配置,就会跟随当前实际提供服务的服务器。显式指定的端点始终优先,因此,如果你设置的地址不可用,系统会如实显示该地址不可用,而不会悄悄替换它。
Console 的 System → Controls 选项卡会显示所有这些信息:哪个服务作出了响应以及如何选定该服务、它提供的模型、在常见本地目录中找到的模型文件,以及一个可将选项固定为持久运行时标志的选择器。
安全与速率限制
- 双模式身份验证:环回地址(
127.0.0.1)上无需密钥;服务器一旦暴露到网络(SERVER_HOST=0.0.0.0、Docker),就必须设置MARM_API_KEY(Bearer)。--generate-key可生成密钥。默认安全,在本地使用时无需任何设置。 - 基于 IP 的速率限制,采用滑动窗口和临时封禁,可通过 CLI 预设进行调整,无需在复杂配置中摸索(见下表)。
- 本地优先:所有内容都存放在
~/.marm/下;不进行云同步、遥测或外部存储。 - 平滑关闭:SIGTERM/SIGINT 处理程序会排空并干净地关闭连接池;内部事件系统会运行自动化回调,并对每个回调单独隔离错误并设置超时,避免某个异常钩子卡住服务器。
Swarm 和多 Agent 预设
| 标志 | 速率限制 | 写入队列 | 适用场景 |
|---|---|---|---|
| (none) | 80 RPM | enabled | 常规本地使用和小型的 3-5 个 Agent 部署 |
--swarm | 200 RPM | enabled | 共享 HTTP 服务,具体取决于写入方式,约支持 15-30 个 Agent |
--swarm-max | 600 RPM | enabled | 更高负载的本地/私有 swarm,具体取决于写入方式,约支持 50-100 个 Agent |
--trusted | disabled | enabled | 仅限私有/可信部署 |
--rate-limit-rpm N | N RPM | unchanged | 自定义覆盖值;0 表示禁用限制 |
无论使用哪种预设,写入队列都会串行处理内存写入;swarm 标志则在此基础上调整 HTTP 速率限制。队列负责控制写入顺序;整合和压缩属于独立的内存维护层。此技术栈(WAL + 连接池 + 单个串行写入器 + RPM 预设)有意限定在“SQLite、多 Agent、单台机器”的场景;分布式多节点内存不在当前设计的范围内。
自动维护文档
启动时,打包的文档会被索引到 marm_system 内存命名空间中,并每 50 次工具调用刷新一次。系统会跟踪源文件哈希,因此不会重新处理未更改的文档,而更改或删除的条目则会重新索引。连接的 Agent 可以通过 marm_smart_recall 回答 MARM 使用问题,无需你把文档粘贴给它们。
配置参考
环境变量(括号内为默认值)
| 变量 | 默认值 | 控制内容 | | ---------- | --------- | ------------------ | | `SERVER_HOST` | `127.0.0.1` | 绑定地址;`0.0.0.0` 会公开服务,并使 `MARM_API_KEY` 成为必填项 | | `SERVER_PORT` | `8001` | HTTP 端口 | | `MARM_API_KEY` | *(空)* | 用于网络公开部署的 Bearer 密钥 | | `MARM_DB_PATH` | `~/.marm/marm_memory.db` | 记忆数据库位置 | | `MARM_CONCEPT_DB_PATH` | `~/.marm/index/marm_index.db` | 概念图数据库位置 | | `MARM_PROJECT` / `MARM_PLATFORM` | *(自动检测)* | 覆盖项目/平台归属信息 | | `MARM_RATE_LIMIT_RPM` | `80` | 每个 IP 每分钟的请求数(预设值会覆盖此设置) | | `WRITE_QUEUE_ENABLED` | `1` | 通过单个工作线程串行处理写入 | | `FTS_CANDIDATE_LIMIT` | `200` | 语义重排前获取的 BM25 候选数;对于关键词重合度较低的存储,可调高此值;若要将结果收紧到关键词匹配度最高的内容,可调低此值 | | `RECALL_SCAN_LIMIT` | `10000` | 语义回退扫描的上限;响应中的 `recall_scan_truncated=true` 表示已达到该上限 | | `FTS_QUERY_MODE` | `or_nostop` | 语义召回构建关键词查询的方式:`or_nostop` 会忽略填充词,然后匹配任意剩余词项;`or` 会匹配任意词项;`and` 要求匹配每个词项(2.31.0 之前的行为)。精确/词法通道始终要求匹配每个词项。 | | `FTS_EXTRA_STOPWORDS` | *(空)* | 构建关键词查询时要忽略的额外词语,以逗号分隔;适用于在存储中非常常见、无法提供有效信号的词语 | | `HYBRID_SEARCH_TEXT_WEIGHT` | `0.05` | 关键词分数对排名的影响程度。根据基准测试扫描结果设置;准确率在 `0.04`-`0.08` 之间达到峰值,超过 `0.10` 后会急剧下降。设为 `0.0` 时,关键词匹配会缩小纳入考虑的记忆范围,但不会重新排序。 | | `FTS_LONE_HIT_SCORE` | `1.0` | 只有一条记忆匹配,或所有匹配结果得分相同时使用的关键词分数。如果在小型存储中不应将单个关键词匹配视为完美匹配,可调低此值。 | | `SEMANTIC_SEARCH_ENABLED` | `1` | 设为 `0` 可在不使用嵌入模型的情况下运行:不会加载模型,也不会写入嵌入向量,召回将回退到关键词匹配。适用于内存有限的主机,或用于查看模型不可用时的召回表现。`marm-memory doctor` 会报告此功能是否关闭。 | | `TEMPORAL_WEIGHT` / `TEMPORAL_HALF_LIFE_DAYS` | `0.1` / `30` | 时间新近度加权的强度和衰减 | | `MARM_RECALL_REFERENCE_TIME` | 未设置 | 用于计算新近度的 ISO 8601 时间点,取代当前时间,以便基准测试运行结果可复现 | | `CONSOLIDATION_ENABLED` | `0` | 写入时去重并进行语义合并 | | `CONSOLIDATION_THRESHOLD` | `0.92` | 合并近似重复项所需的余弦相似度。比较依据仅为含义相似度,而非混合排名分数 | | `COMPACTION_ENABLED` | `0` | 后台集群检测和 Agent 辅助压缩 | | `COMPACTION_TRIGGER_COUNT` | `5` | 每个会话在执行一次压缩前的写入次数。调度器间隔到期时也会执行维护扫描,因此即使某个会话不再有写入,只要其中的记忆超过 `COMPACTION_MIN_AGE_HOURS`,仍会被扫描一次 | | `COMPACTION_SIMILARITY_THRESHOLD` / `COMPACTION_MIN_CLUSTER_SIZE` / `COMPACTION_MIN_AGE_HOURS` | `0.88` / `3` / `24` | 集群检测门槛 | | `COMPACTION_MAX_CLUSTER_SIZE` | `8` | 一次压缩最多可折叠到摘要中的记忆数。某个集群一旦被丢弃,之后即使规模增大也不会再次提交处理 | | `COMPACTION_MIN_CONTAINMENT` | `0.9` | 较短文本的 Unicode casefold 后词语集合中,被另一条记忆重复的比例(按字符长度选择较短文本;长度相同时选择词元集合较大的文本)。此阈值仅约束较短的一侧,不约束较长记忆中的额外内容。保留所有短词;若词元集合为空或无法识别,则安全地拒绝聚类:当无法验证改述时,以牺牲召回率换取安全性。数值差异和已知极性标记(如 not/no、缩写 n't/n’t、on/off、up/down)会独立阻止聚类。设为 `0` 即明确选择仅依据相似度进行聚类。这种词法启发式方法无法证明语义等价;CJK 文本使用完整 Unicode 字符串而不进行词典分词,因此可能会保守地漏掉改述。 | | `COMPACTION_STAGING_TTL_HOURS` | `168` | 暂存摘要过期前的等待时长 | | `MARM_DISTILL_NUDGE` | `1` | MARM 是否可以在工具响应中附加一条针对待处理提案的审核请求,要求 Agent `apply` 或 `discard` 该提案。设为 `0` 可始终不发出请求 | | `MARM_DISTILL_MAX_NUDGES` | `3` | 对单个提案发出审核请求的次数上限;达到上限后,提案会标记为 `nudge_exhausted`,不再提交 | | `MARM_DISTILL_NUDGE_COOLDOWN` | `900` | 两次审核请求之间的秒数。此设置适用于整个服务,而非单个提案或会话 | | `MARM_DISTILL_INJECTION_BYTES` | `1536` | 注入 Agent 上下文的提醒所占用的字节预算 | | `MARM_LLM_ENABLED` | 未设置(关闭) | 开启可选的本地生成。从 Console 保存的选项会覆盖此设置,无论方向为何。检测到正在运行的模型不会自动开启生成 | | `MARM_LLM_URL` | `http://127.0.0.1:18080` | 用于可选生成的本地 OpenAI 兼容端点。指定的地址优先于自动发现,因此若该地址不可用,系统会明确报告,而不会静默替换 | | `MARM_LLM_ALLOW_REMOTE` | 未设置 | 必须是确切字符串 `i-understand-this-leaves-my-machine` 才允许使用非环回端点。其他任何值,包括 `1` 或 `true`,都会被拒绝 | | `MARM_LLM_TIMEOUT` | `120` | 等待生成结果的秒数。此值刻意设置得较宽裕:共享 GPU 上响应缓慢是正常情况,不代表出现故障 | | `MARM_LLM_MAX_RETRY_TOKENS` | `8192` | 当模型耗尽全部预算却未生成内容时,单次扩大重试的上限(分析器不会使用此设置,因为它的上限是硬限制) | | `MARM_ANALYST_PROFILE` | `general` | 分析器配置:`general`、`small` 或 `large`。在 System > Controls 中保存的选项优先 | | `MARM_CODE_CONTEXT_ANSWER_TOKENS` | `900` | `general` 配置每次调用的回答词元数,范围为 64 至 8192。结构化配置的大小由其架构决定 | | `MARM_ANALYST_TIME_BUDGET` | 配置(`90`/`60`/`180`) | 分析器回答可花费的秒数,范围为 5 至 600。超出此时间后不会启动新的模型调用 | | `MARM_ANALYST_REASONING_TOKENS` | 配置(`0`/`0`/`8192`) | 推理模型回答前每次调用可额外使用的词元数,最多 32768。此值会加到请求上限中的回答词元数上 | | `MARM_ANALYST_AUTO_APPLY` | 未设置(关闭) | 防护栏自动应用开关的默认值:只有确切值 `1` 才会开启,其他任何值(包括 `true`)都会让所有提案保持待处理状态。在 System > Controls(Automated Guardrails)中保存的选项优先,因此容器无法重新启用已保存的关闭状态;选择“Use environment”可恢复使用此变量。即使开启,也只会应用能够通过机械方式验证的声明 | | `GRAPH_ENABLED` | `true` | 6 个代码图工具的总开关 | | `GRAPH_AUTO_INDEX` | `true` | 自动重新索引已加入代码图的代码仓库。从 `projects auto off` 或 `marm_graph_index(action="auto_off")` 保存的开关会覆盖此设置,因此在此处设置的值无法重新启用用户已关闭的功能 | | `GRAPH_AUTO_INDEX_DEBOUNCE_SECONDS` | `2` | 监视器事件后等待的静默时长,之后再评估代码仓库;这样一连串保存操作只会触发一次重新索引。最小值为 0.5 | | `GRAPH_AUTO_INDEX_RECONCILE_SECONDS` | `300` | 用于捕捉遗漏的监视器事件、覆盖无法监视的文件系统,以及作为非 git 目录唯一触发条件的回退扫描。最小值为 60。此设置取代已弃用的 `GRAPH_AUTO_INDEX_FULL_INTERVAL`;若未设置此项,旧值会自动沿用。`GRAPH_AUTO_INDEX_INTERVAL`(旧的固定轮询设置)已弃用,除发出警告外不再读取 | | `GRAPH_AUTO_INDEX_MODE` | `moderate` | 自动重新索引的深度:`full`、`moderate` 或 `fast`。其他值会触发警告并回退 | | `MARM_CODE_CONTEXT_DETAIL` | `1` | 调用方传入 `0` 时,`marm_code_context` 使用的默认 `detail`。限制在 1-3 之间。提高此值适用于会自行渲染结构化部分的客户端;保持为 `1` 时,响应仅包含 Markdown 块,这是大多数 Agent 会读取的内容 | | `GRAPH_AUTO_INDEX_LEASE_SECONDS` | `120` | 在无人续期时,索引门仍保持占用的时长。运行中的索引会自行续期,因此此值限定的是*被终止*的进程阻塞索引的时长,而非索引本身的耗时 | | `GRAPH_AUTO_INDEX_PROJECT_TTL` | `300` | 信任已监视项目列表的时长,超过后会从引擎重新读取 | | `CONCEPT_BUILD_ROW_CAP` | `500` | 构建概念图时每页读取的记忆行数。这不是构建的上限:无论如何都会读取范围内的每条记忆 | | `CONCEPT_AUTO_INDEX` | `true` | 自动为新记忆建立概念索引。设为 `false`、`0`、`no` 或 `off` 会停止工作线程,并改为手动构建。无论此设置为何,写入仍会记录队列行 | | `CONCEPT_INDEX_DEBOUNCE_SECONDS` | `30` | 写入后到索引开始前的静默时长,因此一连串写入会合并为一次处理 | | `CONCEPT_INDEX_BATCH_SIZE` | `20` | 每批索引的记忆数,上限为 500。调低此值不会减少资源争用;实测结果略差 | | `CONCEPT_INDEX_BATCH_PAUSE_MS` | `250` | 清理积压时各批次之间的暂停时间。可将索引期间最坏情况下的召回耗时从 ~270ms 降至 ~80ms,代价是积压清理时间延长约 18%。设为 `0` 可禁用 | | `CONCEPT_INDEX_LEASE_SECONDS` | `300` | 在无人续期时,已认领索引任务仍保持占用的时长。正在进行的任务会自行续期,因此此值限定的是*被终止*的进程占用任务的时长,而非单批任务可能耗费的时间。重新认领的任务不会消耗尝试次数 | | `CONCEPT_INDEX_MAX_ATTEMPTS` | `3` | 记忆失败多少次后会连同错误一起暂存,而不再重试 | 提取式回退采用比聚类阈值更严格的独立规则: 只有逐字一致、按词边界对齐的包含副本,且保留数值事实并匹配已知极性标记时,才可以用较完整的副本替换。其他陈述(包括相互矛盾的历史更正)仍会单独保留。 质心相似度用于为有界的 `top_n` 选择排序;得分相同时,优先选择存储时间戳较新的内容(缺失或无效的时间戳排在最旧)。较新的短副本绝不会抹去较旧的完整副本中的额外事实。此预算并不保证保留规模任意大的候选内容中的每一项事实。极性词汇表采用保守的英语/俄语检查,并非通用的多语言否定或语义解析器;应用摘要前仍需人工审核。故障排除
升级嵌入
Jina v2 Small 默认使用 512 维嵌入;旧版 all-MiniLM-L6-v2 数据为 384 维,必须重新嵌入。停止所有 MARM HTTP 和 STDIO 进程,然后运行:
marm-memory maintenance embeddings migrate
它会重新嵌入记忆、分块和所有现有概念图向量(笔记本临时条目不再包含嵌入),报告进度,验证两个数据库,并可在中断后恢复。若 HTTP 服务仍在运行,它会拒绝启动;无法可靠检测 STDIO 进程,必须手动停止。
修复分块记忆
超过 500 个单词的记忆也会以较小的分块形式存储。不同版本的分块大小有所变化,上述迁移会重新嵌入分块,但不会重新拆分,因此较旧的分块仍保留过时的边界。停止所有 MARM 进程,然后运行:
marm-memory maintenance chunks rechunk
它会重新拆分过时的分块,补齐因写入中断而丢失的分块,并删除现已低于阈值的记忆所对应的分块。已正确的记忆会直接跳过,不会加载编码器,因此重复运行不会产生额外开销。与上述操作一样,它会检查服务是否仍在运行;此外,如果存储的向量与配置的嵌入模型不匹配,它也会拒绝运行:这种情况下请先迁移。即使不执行此操作,召回功能仍可使用,只是处理长记忆时准确度较低。
服务问题
服务无法启动
- 检查 Python 版本:
python --version(必须为 3.10+) - 确认端口 8001 未被占用:
lsof -i :8001(macOS/Linux)或netstat -ano | findstr :8001(Windows) - 检查主目录中是否存在权限错误(
~/.marm/必须可读写) - 查看特定平台的故障排除指南:INSTALL-DOCKER.md、INSTALL-WINDOWS.md、INSTALL-MACOS.md、INSTALL-LINUX.md
STDIO 连接失败
- pip install 后,确认
marm-mcp-stdio位于 PATH 中:marm-mcp-stdio --help - 或使用:
python -m marm_mcp_server.server_stdio - 查阅 AI 客户端文档,了解 STDIO 传输要求
- 尝试直接执行以查看错误消息:
python -m marm_mcp_server.server_stdio
连接与集成
AI 客户端无法连接到 MARM
- 使用
curl http://localhost:8001/health确认服务正在运行 - 检查防火墙是否阻止了端口 8001
- 对于 STDIO:使用
marm-mcp-stdio(控制台脚本)或python -m marm_mcp_server.server_stdio - 重启服务和 AI 客户端
AI 客户端中未显示工具
- 使用
curl http://localhost:8001/health确认 HTTP 模式 - 检查服务日志中是否存在初始化错误
- 断开并重新连接 AI 客户端,以刷新工具列表
- HTTP 和 STDIO 均提供 16 个工具:8 个核心记忆/日志/笔记本/压缩工具、6 个捆绑的代码图工具,以及 2 个概念图工具
图工具返回 graph backend unavailable
- 确认
GRAPH_ENABLED未设为false(会同时影响 HTTP 和 STDIO;图工具在两种传输方式下功能完全一致) - 首次使用图功能时,可能需要更长时间,因为固定版本的 codebase-memory 引擎需要启动或在本地下载
- 在 Docker 中,图引擎二进制文件已打包进映像;本地 pip 安装可能会在首次使用图功能时下载该文件
- 即使图引擎启动失败,核心记忆工具仍会继续工作
概念工具返回 entities_extracted: 0
- 首先确认指定范围的概念构建确实包含可提取实体的记忆。
- 运行
marm-memory knowledge status;如果提示缺少运行时或模型,请通过python -m pip install -U --force-reinstall marm-mcp-server修复安装。
新记忆未显示在图中
- 运行
marm-memory knowledge status。index_queue.pending表示正在等待的记忆数量;index_queue.parked表示放弃处理的记忆数量。auto_index: false表示索引已关闭。 - 等待防抖间隔(默认为 30 秒)及提取所需时间。一批写入会作为一次任务索引,而不是每条记忆分别索引。
- 检查
CONCEPT_AUTO_INDEX是否未设为false、0、no或off。 - 等待重建的图不会被写入索引。如果 Console 或
marm-memory knowledge status显示rebuild_required,请运行一次marm_concept_build(search_all=True);之后会处理排队中的记忆。 - 自动索引仅涵盖升级后写入的记忆。运行一次构建即可纳入所有更早的记忆。
- 提取失败三次的记忆会被搁置,不会无限重试。失败原因会与任务一并记录。
代码变更未显示在代码图中
- 运行
marm-memory projects auto status。enabled: false表示自动重新索引已关闭;source: override表示将其关闭的是已保存的开关,而非环境设置。 - 必须先为代码库建立一次索引,之后才会监视它。
marm-memory projects list会显示已纳入的项目。 - 等待防抖时间(默认为 2 秒)及索引所需时间。如果此后仍无变化,默认每 5 分钟运行一次的协调检查会作为后备机制。
- 从 Console 删除的项目会被有意保持为已停用状态,避免过时的监视列表将其重新创建。显式为其建立索引会重新纳入该项目。
- 自动索引需要图引擎;在下载引擎二进制文件前,图引擎会保持休眠状态。调用任何图工具都会下载一次。
索引返回 index_in_progress
- 另一个 MARM 进程持有索引闸门,通常是另一种传输方式的索引工作线程或 Console 索引任务。删除项目时也会返回相同结果,因为在索引期间删除会被索引操作撤销。稍等片刻后重试。
构建返回 build_in_progress
- 另一个 MARM 进程正在写入图,通常是另一种传输方式的索引工作线程。除完整重建外,构建通常耗时很短;稍等片刻后重试。
构建返回 lock_lost
- 构建停滞时间过长,导致另一个进程接管了图,因此它中途停止,以免与另一个进程同时写入。通常是机器休眠或调试器暂停所致。停止前已索引的内容会保留;重新运行构建即可完成剩余部分。
记忆与数据问题
记忆未保存
- 确认
~/.marm/目录存在且具有写入权限 - 检查可用磁盘空间
- 使用简单记忆进行测试:让 AI 保存一行内容,然后通过
marm_log_show检查 - 对于 HTTP 模式,使用
curl http://localhost:8001/health确认服务健康状态
搜索未返回结果
- 确认记忆确实存在:使用
marm_log_show列出条目 - 使用
search_all=True搜索所有会话 - 尝试更简单、更宽泛的搜索查询
- 等待几秒钟;首次语义搜索需要加载 ML 模型
记忆出现后又消失
- 检查 MARM 是否重启或崩溃(数据会保留在
~/.marm/中) - 确认磁盘空间没有耗尽
- 检查系统日志中是否有数据库错误
数据丢失或损坏
- 立即停止服务
- 检查
~/.marm/目录中是否有备份副本(如果你创建过) - 从备份恢复:将备份中的
~/.marm/复制回主目录 - 重启服务
数据库锁定错误
- 关闭所有 AI 客户端连接
- 停止服务:
Ctrl+C - 备份整个数据库目录:
cp -r ~/.marm ~/.marm.backup - 检查是否有进程占用数据库:
lsof ~/.marm/marm_memory.db(macOS/Linux),或检查任务管理器(Windows) - 如果有进程占用锁,请终止该进程
- 验证数据库完整性:
sqlite3 ~/.marm/marm_memory.db "PRAGMA integrity_check;" - 如果完整性检查失败,请从备份恢复
- 如果完整性检查通过,锁应该已释放;重启服务
性能
搜索结果缓慢
- 首次搜索速度较慢(模型需要从磁盘加载);后续搜索会更快
- 大型数据库(1000+ 条记忆)可能需要几秒钟
- 限制搜索结果:使用
limit=10,而不是不限制结果数量 - 使用
marm_summary压缩旧会话
服务占用过多内存
- 条目较多的笔记本可能会不断累积内容;使用
marm_notebook(action="clear")清理活跃条目 - 关闭未使用的 AI 客户端连接
- 启用压缩后,使用
marm_compaction(action="review")检查暂存的压缩摘要
常见错误消息
| 错误 | 原因 | 解决方案 |
|---|---|---|
address already in use | 端口 8001 已被占用 | 终止占用 8001 的进程,或使用其他端口 |
permission denied: ~/.marm/ | 数据库目录不可写 | chmod 755 ~/.marm/,或检查所有权 |
module not found: core.memory | 缺少依赖项 | 从 marm-mcp-server/ 重新安装:pip install -e ".[dev]" |
database is locked | 多个进程正在访问数据库 | 关闭其他连接,然后重启服务 |
embedding model not found | 语义搜索模型未下载 | 首次运行需要一些时间;请耐心等待并检查网络连接 |
有关记忆行为、传输方式、支持的客户端、压缩和备份的问题,请参阅 FAQ。
Star 历史
MARM 欢迎各个层面的贡献者。代码固然有帮助,文档、设置说明、客户端测试、错误报告、基准测试,以及日常使用 AI 工具的人分享的真实工作流反馈,同样重要。
欢迎参与的方式:
- 使用更多 MCP 客户端、IDE Agent 和操作系统测试 MARM
- 改进文档、截图、示例和特定平台的设置说明
- 报告错误或令人困惑的安装步骤,并提供清晰的复现细节
- 分享实际使用中的记忆工作流、Agent 习惯和工具创意
- 查看未解决的问题
💡 想在此列表中留下你的名字吗?请查看我们的 CONTRIBUTING.md 指南,开始参与!
加入 MARM 社区
助力构建 AI 记忆的未来——无需编写代码!
交流: MARM Discord | GitHub 讨论区
许可证与使用声明
版权所有 © 2026 Ryan A. Lyell。MARM 基于 Apache 2.0 License 发布(版权声明请参阅 NOTICE),欢迎分支、实验和集成。MARM 也封装了 codebase-memory-mcp 等第三方开源组件,这些组件采用 MIT 许可证;版权归属信息请参阅 THIRD_PARTY_NOTICES.md。如果你基于 MARM 构建项目,请让非官方版本易于与官方 MARM 仓库发布的版本区分开来,以便用户了解自己安装的是什么。
项目文档
使用指南
- README.md - 本文件:完整使用指南、工具参考、工作流和架构
- PROTOCOL.md - MCP 操作协议
- FAQ.md - 关于使用 MARM 的常见问题解答
MCP 服务安装
- INSTALL-DOCKER.md - Docker 部署(推荐)
- INSTALL-WINDOWS.md - Windows 安装指南
- INSTALL-MACOS.md - macOS 安装指南
- INSTALL-LINUX.md - Linux 安装指南
- INSTALL-PLATFORMS.md - 平台安装指南
项目信息
- CONTRIBUTING.md - 如何为 MARM 做贡献
- CHANGELOG.md - 版本历史和更新
- ACKNOWLEDGMENTS.md - 贡献者和致谢
- ROADMAP.md - 计划中的功能和开发路线图
- LICENSE - Apache 2.0 许可证条款
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。