关于 Memory Arbiter Mcp
Memory Arbiter MCP 是面向多个 AI Agent 和编码工具的本地事实存储服务,使用 SQLite 保存记忆并通过 MCP 共享。它保留来源与版本记录,通过冲突审查和需用户授权的治理操作,避免事实被静默覆盖。
主要功能
- 01使用本地 SQLite 存储记忆
- 02按证据检索事实
- 03记录来源与完整版本历史
- 04检测冲突并提供审查记录
- 05治理操作需逐项用户授权
- 06支持多个客户端共享记忆
适用场景
- 01在不同编码工具间共享项目事实
- 02查找并核对先前记录的信息
- 03追踪被更新或取代的事实
- 04审查冲突并授权记忆变更
MCP 相关
通过 MCP 提供记忆存取、审查、治理和修复工具。可使用 stdio 或本地 HTTP 传输,多个客户端可连接同一本地服务。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Memory Arbiter MCP
English | 中文
Memory Arbiter 是面向 AI Agent 的可信本地事实层——不仅是共享记忆,更是共享当前有效、可信、可追溯且可安全使用的事实。它是通过 MCP 暴露的本地 SQLite 服务:提供四种产品工具、基于证据的回忆、建议性的冲突通知,以及由用户授权的治理。每条事实只在本地 SQLite 中存储一次,它能够调用的每个模型都在本地运行。
当前版本:
0.17.2(采用三分类 mDeBERTa 判别器,已退役 claims 通道;remember 和 workspace-govern 操作需要 workspace,提供workspaces视图;升级后自动回填行向量;全面修复项目审查中发现的问题)。
为什么值得信任
- 唯一且完整的事实来源。 每条记忆都保留完整的原始文本。证据向量、全文搜索和排序都是派生索引——可重建,绝不是唯一副本。
- 每次写入都有来源信息。 每条记忆都包含
source_type、source_ref、event_time和ingest_time。按照约定,user_confirmed标签仅用于用户明确核实过的事实;技术层面的强制保护体现在标记之后——user_confirmed记忆会被锁定,防止被悄悄修改。 - 信任等级。
normal/protected/locked保护级别可防止 Agent 悄悄覆盖已锁定的内容;只有在每项操作都获得用户授权后,memory_govern(confirm)才会将记忆提升为user_confirmed。 - 完整版本历史。 每次编辑都会递增版本号并追加到
memory_history;取代链会保留旧事实的可追溯性,而不是悄悄将其替换。 - 每个事件一条冲突记录。 单个
conflicts表会为每个一对多冲突事件保存不可变的检测快照、值分组、决策和应用结果。判别器不会指定胜出方,也不会编辑记忆。 - 经授权的治理。 用户确认特定操作后,每项会更改状态的
memory_govern操作都必须设置authorized=true。 - 仅在本地运行。 嵌入在本地 GGUF 模型上运行;可选的冲突判别器使用本地 mDeBERTa 检查点(CPU)。唯一的出站调用是可选的 PyPI 更新检查,可通过
update_check.enabled=false禁用。
基准测试:LoCoMo-Refined
在 LoCoMo-Refined 上评测
(全部 1,382 个问题,使用官方判别器 Qwen3-14B):
| 配置 | 总体 | 纯文本 |
|---|---|---|
| mema + writer-agent(deepseek-v4.1-flash writer,公开规则) | 61.00% | 65.62% |
mema verbatim(零 LLM 写入路径,原样使用话语和 event_time) | 43.13% | 49.48% |
背景:Mem0 的完整流程得分为 48.91%(由基准测试作者重新评测的纯文本结果)——不使用 LLM 写入的基础 mema 与之持平;使用 writer-agent 后,按排行榜的纯文本标准,mema 位列第二。 在重放的 20 段对话中,写入路径还检测出 552 个语义冲突(自行训练的 mDeBERTa 判别器,按发布配置运行)。
完整的方法说明、消融实验(包括答案器独立性和 82% 的信息上限)、复现步骤及提交文件:
evals/locomo/RESULTS.md。
安装与快速开始
使用 AI Agent 安装
将以下内容粘贴到 Codex、Claude Code、Cursor 或其他可访问终端的编码 Agent 中:
Read the latest README at https://github.com/billy12151/memory-arbiter-mcp.
Install and configure the latest mema release for my operating system and current AI client.
Preserve any existing config and database; do not overwrite or delete existing data.
Ask me before choosing between materially different install modes, changing existing config,
or performing any destructive or privileged action. When finished, run mema doctor and report
the install method, config path, database path, client integration, and verification result.
Agent 应将此 README 视为事实依据,在选择 uvx、core、vec 或 semantic-local 之前检查本地环境;如果无法推断出安全的选择,则应暂停并向用户询问。只有在运行 mema doctor 并报告所有警告后,才算完成成功安装。
手动安装
# One command: package + deps + embedding model + config.json (resumable downloads, ModelScope fallback)
curl -fsSL https://memarbiter.cn/install.sh | bash
或按步骤操作:
pip install "memory-arbiter-mcp[vec,semantic-local]" # core + sqlite-vec + local GGUF runtime
mema setup --install # downloads the embedding GGUF (~330MB, resumable); the mDeBERTa judge is a separate manual install
mema doctor # verify
不带 --install 的 mema setup 仅提供指导:它会写入 ~/.config/memory-arbiter/config.json 并自检环境,不会触碰 pip 或网络;--install 则是执行模式(pip 会安装额外依赖,下载嵌入 GGUF 模型,并在支持断点续传和镜像回退的情况下完成下载,且会自行写入完整配置)。从 0.15.0 起,配置仅通过文件设置,整个用户配置界面有 28 个键(参见配置):路径、身份、工作区/隔离、update_check.enabled、include_size、嵌入模型、可选的语义冲突 mDeBERTa 判别器(mdeberta_ckpt,见下文)、Console LLM 工作台自己的端点(llm.*,0.18.0),以及 MCP 传输方式/主机/端口。参考配置 examples/memory-arbiter.config.example.json 展示了同样精简的配置界面,并附有各键说明。然后使用 examples/*.mcp.json 配置 MCP 客户端,并通过 mema 启动服务。
缺少某项功能时(例如从未下载模型),每个工具响应都会持续显示降级模式横幅,并提供 mema setup --install 解决方法;每个 Agent 的首次调用还会包含功能健康卡,安装不完整时无法悄无声息地冒充完整安装。
服务必须显式配置身份:在 config.json 中设置 client 和 agent_id,或通过启动上下文环境变量 MEMORY_ARBITER_CLIENT/MEMORY_ARBITER_AGENT_ID 设置(stdio 的 examples/*.mcp.json 条目会通过 env 完成设置)。没有内置默认值——任一值为空时,服务都会拒绝启动。对于 stdio,此配置身份是用于归属标记的进程级调用方身份;memory(action="remember") 不接受 data 中的 agent_id/client。streamable-http 则从下文所述的逐请求请求头中获取调用方身份。
stdio 仍是默认方式。如需由多个客户端共享一个本地服务,将 mcp.transport 设置为 streamable-http(或设置六个保留的启动上下文变量之一:MEMORY_ARBITER_MCP_TRANSPORT=streamable-http),并连接到 http://127.0.0.1:8000/mcp。每个客户端的 MCP 服务条目都必须设置固定的 X-Mema-Client 和 X-Mema-Agent-Id 请求头;参见 examples/streamable-http.mcp.json。客户端会在每个 HTTP MCP 请求中自动发送这些请求头——Agent 不应在单独的工具调用中添加身份信息。身份信息缺失、为空、无效、重复或冲突时,都会被拒绝,而不会回退到默认值。社区版 HTTP 模式仅绑定到 localhost;这些请求头仅用于标示来源,不提供身份验证或多租户隔离。
日常循环只需调用四个工具——用 remember 记录可复用的信息,用 find 检索,用 read 精确查找,并在较新的来源替换现有当前记忆时用 update(绝不要为同一事实来源创建第二份有效副本)。remember 必须提供 workspace(0.17.1):首次调用时先用 memory_review(view="workspaces") 列出现有分区,然后传入已存在的规范名称——'default' 是全局池;只有在确实要创建新分区时才传入新名称。为任意 Agent 指定随附规则:
{"action":"help","data":{"topic":"agent_onboarding"}}
四个工具
memory:remember、find、batch_find、read、batch_read、update、judge、status、helpmemory_review:只读查看健康状态、冲突组/详情、历史记录、过期记忆、审计记录和实体memory_govern:经明确授权后执行退役、应用/解决冲突计划、确认和工作区治理memory_repair:重建证据、广泛扫描/记录冲突、清理历史记录、分配实体、激活待处理项、重放备份、控制语义运行时,以及管理通知生命周期 每次产品调用都会返回封套{ok, mode, warnings, degraded, data}。特定操作的action_required、next_action、replan和记录都位于data下;成功的调用还可能带有顶层notices数组。每条 notice 都有自己的action_required,以及位于 notice 对象中的机器可读调用。请勿查找通用的顶层action_required。
batch_find 一次调用最多运行 8 条查询并合并结果页(按 memory_id 去重;每项带有 matched_query_ids/best_query_id;per_query 提供每条查询的统计信息)——对于多主题任务,这可以用一次调用替代 5-10 次工具往返。自 0.15.9 起,find 对空结果的处理也更加真实:查询没有召回任何内容时,会返回带有改写提示的空结果页(不会塞入近期记忆);低于校准相关性下限(8.1)的候选项不会进入查询召回结果页——减少“看起来相关,其实并非如此”的引用。
find 返回索引页:默认情况下(content_mode="preview",0.15.10),每条结果都包含元数据以及 content_chars(全文长度,即 read 会返回的全文量)和一个有界的 outline,其中最多包含 8 个 {head, offset} 片段,偏移量与 read 使用相同的 span 坐标系,因此 span=[offset, offset+N] 会截取该片段。**关键词查询风格(0.17.0):**由空格分隔的简短中文词语组成的查询(每个词 ≤4 个字符,例如 向量 唯一键 冲突)会被视为关键词——语义上接近查询、且内容/主题包含任一关键词(整词子串)的记忆会获得更高排名;会忽略那些大量涌入候选池的主题泛化词;若关键词在任何地方都未出现,则不会强制匹配(请改写查询)。内容深度采用单选枚举:content_mode="hits" 会添加 hit_spans——与向量匹配的单元,格式为 {text, start_offset, end_offset},从来源内容中截取(读取 span=[start,end] 会返回完全相同的文本)。命中片段绝不会被截断:合并后的命中覆盖内容的 ≥50% 时,该条目会升级为全文,同时保留 hit_spans 作为注释;没有向量命中的条目则保留普通预览格式。hit_window=N(默认值为 0)会为每个命中扩展 ±N 个相邻完整句子(相邻句子标记为 matched=false);hit_spans 只出现在查询召回结果页中——浏览/筛选结果页不包含此字段——过期版本的命中会被丢弃,并附带 stale_hit_spans 标记和重新查询警告(编辑后,证据索引可能会短暂滞后)。content_mode="full" 会返回全文(旧参数 include_content=true 已于 0.15.10 移除——调用会明确报错并提示迁移方式)。分数仅在同一结果页内可比较;如果第一页没有找到目标,请改写查询或添加 tags_filter,而不要翻到更深页——未筛选的查询召回会报告 total_estimate=null/has_more=false,筛选后的召回则会保留精确数量。size 区块会统计实际返回的结果页:returned_chars/returned_count,以及基于确定性分桶表估算器(heuristic_v1)得出的 tokens_estimate;该估算器在设计阶段根据 Qwen2.5 分词器进行校准(仅作校准参考——自 0.17.1 起不再随附 Qwen 运行时);纯中文文本的估算值约高出 30%,纯英文文本约高出 17%——估算值和估算份额使用同一把尺子,因此节省量比较仍然有效。自 0.15.6 起,同一 size 区块会出现在所有召回接口中——read(统计返回的记录,包括 span 窗口)、memory_review 的 expired 和 history(统计返回的列表)——统一由全局配置键 include_size 控制(默认值为 true);每个区块的 display_hint 都会重复显示 token 数,并提示用户报告此次召回的成本;include_size=false 会同时关闭所有这些区块;find 旧有的逐次调用参数 include_size 会被忽略,并附带警告。unresolved_conflict_count 仅当结果页条目直接命中处于未解决/应用中状态的冲突组时才会出现,且统计的是这些结果页条目的数量。
召回机制
词法和证据通道分别进行召回,再通过互惠排名融合按记忆合并,随后应用信任度、时效性、筛选和工作区调整。
- 词法:基于内容的 FTS5,加上 subject/tags LIKE;只有在向量不可用时,才运行有界的 content-LIKE 锚定通道(自 0.16.10 起作为降级路径)。
- 证据:写入路径任务会从
subject(开头的 subject 行)、句子和表格行派生行片段(0.17.0:原有的单元表已弃用;行向量是唯一的证据通道)。索引器不会提取事实、推断实体或调用模型,只会切分已存储的源文本。证据命中会携带源文本偏移量。memory(action="read", data={"memory_id": 42, "span":{"start":120,"end":640}})只返回裁剪后的源文本窗口,以及data.span.{start,end,total_chars};省略span即读取完整源文本。Span 边界必须是严格整数,满足0 <= start < end,且end会裁剪至内容长度。整张超过 100 行的表格不参与处理(不生成行向量,也不检测配对——回执中显示为table_rows_exempted)。
冲突组与通知
证据 KNN 会召回句子级邻近项,但不会判定冲突真伪。自 0.17.1 起,通过确定性筛选流程(句子预筛选、记忆级筛查、余弦相似度区间、规则证据)的每个候选对,都会由可选的本地 mDeBERTa 编码器进行判定(三个类别:conflict / no_conflict / possible_conflict,另有一个机制分类头)。判定器只会看到两段不含其他信息的行文本——没有元数据,也不进行提示词工程——并返回校准后的概率:
- 当
conflict的 P ≥semantic_conflict.mdeberta_notice_min_prob(默认值为 0.8,即自 0.17.2 起生产环境使用的 v58_ep3_fp16 配对)时,发出普通严重级别通知; - 当
possible_conflict的 P(conflict)+P(possible_conflict) ≥semantic_conflict.mdeberta_possible_min_susp(默认值为 0.7,自 0.17.2 起)时,发出info严重级别通知(灰区参考,不含action_required);低于门槛的配对会被计数(model_possible_below_gate),但不会通知; no_conflict→ 静默判定为无冲突(计入回执)。
判定器不会选出胜者、抑制计划扫描或编辑记忆。
这里有意设置了两道门槛:
- 计划扫描范围较广。
memory_repair(task="scan_candidates")会保留确定性的 KNN/规则候选;扫描路径不会运行模型——Agent 会在此处审核候选项。include_duplicates=true仍是单页抽查(该页内与 record_conflict 兼容的所有成员);如需完整扫描重复项,请使用独立的memory_repair(task="scan_duplicates")任务,该任务会在服务端汇总所有页面,并统一受 200 对的全局上限约束。外部审核者会通过record_conflict(status="open"|"not_a_conflict")记录每个完成分类的候选项,以实现快照去重。 - 写入时通知由判定器把关。 只有判定器给出高于所配置概率下限的
conflict结果(或确定性的同键/值差异直接判定),才会向用户显示通知。槽位标识由workspace + subject以及配对哈希差异锚点构成(确定性直接路径保留真实属性)。其他情况都会放行,留待后续扫描审核;内部(同一记忆内)发现始终会进入待处理状态——扫描端的强模型负责给出否定判定。同步投递等待时间(可通过semantic_conflict.notice_sync_wait_ms配置,默认值为3000,范围限制为0–5000)只控制何时附加通知,不会改变检测结果。 设置定时任务。 mema 按设计不提供内部计时器:流水线的价值闭环止于 Agent 侧判断,因此外部调度器负责唤醒 Agent。0.16.0 规范 v2 取代了 v1 基于页面的分流循环:每小时运行一次任务,反复调用memory_repair(task="scan_pipeline", data={"action": "kick"}),直到complete=true(服务端自行遍历知识库,根据每条记忆的水位线判断执行完整扫描还是增量扫描,并将每个可疑项放入仅供 Agent 使用的判断队列——绝不放入通知或面向用户的冲突列表),然后通过memory_repair(task="scan_queue", data={"action": "page"})/action="submit"清空队列(服务端根据引用落地:驳回 → 抑制来源;确认 → Agent 只需提供 slot_key + 显示值)。每天执行一次memory_review(view="doctor")。scan_candidates仍仅用作手动/诊断通道;conflicts.spec_drift会标记需要重建的 v1 时代任务。每次完整扫描边界完成后(某个页面返回next_anchor_memory_id=null且已扫描锚点),会向scan_log.jsonl追加一条轻量审计记录;在此之前,Agent 会收到scan_never_run/scan_stale指引通知,doctor 会标记仍待执行的重建(conflicts.scan_required),或标记扫描已闲置超过 14 天(conflicts.scan_stale)——任务运行后,这两项都会自行消失。完整的平台无关规范见memory(action="help", data={"topic": "scheduled_tasks"})。
单个 conflicts 表存储一条一对多事件及其不可变的成员/值快照。其公开生命周期为 open → applying → resolved,并以 not_a_conflict 作为终态分流结果。memory(action="judge") 会通过 CAS 固定冲突修订版本、记录选定值和计划,并将其状态改为 applying;随后按顺序逐一执行返回的 memory_govern(action="apply_conflict_action"),明确提供授权和最新修订版本,然后仅在所有计划中的成员操作完成后调用已授权的 resolve_conflict。use_as_resolution 必须指向持有所选值组的成员。默认判断会更正记忆中的错误数据——对于持有已过时声明的成员,计划使用 update_current_claim 或 append_superseded_context;仅当用户明确要求保留历史记录时,才使用 preserve_historical_record。部分失败会使状态保持为 applying:当 data.action_required="replan_conflict" 时,重新读取该组/成员,并使用当前修订版本和替换计划调用已授权的 memory_govern(action="replan_conflict")——若 update_current_claim 未通过依据校验,可重新编辑,使所选值逐字出现在成员内容中(即存储的机器规范化形式;对于多个单词组成的短语,必须使用规范化后的字符串本身),或者传入从该组 value_groups 中选出的替换 chosen_value(0.15.15;替换 chosen_value 也会将解决方案持有者移至新的值组,除非已明确固定)。重新规划会保留之前的计划历史;绝不要重试基于过期状态预先计算的步骤。
工作区
在每种 isolation 模式下都会执行工作区规范化,且与访问控制分开。none 不应用工作区 ACL:省略工作区时,范围涵盖整个库;显式提供工作区时,会将其规范化,并将读取范围限定在该工作区。weak 会增加一个软排序/提示信号(固定的二进制微调——连续向量距离加权已不再是可调参数)。在 strict 模式下,系统绝不会静默合并近似匹配项:新工作区会保持 pending 状态,直到经过授权的 memory_go(confirm_pending_workspace) 将其激活。严格可见性使用受保护的向量准入机制(自 0.15.0 起始终启用,且为冻结常量):工作区敏感的回忆/读取/修复操作、冲突/通知工作流以及控制台内容/计数视图共用同一准入集合:调用方规范名称,以及默认池、短名称和通用子字符串保护规则之后,余弦距离不超过 0.25 的所有规范名称。进程全局维护(例如语义运行时控制、备份重放、doctor 和设置)不属于工作区范围内的内容视图。向量缺失或 sqlite-vec 降级时,会回退到调用方的精确规范名称。保留的 default 池与严格项目范围隔离,不会在其中显示。自动向量规范化只会影响记忆的 workspace_canonical;受支持的工作区治理方式包括重命名、迁移、按 ID 移动(move_memories_workspace)、确认待处理项以及确认整个注册表。内部重定向/负向决策状态可防止旧名称再次拆分,也可防止被抑制的候选项重新出现,但这并非面向用户的工作流。
首次成功写入并注册规范工作区时,在 none/weak 模式下会返回顶层非阻塞 workspace_review 通知,以及 data.write_hints.new_workspace_detected。运行经过授权的 confirm_workspaces 前,请先检查可能的重复项。strict 则会返回现有的阻塞式 action_required=confirm_new_workspace 流程,不会发出重复的非阻塞通知。
回忆黑名单(0.15.5)
recall_blacklist.jsonl 中列出的工作区(位于数据库文件旁)会从未指定范围的 find 回忆中排除——这是默认的环境池。每行填写一个不带引号的工作区名称;空行和 # 注释会被忽略;修改会在下一次 find 时生效。没有文件 → 应用内置默认值(mema-twin,即 mema-twin 偏好桶);空文件 → 不排除任何内容;新建的文件会完全替代默认值。
不会过滤的情况:显式指定 workspace 参数(即使该工作区在黑名单中)、严格隔离、筛选条件驱动的回忆(空查询 + tags_filter/时间/source_type)、过期审计路径、写入时去重、冲突扫描以及按 ID 读取。排除匹配规范工作区列和原始工作区列,因此规范名称已漂移的行仍会被捕获。doctor 会报告生效列表(recall.blacklist)。
控制台:治理与知识工作台(0.18.0)
memory-arbiter console 会打开本地浏览器控制台(仅限 127.0.0.1)。
- 治理:概览、并排显示成员的冲突审查、doctor、只读设置。
- 知识库选项卡:整理哪些记忆属于你的知识库
(一键添加/移除、从文档提取的候选池、搜索后添加)。
成员身份存储在专用的
kb_member列中,Agent 重写标签时不会意外将其移除。 按工作区 → 标签浏览,查看渲染后的 Markdown 正文和一跳关系图。 - 大模型研究工作台:使用你自己的 OpenAI 兼容 API(在 Settings 中配置基础 URL /
API 密钥 / 模型 / 上下文预算 — 存储在本地,由控制台后端代理,绝不会暴露给页面;密钥以纯文本形式保存在配置
文件中,因此请确保只有文件所有者有权访问 — 写入路径会强制设为
0600)。可对所选记忆一键执行六种研究 操作 — 总结、列提纲、测验、费曼式讲解、自我测验、时间线 — 还可使用自由格式提示词。输出可通过标准写入管道保存为记忆(归属为agent_id=console)。
在 isolation=strict 下,控制台一次只查看一个工作区(不能跨存储区绕过隔离);在默认的 none 模式下选择“All workspaces”。
mema 的运行
mema doctor [--json|--deep]— 只读健康检查;--deep会加载 GGUF 模型并探测实时嵌入维度。若规范记录未出现在已审查快照中,workspace.review会发出警告(CLI 退出码为 1)。请先重命名/合并重复项,然后调用经授权的memory_govern(confirm_workspaces),且不提供显式列表,以快照当前注册表并使此项检查恢复通过。只有在没有其他警告时,整个 CLI 才会以 0 退出。mema console— 127.0.0.1 上的只读本地控制台。memory(action="status")— 显示local_text_evidence覆盖情况、vec_index_state、进程本地索引队列,以及semantic_conflict运行时状态,包括队列丢弃/重启和check_degradation.last_reason。memory_repair上的维护任务:rebuild_evidence(先试运行,再分批执行;更改嵌入模型后,索引会报告state=mismatch,重建会自动将其恢复为ready)、semantic_control(status/pause/resume/enable/unload/disable)、replay_backup(先试运行,再经授权执行)、cleanup_history、set_entity、activate_pending和scan_duplicates(一次调用即可对整个资料库执行近重复项扫描,最多检查 200 对轻量级组合;include_quotes=true会添加触发扫描的证据引文)。
证据队列和语义队列都属于进程本地队列,因此崩溃或强制关闭可能导致队列中的工作丢失。不要根据队列深度推断持久化覆盖情况。重启后,或证据侧发出 busy/丢弃信号后,请检查 local_text_evidence 覆盖情况并运行 rebuild_evidence,直到试运行结果为空且向量状态为 ready;语义工作线程队列丢弃的任务由计划执行的 scan_candidates 扫描恢复,而非通过 rebuild_evidence 恢复。重建证据是幂等的派生索引修复操作;只有扫描才能恢复从未处理过的冲突候选项/通知。
从较旧的数据库升级
**0.14.8 升级警告:**当前运行时启动时仅接受架构版本 workspace_state_v1。conflict_groups_v2 和 local_text_evidence_v1,以及更旧的 claim/memory-vector/section-vector 数据库,都会被拒绝且不会修改。请运行公开的并行升级命令 mema upgrade。每次架构迁移都会声明 vector_effect=preserve|rebuild;从前两个证据版本迁移时,无论当前模型是否可用,都会保留向量负载。兼容性会单独评估:配置的嵌入空间不同会记录 state=mismatch、禁用向量读取,并在之后通过 memory_repair(rebuild_evidence) 修复。这两种路径都会压缩当前工作区重定向/否定决策状态,并丢弃已过时的工作区决策事件账本。
并行副本会保留记忆内容/历史记录、备份重放回执、工作区规范项及当前重定向/否定决策状态,以及审计数据。不会复制已过时的工作区决策事件账本。保留迁移会原样克隆 FTS/证据/向量负载,并以事务方式仅重建冲突域;向量健康状态或空间不匹配不会改变结构迁移结果。重建迁移会重新生成证据和向量。两种路径都会有意让新的 conflicts/通知状态保持为空,且不会复制旧的 conflicts、仅追加的 conflict_judgments 或 semantic_notices 历史记录。当前矛盾必须通过计划执行的全库扫描重新发现。
重建后,status/doctor 会报告 conflict_scan_required=true,并提供持久化的扫描纪元。只有成功执行的全量扫描覆盖升级时的活动记忆集合,且使用匹配的检测器版本,才能通过 CAS 清除此标记;分页扫描、失败扫描及使用较旧检测器的扫描都不能清除标记。只有在完成行/指纹检查、成功执行 PRAGMA wal_checkpoint(TRUNCATE) 并移除目标 WAL/SHM 附属文件后,目标才会发布;完整重建路径还要求覆盖所有符合条件的证据。源数据库永远不会被删除。
# Preview only.
mema upgrade --dry-run
# Stop every mema MCP client/worker. Make a WAL-safe rollback backup:
sqlite3 /absolute/path/to/memory.sqlite3 "PRAGMA wal_checkpoint(TRUNCATE);"
cp /absolute/path/to/memory.sqlite3 /absolute/path/to/memory.pre-0.14.sqlite3
# Migrate and switch the standard JSON config.
mema upgrade
# Restart the MCP client and verify.
mema doctor --json
After the upgrade, the first server start launches a daemon thread that backfills sentence row vectors automatically; watch progress in `mema doctor` (`rows.coverage`) or `memory(action="status")`. With no embedding model configured the backfill stays pending and resumes once the model is available — nothing to run by hand.
完整证据重建路径需要 sqlite-vec、已配置且可读取的本地 GGUF 嵌入模型、llama-cpp-python(请安装 semantic-local extra,因为它也会运行 GGUF 嵌入)、可写的目标目录,以及充足的可用磁盘空间。保留迁移不会加载任何模型,也不要求向量完整;它会单独报告向量兼容性,并将不兼容的保留数据标记为 mismatch。可选的冲突裁判检查点本身绝不是迁移的前提条件。命令会报告所选模式、向量影响/兼容性、记忆数量、估算的向量处理量、可用磁盘空间、源和目标,然后请求确认。
上述检查点很重要,因为当实时 WAL 帧存在时,只复制主 .sqlite3 文件并不是完整备份;或者,也可以在停止服务前使用 SQLite 的在线 .backup 命令。如果 wal_checkpoint(TRUNCATE) 报告非零的忙碌计数,请中止操作。mema upgrade 也会在切换前对新目标执行检查点并验证,但不会创建供操作员回滚的源数据库副本。
旧数据库永远不会被删除。只有在完整验证后,才会备份并切换标准 JSON 配置;环境变量 db_path 覆盖项会作为手动操作报告。使用 --no-switch 可在不修改配置的情况下构建并验证。--yes 会跳过交互式确认以及确认所有写入器/工作器均已停止且旧冲突/判定/通知历史将被永久舍弃的步骤;它不会停止进程、对源数据库执行检查点,也不会创建备份。较底层的 mema migrate-vnext 命令仍可用于诊断。在新数据库正常运行并成功使用之前,请保留旧数据库;如果新数据库已接受写入,切勿直接切回旧数据库,除非先妥善处理这些较新的记录。
配置
自 0.15.0 起,配置仅通过文件设置。所有可调选项都位于 ~/.config/memory-arbiter/config.json 中(或位于启动上下文变量 MEMORY_ARBITER_CONFIG 指定的文件中;mema setup 会写入初始模板)。引擎参数、超时、阈值和上限均为固定常量(memory_arbiter/constants.py)。
用户可配置的完整选项共 28 项(0.15.14:新增 semantic_conflict.n_gpu_layers,移除 semantic_conflict.max_notice_pairs 和 policy_path;0.17.1:移除 claims.required、semantic_conflict.model_path 和 n_gpu_layers,新增四个 semantic_conflict.mdeberta_* 选项;0.17.2:新增 semantic_conflict.mdeberta_possible_min_susp;0.18.0:新增六个 llm.* 选项):
{
"db_path": "~/.local/share/memory-arbiter/memory.sqlite3",
"backup_jsonl": "~/.local/share/memory-arbiter/memory.backup.jsonl",
"client": "your-client",
"agent_id": "your-agent-id",
"workspace": "default",
"isolation": "none",
"update_check": { "enabled": true },
"include_size": true,
"embedding": {
"model_path": "~/.local/share/memory-arbiter/models/embedding.gguf",
"auto_query": true,
"auto_write": true
},
"semantic_conflict": {
"enabled": true,
"mdeberta_ckpt": "~/.local/share/memory-arbiter/models/mdeberta-v58_ep3_fp16.pt",
"mdeberta_notice_min_prob": 0.8,
"mdeberta_possible_min_susp": 0.7,
"on_write": "async",
"notice_sync_wait_ms": 3000
},
"llm": {
"base_url": "",
"model": "",
"api_key": "",
"max_context_tokens": 0,
"max_output_tokens": 8192,
"timeout_seconds": 120
},
"mcp": {
"transport": "stdio",
"http": { "host": "127.0.0.1", "port": 8000 }
}
}
| 设置 | 用途 |
|---|---|
db_path | 当前 SQLite 数据库 |
backup_jsonl | SQLite 无法写入时使用的仅追加备用方案 |
client / agent_id | 必需的调用方身份;没有内置默认值——任一项为空时,服务都会拒绝启动 |
workspace / isolation | 默认工作区及 none/weak/strict 工作区行为 |
update_check.enabled | 可选的一次性后台 PyPI 检查(默认 true);这是唯一的网络调用,会缓存或抑制通知,且不会自动升级 |
include_size | 召回大小信息块的全局开关(v0.15.6):开启 = find/read/expired/history 均会附加 {returned_chars, returned_count, tokens_estimate};关闭 = 均不附加 |
embedding.model_path | 本地 GGUF 嵌入模型——仅当指向该模型时,才表示要启用 sqlite-vec 证据召回 |
embedding.auto_query / auto_write | 在查询/写入时自动生成嵌入(默认 true) |
semantic_conflict.mdeberta_ckpt | 用于写入时冲突判定的本地 mDeBERTa 检查点(自 0.17.2 切换后使用 v58_ep3_fp16,约 531 MB,需单独提供)。配置后会自动启用、在启动时加载并常驻内存(CPU fp32)。请先安装 mdeberta extra;参见下方的模型下载说明 |
semantic_conflict.enabled | 显式关闭开关;未设置且配置了 mdeberta_ckpt 时表示启用,显式设置为 false 时优先 |
semantic_conflict.on_write | 写入时检测:async(默认)或 off |
semantic_conflict.notice_sync_wait_ms | 写入响应等待提交后检查结果的时长,以便一并返回结果(v0.15.8,默认 3000,范围限制为 0–5000);0 = 写入响应永不阻塞——批量摄取仍会异步运行检查,并在后续响应中发送通知 |
semantic_conflict.mdeberta_model_dir | 包含 config.json 和 tokenizer 的目录;默认值 = <ckpt dir>/mdeberta-base |
semantic_conflict.mdeberta_notice_min_prob | 普通严重程度通知的 P(conflict) 下限(默认 0.8,自 0.17.2 起为 v58_ep3_fp16 生产配对);低于该值时会统计配对数量,但不会发送通知 |
semantic_conflict.mdeberta_possible_min_susp | info 严重程度灰色区域通知的 P(conflict)+P(possible_conflict) 下限(默认 0.7,v0.17.2;根据 exam + LoCoMo gold 语料校准);低于该值时会统计配对数量(model_possible_below_gate),但不会发送通知;0 可恢复到 v0.17.2 之前不设门槛的行为 |
semantic_conflict.mdeberta_batch | 判定批次大小(默认 0 = 自动,按设备级别设置:使用 GPU 时为 16——Apple Silicon / NVIDIA;CPU 上为 8;显式设置为 >0 时会覆盖设备级别设置。不进行启动探测) |
mcp.transport | stdio(默认)或选择启用的本地主机 streamable-http 服务 |
mcp.http.host / port | 本地 HTTP 端点;主机限制为环回地址,默认值为 127.0.0.1:8000;端点路径固定为 /mcp |
llm.base_url / llm.model / llm.api_key | Console LLM 学习工作台自身的 OpenAI 兼容端点(0.18.0,全部可选——留空时工作台不可用)。以纯文本形式本地存储;写入时强制将配置文件权限设为 0600;密钥仅由控制台后端代理,绝不会暴露给页面 |
llm.max_context_tokens | 单次工作台调用的材料预算(默认 0 = 自动,范围限制为 0–10,000,000) |
llm.max_output_tokens | 完成输出上限(默认 8192,范围限制为 1–1,000,000)——设置该值可避免思考模式模型耗尽整个输出预算 |
llm.timeout_seconds | 单次请求超时(默认 120,范围限制为 1–3600);写入和重新加载时都会以相同方式限制该值 |
参见 examples/memory-arbiter.config.example.json。
值得了解的语义:嵌入维度由模型本身决定——数据库会记录当前启用的维度,切换到维度不同的模型后,启动时会自动删除并按新维度重建向量表(一次性完整重建证据)。排序固定为混合排序(词法 + 证据融合);没有排序模式选项。HTTP 请求处理是无状态的,请求正文上限为 4 MB。
以下六个环境变量仍作为启动上下文:MEMORY_ARBITER_CONFIG、MEMORY_ARBITER_DB_PATH、MEMORY_ARBITER_BACKUP_JSONL、MEMORY_ARBITER_MCP_TRANSPORT、MEMORY_ARBITER_CLIENT、MEMORY_ARBITER_AGENT_ID。它们用于选择进程上下文(使用哪个配置文件、哪个 DB、哪种传输方式、哪个身份),且配置文件中的值优先于对应的环境变量。其他所有 MEMORY_ARBITER_* 变量都不再读取——过时的导出变量会在 mema doctor、控制台设置页面和 memory(action="status") 中显示“no longer read”警告。已移除的文件键也会显示“no longer configurable”警告,并被忽略;docs/INTEGRATION.md 列出了 0.14 → 0.15 的键迁移表。
HTTP 模式:共享一个本地服务
stdio(默认模式)无需后台进程:每个 MCP 客户端都会启动 mema,作为自己的短生命周期子进程。只有在需要一个由多个客户端连接的长期运行本地服务时,才切换到 streamable-http。
| stdio(默认) | streamable-http | |
|---|---|---|
| 谁启动 mema | 每个客户端都会生成一个子进程 | 你运行一个持久进程;客户端连接到该进程 |
| 是否需要后台进程 | 否 | 是——否则终端关闭时进程会退出 |
| 客户端配置 | 命令 + 参数 | url + 两个固定请求标头 |
| 适用场景 | 一个人、一个客户端 | 一台机器上的多个客户端共享一个记忆库 |
设置步骤:
- 配置:在
~/.config/memory-arbiter/config.json中将mcp.transport设为"streamable-http"(或设置MEMORY_ARBITER_MCP_TRANSPORT=streamable-http)。 - 保持运行:mema 没有内置守护进程——请使用进程管理器。在 macOS 上,
examples/com.memory-arbiter.mema.plist中的 launchd 模板会在加载时运行该程序,崩溃时自动重启,并将日志写入/tmp/mema.{out,err}.log(将__MEMA_BIN__替换为which mema输出的绝对路径;将文件放入~/Library/LaunchAgents/,然后运行launchctl load)。如需快速试用,可运行tmux new -d -s mema 'mema'。 - 客户端:复制
examples/streamable-http.mcp.json,并填写X-Mema-Client和X-Mema-Agent-Id。
说明:HTTP 请求处理是无状态的(自 0.15.0 起为固定常量),因为 mema 将记忆和语义通知状态存储在 SQLite 中,而不是 MCP 会话中。因此,服务重启不会导致客户端持有已过期的服务会话。异步创建的语义通知仍会从 SQLite 中领取,并像以前一样附加到之后成功的工具响应中;只有尚未持久化通知的工作线程任务可能会因进程重启而中断。
客户端会在每个 HTTP MCP 请求中自动发送这些固定标头——Agent 不得在单个工具的 data 中添加身份信息,否则请求会被拒绝。身份缺失、为空、重复或冲突时都会失败关闭(400),绝不会回退到默认值。服务仅绑定到回环地址;这些标头用于溯源,并非身份验证。由于 launchd 不会继承 shell 的 PATH,也不会展开 ~,因此请在 ProgramArguments 以及 config.json 中任何 GGUF 的 model_path 配置项中使用绝对路径。
通过 localhost HTTP 使用 Claude Desktop / Claude Code
Claude 的本地 MCP 配置会启动 stdio 命令。若要复用一个正在运行的 mema HTTP 服务,而不是另行启动一个 mema 进程,请将以下单个条目放在 ~/.claude.json 的 mcpServers 下(当前的 Claude Desktop/Cowork 和 Claude Code 安装可能共用此用户级文件):
{
"mcpServers": {
"memory-arbiter": {
"command": "/opt/homebrew/bin/npx",
"args": [
"-y",
"[email protected]",
"http://127.0.0.1:8000/mcp",
"--allow-http",
"--transport", "http-only",
"--header", "X-Mema-Client:claude",
"--header", "X-Mema-Agent-Id:claude",
"--silent"
],
"env": {
"PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
"NO_PROXY": "127.0.0.1,localhost"
}
}
}
}
使用你机器上 which npx 返回的绝对 npx 路径。删除任何会直接启动 mema/memory-arbiter-mcp 的旧版 memory-arbiter 条目,否则 Claude 可能会启动第二个服务进程。修改文件后,完全退出并重新打开 Claude Desktop,并重启 Claude Code 会话。mcp-remote 是第三方桥接工具;上述固定版本是经过 mema 测试的配置。如果你的 Claude 安装使用单独的 Desktop MCP 文件,请改为将相同的单个条目放在那里,但不要同时注册两份。
冲突裁决模型(mDeBERTa,可选)
写入时冲突裁决器需要一次手动安装(约 531MB 的 fp16 检查点不会随 PyPI 一同发布):
pip install memory-arbiter-mcp[mdeberta](torch CPU 轮子约 200MB + transformers);- 从 mini-clash 发布产物中下载
mdeberta-v58_ep3_fp16.pt(约 531MB,fp16 权重)以及mdeberta-base目录(config.json + tokenizer,占用 MB 级空间); - 在 config.json 中,将
semantic_conflict.mdeberta_ckpt指向.pt文件(自动启用并在启动时预加载;mdeberta_model_dir默认为检查点旁的mdeberta-base文件夹)。
mema doctor 会验证依赖、检查点摘要以及裁决器的标签约定。未配置 = 禁用写入时仲裁(scan/Agent 后备机制不受影响)。ONNX+INT8(体积更小,无需 torch)计划在后续版本推出。
降级行为
- 若没有 sqlite-vec 或嵌入模型,词法召回和记忆治理仍会继续;证据索引不可用。
- 若没有 mDeBERTa 裁决器(extra/检查点/配置),写入时仲裁将被禁用(notice 会暂停);定时 scan 仍会返回确定性的 KNN/规则基线候选项。
- 如果 SQLite 不可用或不可写入,仅当写入成功时,写入才会使用仅追加的 JSONL 信封。JSONL 包含记忆记录及其选定的规范项,不包含内部重定向或负面决策;请保留或升级 SQLite 数据库,以留存工作区决策状态。
开发
uv run pytest -q
python scripts/sync_version.py --check
开发期间,软件包/文档可能会描述尚未发布的开发版本,而 server.json(MCP Registry 清单)仍保持为最近发布的版本;scripts/sync_version.py 会在发布准备过程中更新它,--check 则可防止版本信息不一致。
中文摘要
Memory Arbiter(迷码)是面向 AI Agent 的本地可信事实层:每条事实只存一份完整原文,向量与检索均为可重建的派生索引。冲突 scan 走宽门召回,写入时 notice 走 mDeBERTa 三分类判定(自 0.17.1 起,保留所有漏斗门);单一 conflicts 表保存一对多事件,生命周期为 open → applying → resolved 或 not_a_conflict。裁决后按 judge → apply_conflict_action → resolve_conflict 顺序治理。none/weak/strict 都会进行 workspace 归一;strict 使用 guarded vector admission,default 池不会进入项目 scope。workspace_state_v1 升级会清除旧 conflict/judgment/notice 历史和旧 workspace decision event ledger,并要求完成带 epoch 的全库 scan。完整中文文档见 README.zh-CN.md;另见 INTRO.md 与 docs/INTEGRATION.zh-CN.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。