{"_id":"@bingo_touth/memory-mcp-server","_rev":"2-ee4f757d77f0949ae8f307b4a4fc1c51","name":"@bingo_touth/memory-mcp-server","dist-tags":{"latest":"0.9.2"},"versions":{"0.9.1":{"name":"@bingo_touth/memory-mcp-server","version":"0.9.1","_id":"@bingo_touth/memory-mcp-server@0.9.1","maintainers":[{"name":"bingo_touth","email":"2207727224@qq.com"}],"bin":{"memory-mcp":"dist/index.js"},"dist":{"shasum":"eb50c7cc1a65e222cda25a8d98a0a67cf2ed74ac","tarball":"https://registry.npmjs.org/@bingo_touth/memory-mcp-server/-/memory-mcp-server-0.9.1.tgz","fileCount":78,"integrity":"sha512-QEZadw2nB1Vi+fufDzKVAyKezBWRe+I/Z8X98lnUlOMoXwJJFBHL/vLljyyyIPqSZZmWDh4XcVR3WAoGp/NKLg==","signatures":[{"sig":"MEYCIQCwVjPkzA9+KOYg788PmYbnb8UiLBL5fTG33aYyytxD6QIhAIpc3ud98gbYsz74BKqTF3tzss5hc8OlactcHUJwmrHq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":753176},"type":"module","engines":{"node":">=20"},"gitHead":"f304c403ed8e95d17abe50320c80c08702bddbe7","private":false,"scripts":{"dev":"node scripts/inject-version.mjs && tsx src/index.ts","test":"node --import tsx --test test/**/*.test.ts","build":"node scripts/inject-version.mjs && tsc","check":"node scripts/inject-version.mjs && tsc --noEmit","start":"node dist/index.js","watch":"tsx src/watcher/cli.ts","backfill":"tsx src/watcher/cli.ts","multiview:eval":"node bench/run-multiview-eval.mjs","prepublishOnly":"node scripts/inject-version.mjs && tsc"},"_npmUser":{"name":"bingo_touth","email":"2207727224@qq.com"},"_npmVersion":"10.9.8","description":"分层长期记忆 MCP 服务器：本地 MiniLM 或 OpenAI 兼容嵌入 API，供 LLM Agent（DeepSeek Harness / Claude Code）做可语义检索的长期记忆","directories":{},"_nodeVersion":"22.23.1","dependencies":{"sql.js":"^1.14.1","@xenova/transformers":"^2.17.2","@modelcontextprotocol/sdk":"^1.25.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","typescript":"^5.8.0","@types/node":"^26.0.1"},"_npmOperationalInternal":{"tmp":"tmp/memory-mcp-server_0.9.1_1786886236074_0.41743244301338356","host":"s3://npm-registry-packages-npm-production"}},"0.9.2":{"name":"@bingo_touth/memory-mcp-server","version":"0.9.2","private":false,"type":"module","description":"分层长期记忆 MCP 服务器：本地 MiniLM 或 OpenAI 兼容嵌入 API，供 LLM Agent（DeepSeek Harness / Claude Code）做可语义检索的长期记忆","bin":{"memory-mcp":"dist/index.js"},"dsh":{"bundle":{"patch":"cordis.patch.yml"}},"engines":{"node":">=20"},"scripts":{"dev":"node scripts/inject-version.mjs && tsx src/index.ts","watch":"tsx src/watcher/cli.ts","backfill":"tsx src/watcher/cli.ts","check":"node scripts/inject-version.mjs && tsc --noEmit","build":"node scripts/inject-version.mjs && tsc","start":"node dist/index.js","multiview:eval":"node bench/run-multiview-eval.mjs","test":"node --import tsx --test test/**/*.test.ts","prepublishOnly":"node scripts/inject-version.mjs && tsc"},"dependencies":{"@modelcontextprotocol/sdk":"^1.25.0","@xenova/transformers":"^2.17.2","sql.js":"^1.14.1"},"devDependencies":{"@types/node":"^26.0.1","tsx":"^4.20.0","typescript":"^5.8.0"},"_id":"@bingo_touth/memory-mcp-server@0.9.2","gitHead":"0cf5c9a26534327eea95581bcbfa0cfda408421e","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-zuEijIzWFbI8ZesQzNBHY+xSOl3th+k4P6KfaBNGcxw5w/dMfl0oYFfi6a0d6+CC9ar/G3iBL09CUZQI7pmNXg==","shasum":"b47e5f0f208b356a813ec9eea121be6fac4dc0b7","tarball":"https://registry.npmjs.org/@bingo_touth/memory-mcp-server/-/memory-mcp-server-0.9.2.tgz","fileCount":79,"unpackedSize":756323,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCdrid698mUC/+qc/R+fu/vTqL/+XIW2aRsOIUw3mb/yAIgJchU+nU3zrRZnpQUH2CirUfx3CL8uBab0M7qLrFfP1Y="}]},"_npmUser":{"name":"bingo_touth","email":"2207727224@qq.com"},"directories":{},"maintainers":[{"name":"bingo_touth","email":"2207727224@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/memory-mcp-server_0.9.2_1786888799041_0.5385194082348943"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-16T13:17:15.877Z","modified":"2026-08-16T13:59:59.320Z","0.9.1":"2026-08-16T13:17:16.241Z","0.9.2":"2026-08-16T13:59:59.181Z"},"description":"分层长期记忆 MCP 服务器：本地 MiniLM 或 OpenAI 兼容嵌入 API，供 LLM Agent（DeepSeek Harness / Claude Code）做可语义检索的长期记忆","maintainers":[{"name":"bingo_touth","email":"2207727224@qq.com"}],"readme":"# memory-mcp-server\n\n一个给 LLM Agent(如 Claude Code)用的**分层长期记忆 MCP 服务器**。把对话沉淀成可语义检索的三层记忆,回答\"我们上次聊到哪了\"时能带出完整上下文。\n\n> 当前版本:**0.9.1**\n\n- **本地优先,可选 API**:默认用本地 `@xenova/transformers`(多语言 MiniLM,384 维,零云依赖);也可切换到 **OpenAI 兼容嵌入 API**(`MEMORY_EMBED_PROVIDER=api`,免下载本地模型,见下文)。\n- **分层回溯**:命中片段(L1)时自动回填当天总结(L2)和主题脉络(L3)。\n- **优雅降级**:本地模型加载失败或 API 不可用时退回关键词(Jaccard)检索,并在 stderr **明确告警**——不会假装正常。\n\n---\n\n## 记忆分层\n\n```\nmemory/                     # 存储根,相对「服务器进程的工作目录(CWD)」\n├── raw/<date>/turns.jsonl  # 原始对话,一字不改,全量保留\n├── fragments/<date>/       # L1 任务→结果片段 (.md + .embedding 向量)\n├── daily/<date>.md         # L2 每日总结\n└── topics/<topic>.md       # L3 跨天主题索引\n```\n\n写入顺序:`store_turn`(逐轮) → `create_fragment`(打包几轮为一个片段,自动算 embedding) → `create_daily_summary` / `upsert_topic`(汇总)。\n\n> **重要:存储根是相对 CWD 的**(`path.resolve(\"memory/...\")`)。服务器进程以哪个目录为工作目录,记忆就写在那个目录的 `memory/` 下。让宿主(Claude Code 等)以「你想要记忆的项目根」为 CWD 启动本服务器。\n\n---\n\n## 安装 & 构建\n\n下载安装到某个路径\n\n```bash\nnpm install\nnpm run build      # tsc → dist/\n```\n（注意，CherryStudio用户可能由于该GUI的路径问题或管道问题无法直接使用，请谨慎安装）\n\n要求 Node ≥ 20(开发用 22 验证)。\n\n### 从 npm 安装\n\n```bash\nnpm install -g @bingo_touth/memory-mcp-server   # 全局安装\nmemory-mcp                                      # 直接以 stdio 启动\n# 或临时运行：npx @bingo_touth/memory-mcp-server\n```\n\n> 本包发布名：**`@bingo_touth/memory-mcp-server`**（npm 裸名 `memory-mcp-server` / `memory-mcp` 均已被他人占用，故用 scoped 名）。\n\n## 各 harness 接入片段（参数化）\n\n**数据根约定（最重要）**：记忆库存储在**服务器进程 CWD** 下的 `memory/` 目录。以你想让记忆归属的项目根作为 `cwd` 启动——下面两个配置的 `cwd` 字段都是关键。\n\n### DeepSeek Harness（DSH）：`~/.dsh/profiles/<profile>/cordis.patch.yml`\n\n```yaml\n- id: mcp-memory\n  name: '@deepseek-ai/dsh-mcp-client'\n  config:\n    serverName: memory\n    transport: stdio\n    command: node\n    args:\n      - '<安装路径>/dist/index.js'   # 或全局安装后：[\"npx\", \"memory-mcp\"]\n    cwd: '<项目根>'                  # 记忆库落在这里的 memory/ 下\n    toolCallTimeoutMs: 120000\n    failOnStartupError: true\n```\n\n### 作为 DSH 插件安装（推荐，0.9.2+）\n\n本包自带 DSH bundle 声明（`dsh.bundle.patch`），可省去手写整段接入配置：\n\n```bash\nnpm i -g pnpm                        # dsh plugin 依赖 pnpm（一次性）\ndsh plugin --profile web add @bingo_touth/memory-mcp-server\n```\n\n安装后 bundle 已注册 `mcp-memory` 行（默认 `MEMORY_SKIP_INJECT=1`、`cwd`=DSH 启动目录、`failOnStartupError=false` 不阻断启动）。**唯一要做的**：把服务器绝对路径换成你的——在你自己的 `~/.dsh/profiles/<profile>/cordis.patch.yml` 里用同 id 覆盖（用户层覆盖 bundle 层）：\n\n```yaml\n- id: mcp-memory\n  name: '@deepseek-ai/dsh-mcp-client'\n  config:\n    serverName: memory\n    transport: stdio\n    command: node\n    args: ['C:/<你的绝对路径>/dist/index.js']   # npm i -g 后可用 `npm root -g` 查\n    cwd: '<你的项目根>'                          # 记忆库落在这里的 memory/ 下\n    toolCallTimeoutMs: 120000\n    failOnStartupError: true\n```\n\n> 为什么不能全自动：DSH 以 `shell:false` 启动 MCP 子进程，Windows 上 `npx`/`.cmd` 直启不可用（实测 ENOENT/EINVAL），必须 `node + 绝对路径`，而绝对路径只有你本机知道——所以保留这一行替换。\n>\n> 卸载：`dsh plugin --profile web remove @bingo_touth/memory-mcp-server`。\n\n### Claude Code：项目根的 `.mcp.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"memory\": {\n      \"type\": \"stdio\",\n      \"command\": \"node\",\n      \"args\": [\"<安装路径>/dist/index.js\"],\n      \"env\": {}\n    }\n  }\n}\n```\n\n或直接给 Claude Code 文件已安装的路径，让其智能注册，然后重启 Claude Code。\n\n> **发布友好开关**：服务器启动时会向 CWD 项目的 harness 规则文件（AGENTS.md 等）注入「记忆使用规范」。对他人机器这是侵入性行为——设 `MEMORY_SKIP_INJECT=1`（或 `true`/`yes`）可跳过；本机不设则保留现状。\n\n---\n\n## ⚠ Embedding 模型:首次运行需要它,离线环境要手动放\n\n语义检索默认用 `Xenova/paraphrase-multilingual-MiniLM-L12-v2`(quantized,约 118MB,多语言，中文检索排序正确)。**联网**时 transformers.js 首次运行会自动下载到:\n\n```\nnode_modules/@xenova/transformers/.cache/Xenova/paraphrase-multilingual-MiniLM-L12-v2/\n```\n\n> 想换模型：设环境变量 `MEMORY_EMBED_MODEL=<repo/model>` 即可覆盖默认（见 `src/embedding/provider.ts` 的 `MODEL_ID`）。若换成非 384 维的模型，务必回填历史片段（见下文），新旧维度/模型的向量不可混用。\n>\n> 早期版本用的是 `Xenova/all-MiniLM-L6-v2`(英文模型,约 23MB)——它对中文语义排序会**倒挂**(无关闲聊的 cosine 会压过正确答案),已弃用。\n\n**如果网络访问 huggingface.co 受阻**(常见于国内/隔离网络),自动下载会以 `TypeError: fetch failed` 失败,服务器会退回关键词检索(召回质量明显下降)。此时**手动放置模型**即可,用镜像下载:\n\n```bash\nBASE=\"https://hf-mirror.com/Xenova/paraphrase-multilingual-MiniLM-L12-v2/resolve/main\"\nDEST=\"node_modules/@xenova/transformers/.cache/Xenova/paraphrase-multilingual-MiniLM-L12-v2\"\nmkdir -p \"$DEST/onnx\"\ncurl -sL \"$BASE/config.json\"           -o \"$DEST/config.json\"\ncurl -sL \"$BASE/tokenizer.json\"        -o \"$DEST/tokenizer.json\"\ncurl -sL \"$BASE/tokenizer_config.json\" -o \"$DEST/tokenizer_config.json\"\ncurl -sL \"$BASE/onnx/model_quantized.onnx\" -o \"$DEST/onnx/model_quantized.onnx\"\n```\n\n验证离线可加载:\n\n```bash\nnode --input-type=module -e '\nimport { pipeline, env } from \"@xenova/transformers\";\nenv.allowRemoteModels = false;   // 强制只用本地缓存\nconst ex = await pipeline(\"feature-extraction\",\"Xenova/paraphrase-multilingual-MiniLM-L12-v2\",{quantized:true});\nconst r = await ex(\"你好\",{pooling:\"mean\",normalize:true});\nconsole.log(\"OK dim=\", r.data.length);   // 期望 384\n'\n```\n\n放好后**重启 MCP 服务器**(常驻进程,不热更新;在 Claude Code 里即重启客户端)。\n\n### 怎么判断当前跑在哪种模式\n\n看服务器 **stderr** 与 `create_fragment` 返回的 `embedding_mode` 字段(取值为 `api` / `transformers` / `fallback`):\n\n- `embedding_mode: \"api\"` → 走 OpenAI 兼容嵌入 API。\n- `embedding_mode: \"transformers\"` → 本地 MiniLM 语义模式正常。\n- `embedding_mode: \"fallback\"` → 模型没加载 / API 不可用,在用关键词检索,按上面步骤修。\n- `memory_search` 返回分数普遍在 **0.2+**(且同义改写也能命中)→ 语义模式正常。\n\n---\n\n## 嵌入模型 API 后端(可选,免下载本地模型)\n\n不想下载/运行本地 384 维模型时,设 `MEMORY_EMBED_PROVIDER=api` 即可切到 OpenAI 兼容的 `/v1/embeddings`(覆盖 OpenAI、智谱、通义、月之暗面、Ollama、PPInfra 等):\n\n```bash\nMEMORY_EMBED_PROVIDER=api\nMEMORY_EMBED_API_URL=https://api.openai.com/v1   # 必填,含 /v1 的 base URL\nMEMORY_EMBED_API_KEY=sk-xxxx                     # 必填\nMEMORY_EMBED_API_MODEL=text-embedding-3-small    # 可选,默认这个\nMEMORY_EMBED_API_MAX_TOKENS=8191                 # 可选,文档预算上限\nMEMORY_EMBED_API_DIM=1536                        # 可选,固定维度;缺省则首次编码自动探测\nMEMORY_EMBED_API_MAX_RETRIES=4                   # 可选,429/5xx/网络异常的退避重试次数\nMEMORY_EMBED_API_RETRY_BASE_MS=2000              # 可选,重试退避基数(指数增长,上限 60s)\nMEMORY_EMBED_API_DELAY_MS=0                      # 可选,相邻请求最小间隔;严格限流档(如 5/min)设 12000+\n```\n\n要点:\n\n- **API 模式不做本地分词**:文档预算截断用字符近似计数(`tokenizer_id = char-approx-v1`),不下载任何模型文件。\n- **API 模型与本地 MiniLM 的向量不可混用**:切换模型后 `representation_identity_hash` 变化,必须 `migrate_embeddings.mjs build/validate/switch` 重建;建议用 `--representation single`(multiview 证据门阈值是按 MiniLM 384 校准的,不随 API 迁移)。\n- **失败语义分层**:检索路径(编码失败)快速回退关键词,不等待重试;构建/迁移路径严格失败,绝不出半成品向量。429/5xx/网络异常自动指数退避重试(优先 `Retry-After` 头)。\n- **免费档限流**:如 PPInfra 免费档 5 请求/分钟,建库必须配 `MEMORY_EMBED_API_DELAY_MS=12000+`(76 片段 ≈ 16 分钟)。\n\n---\n\n## 回填历史片段\n\n如果某段时间跑在降级模式,那期间的片段没有向量(或为空),且**当前存在 active embedding generation 时不能直接运行旧回填脚本**。D0 会保护性拒绝对 active generation 的写入，避免把不可变快照当作可写目录。\n\n```bash\ncd <记忆库所在的项目根>          # 必须,存储根相对 CWD\nnode <绝对路径>/backfill_embeddings.mjs\n```\n\n脚本仅在没有 active generation 时回填 legacy `.embedding`；如果检测到 active generation，会以非零状态退出并提示使用：\n\n```bash\nnode <绝对路径>/migrate_embeddings.mjs build --generation gen_YYYYMMDD_xxx\nnode <绝对路径>/migrate_embeddings.mjs validate --generation gen_YYYYMMDD_xxx\nnode <绝对路径>/migrate_embeddings.mjs switch --generation gen_YYYYMMDD_xxx\n```\n\n当前简化模型下，服务器启动不会自动做 orphan reconcile 或后台修复；如果你怀疑 delta/base 状态不一致，直接走手动 rebuild + switch。\n\n## Multiview evidence calibration（离线维护者流程）\n\n多窗口 evidence gate 只允许使用通过 development 与 hold-out 验证的、版本化 fixture calibration artifact；不能把 `src/search/retriever.ts` 中的旧候选阈值当作 production policy。评测工具只读取 `bench/datasets/`，不会读取或修改任何 `memory/` root；它不切 active pointer，也不生成真实 generation。\n\n```bash\nnode bench/run-multiview-eval.mjs calibrate \\\n  --max-fpr 0 \\\n  --min-evidence-recall 1 \\\n  --output <candidate-report.json>\n\n# 从 candidate-report.json 提取 candidate_artifact 后，使用 untouched hold-out：\nnode bench/run-multiview-eval.mjs validate \\\n  --artifact <candidate-artifact.json> \\\n  --output <holdout-report.json>\n\nnode bench/run-multiview-eval.mjs evaluate \\\n  --threshold <validated-threshold> \\\n  --output <shadow-report.json>\n```\n\n`validate` 只有在 hold-out 满足冻结目标时才会输出 `validated` artifact；失败时报告 `no_go`，不得手动把 candidate 标为 validated。artifact 绑定 model/tokenizer、recipe、窗口策略、aggregation/raw-similarity mode、development/hold-out dataset hash 和 canonical artifact hash。\n\n新的 multiview generation、activation、delta 写入与 compaction 都必须携带并校验该 immutable validated snapshot；compaction 的 artifact 还必须与 active generation 的 snapshot 完全一致。历史 policy-less multiview generation 仍可读取，并在 search 中保持 summary-only shadow；它们不能重新激活或创建/重置/写入 delta。\n\n本项目采用简单、手动维护优先的落地策略，不把大规模生产级 calibration、长时间 shadow observation 或复杂自动运维作为首次启用的前置条件。真实库首次启用时只需在维护窗口完成 multiview build → validate → switch，保留旧 generation，并用少量真实查询做 sanity check；必要时手动回切旧 generation。fixture artifact 不能冒充真实生产阈值，但不再阻塞首次使用。\n\n## Compaction 日常维护流程（手动维护）\n\n日常写入走 **delta 增量层**（generation 是不可变快照，写入只更新 `memory/embedding_delta/`）。delta 条目数 D 增长后：① 每次 `create_fragment` 重写 `delta_index.json` 的写放大 ≈ O(D²)；② 检索多一层校验。**compaction** 把 base + delta 合并进一个全新 generation 并清空 delta（两层变一层）。\n\n**什么时候做**：delta 条目数（`memory/embedding_delta/delta_index.json` 的键数）≥ 100~300、`create_fragment`/`memory_search` 明显变慢、或按使用强度定期（如每月/每 200 片段）。**全程在维护窗口执行，先备份 memory 根**。\n\n```bash\ncd <记忆库所在的项目根>          # 存储根相对 CWD，必须\nnode <绝对路径>/compact_embeddings.mjs preflight --generation gen_YYYYMMDD_compaction --representation multiview --evidence-policy <validated-artifact.json>\nnode <绝对路径>/compact_embeddings.mjs build --generation gen_YYYYMMDD_compaction\nnode <绝对路径>/compact_embeddings.mjs validate --generation gen_YYYYMMDD_compaction\nnode <绝对路径>/compact_embeddings.mjs switch --generation gen_YYYYMMDD_compaction\n```\n\n- `--representation` 必须与当前 active generation 一致；multiview 时必须携带 **validated** evidence policy（`run-multiview-eval.mjs validate` 产出，candidate 不可用）。\n- preflight 会**上 compaction 锁 + 封存 delta + 写 merge contract**；validate 不通过**不得 switch**；异常中断先用 `compact_embeddings.mjs unlock` 确认解锁，不要把 unlock 当通用恢复手段。\n- switch 后旧 generation 保留在 `previous_generation_id`，可手动回切。\n- 换模型/换表示请用 `migrate_embeddings.mjs`，不要用 compaction 顶替。\n- 详细判定信号、故障处理与操作前检查清单见《项目维护/memory-mcp-server_compaction维护手册_20260809.md》；archive 恢复场景见下一节。\n\n## Compaction archive recovery（维护者手动流程）\n\n此流程只用于恢复一个 **C3-3B v2 compaction archive**：把 archive 中的 sealed delta 和记录的 base active pointer 原样恢复。它不是通用 JSON 修复、`migrate_embeddings.mjs` 的 rollback、orphan reconcile，也不是面向日常用户的操作。\n\n当前没有公开的 restore CLI 或 MCP tool；仅维护者可在受控环境中调用内部 API：`verifyArchivedDelta(archivePath)`、`restoreArchivedDelta(archivePath)`、`recoverDeltaRestoreTransaction()`。**不要**手动复制 archive 文件、改写 `embedding_active.json`、删除 transaction，或把 `compact_embeddings.mjs unlock` 当作通用恢复手段。\n\n恢复前按顺序完成：\n\n1. 停止 MCP server 和全部写入方，记录绝对 memory root、候选 archive 路径、当前 active pointer、delta manifest/index 摘要、compaction lock，以及 `memory/embedding_delta/transactions/restore-*` 目录。\n2. 对整个 memory root 做独立的字节级备份；恢复流程不会替代这一份操作前备份。\n3. 只选择 `memory/embedding_delta/archive/<delta-id>-into-<target-generation-id>/` 下的 archive。它必须包含 `merge_receipt.json`、`merge_contract.json`、`manifest.json`、`delta_index.json`；有 materialized record 时还必须有对应 `vectors/` payload。\n4. 先执行 `verifyArchivedDelta(archivePath)`，只有返回 `valid: true` 才能继续。v1 receipt、任意 payload/receipt/contract/pointer 校验失败都必须停止，不能尝试“修好” archive 后继续。\n5. `restoreArchivedDelta(archivePath)` 会再次拒绝 source inventory 漂移、active pointer 不等于 receipt target pointer、非空的 post-compaction target delta、或已有未完成 restore transaction。满足条件后它才会恢复 archive 的 sealed delta，并最后写入 receipt base pointer。\n6. 成功后确认：active pointer 等于 `receipt.pointer_snapshots.base`；live delta 的 ID/payload 等于 archive、状态为 `sealed`、兼容性正常；target generation 与 archive 均仍存在；没有遗留 `restore-*` transaction。\n\n正常调用返回 `{ restored: true, idempotent: false }`；若已经完全处于 archive 记录的 base+sealed-delta 状态，会返回 `{ restored: false, idempotent: true }`。若出现 `recovery_failed: true`，保留其 `transaction_path`、archive、pointer/manifest 快照和错误输出，**不要重跑 restore 或手动清理**；由维护者先调用一次 `recoverDeltaRestoreTransaction()`。多个 restore transaction、未知 transaction schema、archive 验证失败或 recovery 再次失败都属于停止并人工检查的条件，不能 force-unlock。\n\n当没有有效 archive、source 已变化或 pointer 状态不满足恢复前提时，走受控 rebuild：\n\n```bash\nnode <绝对路径>/migrate_embeddings.mjs build --generation gen_YYYYMMDD_xxx\nnode <绝对路径>/migrate_embeddings.mjs validate --generation gen_YYYYMMDD_xxx\nnode <绝对路径>/migrate_embeddings.mjs switch --generation gen_YYYYMMDD_xxx\n```\n\n对真实 memory root 的复制副本演练、自动启动恢复、公开 restore CLI 和 MCP restore tool 都是后续独立授权事项；本文档不启用它们。\n\n---\n\n## MCP 工具一览\n\n| 工具 | 作用 |\n|---|---|\n| `memory_store_turn` | 追加一轮对话到 raw(全量原文) |\n| `memory_create_fragment` | 把若干轮打包成 L1 片段,自动算 embedding |\n| `memory_create_daily_summary` | 写 L2 每日总结 |\n| `memory_upsert_topic` | 创建/更新 L3 跨天主题索引 |\n| `memory_search` | 语义检索 → 命中 L1 并回填 L2/L3 上下文 |\n| `memory_get_fragment` / `memory_get_daily` / `memory_get_topic` | 按 ID 读取完整内容 |\n| `memory_list_dates` | 列出所有有记录的日期 |\n| `memory_get_raw_turns` | 按 exact/range/recent/all 四种互斥模式读取 L0 逐轮原文，可先按 `agent_id` 过滤 |\n| `memory_consolidate_topics` | 检测中文相似 Topic；经审阅后支持 dry-run、整批预检、执行合并与 fragment 回指修复 |\n\n### Topic 合并说明\n\n`memory_consolidate_topics(action=\"execute\")` 会先做整批校验。任一 active 合并组存在 source/target 冲突、非法 fragment ID、路径越界、fragment 缺失或旧 Topic 回指不唯一时，整批返回 `validated: false` 和 MCP `isError: true`，不会改写 live 文件。\n\n`dry_run: true` 使用与正式执行相同的计划和预检，只返回 `changes`，不写文件。正式执行会更新 target、改写 fragment 回指，并把 source 主题备份到 `.trash` 后删除。\n\n这是面向个人项目的简化维护模型：优先保证行为直白、出问题后可人工检查；不承诺工业级自动恢复或复杂维护编排。\n\n---\n\n## 和宿主自带记忆的分工(避免双写)\n\n很多 Agent 宿主(如 Claude Code)自身已有一套\"始终加载进上下文\"的轻量记忆。本 MCP 与它**职责不同,不要重复存**:\n\n- **宿主自带记忆** = 蒸馏后的常驻规则/偏好,需要**每个会话都在上下文里**、无需检索。少而精,一条一行。\n- **本 MCP** = 可检索的**情节档案**:完整对话、任务片段、每日/主题脉络。**按需 `memory_search` 取用**,不常驻。\n\n一条经验值得记时问自己:*它需要每个会话都在场,还是只在我去翻的时候才要?* 前者进宿主记忆(一行),后者进本 MCP(带证据的片段)。宿主里的那一行可以引用 MCP 的主题名做下钻,但不要复制正文。\n\n---\n\n## 仓库卫生\n\n`memory/` 里是**原始对话逐字记录**。若把本服务器的记忆库放在某个 git 项目内,记得在该项目 `.gitignore` 忽略它,别把对话原文和向量提交进版本库:\n\n```gitignore\n/memory/\n```\n\n---\n\n## 记忆重要性评分\n\n新建 fragment 时请保守填写 `importance`，不要把普通记忆默认评为 0.7 以上：\n\n- `0.35~0.4`：临时、局部、低复用信息\n- `0.5`：普通可复用记忆\n- `0.6~0.7`：持续有帮助或明确重要\n- `0.8`：关键架构、重要约束\n- `0.9~1.0`：核心事实，错误代价高，应该很少使用\n\n历史 fragment 的 importance 不因这次规则调整而批量改写。P3 Phase 1c 检索时使用 `max(importance, earned_importance)`，earned 只提升有效重要性，不会降低已有权重。\n\n## 已知取舍\n\n- MiniLM 的相似度整体偏低,**0.2–0.35 就是可靠命中**,不要按 0.8 的直觉设阈值。\n- 检索质量高度依赖**写入方**给的 `task_desc`/`result_desc`/片段浓缩质量——工具负责结构与召回,浓缩得好不好看用的人。\n- embedding 文本 = `task_desc + result_desc + turns_text`(查询多针对结论,纳入后召回更准)。\n\n## 开发\n\n```bash\nnpm run dev      # tsx 直跑 src/index.ts\nnpm run check    # tsc --noEmit 类型检查\nnpm run watch    # 文件监听(如启用 watcher)\n```\n","readmeFilename":"README.md"}