🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

分层记忆库 BingoAgentTouch/Personal_MCP

MCP
BingoAgentTouch75 天前有提交已提供中文文档扫描:高危兼容 / 相关生态

把对话沉淀成三层可检索的长期记忆

29.5/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/19 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/BingoAgentTouch/Personal_MCP.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
生态插件
可安装,未声明 dsh 能力
暂无时间戳·判据 →
装得上吗[实装验证]—
静态安装检查有提示项,装前建议看一眼 README
数据截至 2026/09/25·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/06·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 75 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包@bingo_touth/memory-mcp-server(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/22 05:59:16

🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0
🔴 扫描:高危尚无人工评估

静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。

命令参数由运行时变量拼接读写/删除本地文件
查看扫描证据(共 40 处,展示前 37 条)
  • 读取本地文件
    analyze_signals.mjs:149
    if (!fs.existsSync(filePath)) return { name, filePath, content: "", rows: [], invalidLines: [] };
  • 读取本地文件
    analyze_signals.mjs:150
    const content = fs.readFileSync(filePath, "utf8");
  • 读取本地文件
    analyze_signals.mjs:404
    if (!fs.existsSync(filePath)) {
  • 读取本地文件
    analyze_signals.mjs:408
    const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
  • 写入本地文件
    analyze_signals.mjs:481
    fs.mkdirSync(path.dirname(filePath), { recursive: true });
  • 写入本地文件
    analyze_signals.mjs:483
    fs.writeFileSync(tempPath, content, "utf8");
  • 写入本地文件
    analyze_signals.mjs:484
    fs.renameSync(tempPath, filePath);
  • 读取本地文件
    analyze_signals.mjs:488
    if (!fs.existsSync(ledgerPath)) return [];
  • 读取本地文件
    analyze_signals.mjs:490
    for (const [index, line] of fs.readFileSync(ledgerPath, "utf8").split(/ ? /).entries()) {
  • 写入本地文件
    analyze_signals.mjs:504
    fs.mkdirSync(path.dirname(ledgerPath), { recursive: true });
  • 写入本地文件
    analyze_signals.mjs:505
    fs.appendFileSync(ledgerPath, `${JSON.stringify(entry)}\n`, "utf8");
  • 写入本地文件
    backfill_embeddings.mjs:39
    fs.writeFileSync(embeddingPath(date, id), JSON.stringify(vec), "utf-8");
  • 读取本地文件
    backfill_meta.mjs:19
    if (fs.existsSync(metaPath(date, id))) {
  • 读取本地文件
    compact_embeddings.mjs:54
    if (!fs.existsSync(filePath)) return null;
  • 读取本地文件
    compact_embeddings.mjs:55
    return JSON.parse(fs.readFileSync(filePath, "utf8"));
  • 写入本地文件
    compact_embeddings.mjs:83
    fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
  • 执行外部命令运行时拼接
    dump_schema.mjs:9
    const out = execSync(`sqlite3 "${dbPath}" ".tables"`, { encoding: "utf-8", timeout: 5000 });
  • 写入本地文件
    dump_schema.mjs:10
    fs.writeFileSync(outPath, "=== Tables ===\n" + out + "\n\n=== Schema ===\n");
  • 执行外部命令运行时拼接
    dump_schema.mjs:13
    const schema = execSync(`sqlite3 "${dbPath}" ".schema"`, { encoding: "utf-8", timeout: 5000 });
  • 写入本地文件
    dump_schema.mjs:14
    fs.appendFileSync(outPath, schema);
  • 执行外部命令运行时拼接
    dump_schema.mjs:21
    const sample = execSync(`sqlite3 "${dbPath}" "SELECT * FROM \\"${table}\\" LIMIT 3;"`, { encoding: "utf-8", timeout: 5000 });
  • 写入本地文件
    dump_schema.mjs:22
    fs.appendFileSync(outPath, `\n=== ${table} (3 rows) ===\n${sample}\n`);
  • 读取本地文件
    dump_schema.mjs:31
    const buf = fs.readFileSync(dbPath);
  • 写入本地文件
    dump_schema.mjs:43
    fs.writeFileSync(outPath, results.join("\n\n---\n\n"));
  • 写入本地文件
    dump_schema.mjs:54
    fs.writeFileSync(outPath, `=== Exploring ${dir} ===\n\n`);
  • 读取本地文件
    dump_schema.mjs:55
    const entries = fs.readdirSync(dir, { withFileTypes: true, recursive: true });
  • 写入本地文件
    dump_schema.mjs:59
    fs.appendFileSync(outPath, fullPath + "\n");
  • 写入本地文件
    migrate_embeddings.mjs:33
    fs.mkdirSync(path.dirname(file), { recursive: true });
  • 写入本地文件
    migrate_embeddings.mjs:35
    fs.writeFileSync(tmp, content, "utf8");
  • 写入本地文件
    migrate_embeddings.mjs:36
    fs.renameSync(tmp, file);
  • 读取本地文件
    migrate_embeddings.mjs:87
    function readJson(file) { return JSON.parse(fs.readFileSync(file, "utf8")); }
  • 读取本地文件
    migrate_embeddings.mjs:236
    if (!fs.existsSync(pointerPath)) throw new Error("active pointer not found");
  • 读取本地文件
    query_db.mjs:10
    if (!fs.existsSync(sqlJsPath)) {
  • 执行外部命令固定命令
    query_db.mjs:12
    execSync("cd D:/AgentStore/memory-mcp-server && npm install sql.js", { stdio: "inherit" });
  • 读取本地文件
    query_db.mjs:19
    const buf = fs.readFileSync(dbPath);
  • 写入本地文件
    query_db.mjs:90
    fs.writeFileSync(outPath, output);
  • 执行外部命令来自配置/变量
    relay.mjs:16
    const child = spawn(process.execPath, [TSX_CLI, MCP_SCRIPT], {
扫描于 2026/11/6(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 存放MCP服务
  • 对话沉淀为长期记忆
  • 三层可检索记忆

这是一个用来存放个人搭建的MCP服务的仓库

README

由 DeepSeek 最新模型翻译生成
memory-mcp-server 一个给 LLM Agent(如 Claude Code)用的分层长期记忆 MCP 服务器。把对话沉淀成可语义检索的三层记忆,回答"我们上次聊到哪了"时能带出完整上下文。 当前版本:0.9.1 - 本地优先,可选 API:默认用本地 @xenova/transformers(多语言 MiniLM,384 维,零云依赖);也可切换到 OpenAI 兼容嵌入 API(MEMORY_EMBED_PROVIDER=api,免下载本地模型,见下文)。 - 分层回溯:命中片段(L1)时自动回填当天总结(L2)和主题脉络(L3)。 - 优雅降级:本地模型加载失败或 API 不可用时退回关键词(Jaccard)检索,并在 stderr 明确告警——不会假装正常。
展开完整文档(README 剩余 1 节)
memory-mcp-server

一个给 LLM Agent(如 Claude Code)用的分层长期记忆 MCP 服务器。把对话沉淀成可语义检索的三层记忆,回答"我们上次聊到哪了"时能带出完整上下文。

当前版本:0.9.1

- 本地优先,可选 API:默认用本地 @xenova/transformers(多语言 MiniLM,384 维,零云依赖);也可切换到 OpenAI 兼容嵌入 API(MEMORY_EMBED_PROVIDER=api,免下载本地模型,见下文)。
- 分层回溯:命中片段(L1)时自动回填当天总结(L2)和主题脉络(L3)。
- 优雅降级:本地模型加载失败或 API 不可用时退回关键词(Jaccard)检索,并在 stderr 明确告警——不会假装正常。

记忆分层

memory/ # 存储根,相对「服务器进程的工作目录(CWD)」 ├── raw//turns.jsonl # 原始对话,一字不改,全量保留 ├── fragments// # L1 任务→结果片段 (.md + .embedding 向量) ├── daily/.md # L2 每日总结 └── topics/.md # L3 跨天主题索引

写入顺序:store_turn(逐轮) → create_fragment(打包几轮为一个片段,自动算 embedding) → create_daily_summary / upsert_topic(汇总)。

重要:存储根是相对 CWD 的(path.resolve("memory/..."))。服务器进程以哪个目录为工作目录,记忆就写在那个目录的 memory/ 下。让宿主(Claude Code 等)以「你想要记忆的项目根」为 CWD 启动本服务器。

安装 & 构建

下载安装到某个路径

npm install
npm run build # tsc → dist/
(注意,CherryStudio用户可能由于该GUI的路径问题或管道问题无法直接使用,请谨慎安装)

要求 Node ≥ 20(开发用 22 验证)。

从 npm 安装

npm install -g @bingo_touth/memory-mcp-server # 全局安装
memory-mcp # 直接以 stdio 启动或临时运行:npx @bingo_touth/memory-mcp-server

本包发布名:@bingo_touth/memory-mcp-server(npm 裸名 memory-mcp-server / memory-mcp 均已被他人占用,故用 scoped 名)。

各 harness 接入片段(参数化)

数据根约定(最重要):记忆库存储在服务器进程 CWD 下的 memory/ 目录。以你想让记忆归属的项目根作为 cwd 启动——下面两个配置的 cwd 字段都是关键。

DeepSeek Harness(DSH):~/.dsh/profiles//cordis.patch.yml

- id: mcp-memory
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: memory
transport: stdio
command: node
args:
- '/dist/index.js' # 或全局安装后:["npx", "memory-mcp"] cwd: '' # 记忆库落在这里的 memory/ 下 toolCallTimeoutMs: 120000 failOnStartupError: true

作为 DSH 插件安装(推荐,0.9.2+)

本包自带 DSH bundle 声明(dsh.bundle.patch),可省去手写整段接入配置:

npm i -g pnpm # dsh plugin 依赖 pnpm(一次性)
dsh plugin --profile web add @bingo_touth/memory-mcp-server

pnpm 10 提示 ERR_PNPM_IGNORED_BUILDS(Ignored build scripts: protobufjs, sharp)时:这是 pnpm 10 默认拦截依赖构建脚本,会让 dsh plugin add 以非零退出、登记不生效。文本嵌入用不到这两个构建产物——编辑 ~/.dsh/profiles/web/pnpm-workspace.yaml(pnpm 已自动写好占位符),把 protobufjs / sharp 的 allowBuilds 置为 false,然后重跑一次 dsh plugin add 即可。

安装后 bundle 已注册 mcp-memory 行(默认 MEMORY_SKIP_INJECT=1、cwd=DSH 启动目录、failOnStartupError=false 不阻断启动)。唯一要做的:把服务器绝对路径换成你的——在你自己的 ~/.dsh/profiles//cordis.patch.yml 里用同 id 覆盖(用户层覆盖 bundle 层):

- id: mcp-memory
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: memory
transport: stdio
command: node
args: ['C://dist/index.js'] # npm i -g 后可用 npm root -g 查
cwd: '' # 记忆库落在这里的 memory/ 下 toolCallTimeoutMs: 120000 failOnStartupError: true 为什么不能全自动:DSH 以 shell:false 启动 MCP 子进程,Windows 上 npx/.cmd 直启不可用(实测 ENOENT/EINVAL),必须 node + 绝对路径,而绝对路径只有你本机知道——所以保留这一行替换。

⚠️ 覆盖行必须是上面的普通 - id: 形式,不要再用 - insert: 包同一个 id——bundle 已插入该行,再 insert 会产生重复条目,DSH 启动直接报错 duplicate loader entry id: mcp-memory(实测踩坑)。卸载插件后这一行会因找不到条目而自动跳过(告警无害)。

卸载:dsh plugin --profile web remove @bingo_touth/memory-mcp-server。

Claude Code:项目根的 .mcp.json

{
"mcpServers": {
"memory": {
"type": "stdio",
"command": "node",
"args": ["/dist/index.js"],
"env": {}
}
}
}

或直接给 Claude Code 文件已安装的路径,让其智能注册,然后重启 Claude Code。

发布友好开关:服务器启动时会向 CWD 项目的 harness 规则文件(AGENTS.md 等)注入「记忆使用规范」。对他人机器这是侵入性行为——设 MEMORY_SKIP_INJECT=1(或 true/yes)可跳过;本机不设则保留现状。

⚠ Embedding 模型:首次运行需要它,离线环境要手动放

语义检索默认用 Xenova/paraphrase-multilingual-MiniLM-L12-v2(quantized,约 118MB,多语言,中文检索排序正确)。联网时 transformers.js 首次运行会自动下载到:

node_modules/@xenova/transformers/.cache/Xenova/paraphrase-multilingual-MiniLM-L12-v2/

想换模型:设环境变量 MEMORY_EMBED_MODEL= 即可覆盖默认(见 src/embedding/provider.ts 的 MODEL_ID)。若换成非 384 维的模型,务必回填历史片段(见下文),新旧维度/模型的向量不可混用。

早期版本用的是 Xenova/all-MiniLM-L6-v2(英文模型,约 23MB)——它对中文语义排序会倒挂(无关闲聊的 cosine 会压过正确答案),已弃用。

如果网络访问 huggingface.co 受阻(常见于国内/隔离网络),自动下载会以 TypeError: fetch failed 失败,服务器会退回关键词检索(召回质量明显下降)。此时手动放置模型即可,用镜像下载:

BASE="https://hf-mirror.com/Xenova/paraphrase-multilingual-MiniLM-L12-v2/resolve/main"
DEST="node_modules/@xenova/transformers/.cache/Xenova/paraphrase-multilingual-MiniLM-L12-v2"
mkdir -p "$DEST/onnx"
curl -sL "$BASE/config.json" -o "$DEST/config.json"
curl -sL "$BASE/tokenizer.json" -o "$DEST/tokenizer.json"
curl -sL "$BASE/tokenizer_config.json" -o "$DEST/tokenizer_config.json"
curl -sL "$BASE/onnx/model_quantized.onnx" -o "$DEST/onnx/model_quantized.onnx"

验证离线可加载:

node --input-type=module -e '
import { pipeline, env } from "@xenova/transformers";
env.allowRemoteModels = false; // 强制只用本地缓存
const ex = await pipeline("feature-extraction","Xenova/paraphrase-multilingual-MiniLM-L12-v2",{quantized:true});
const r = await ex("你好",{pooling:"mean",normalize:true});
console.log("OK dim=", r.data.length); // 期望 384
'

放好后重启 MCP 服务器(常驻进程,不热更新;在 Claude Code 里即重启客户端)。

怎么判断当前跑在哪种模式

看服务器 stderr 与 create_fragment 返回的 embedding_mode 字段(取值为 api / transformers / fallback):

- embedding_mode: "api" → 走 OpenAI 兼容嵌入 API。
- embedding_mode: "transformers" → 本地 MiniLM 语义模式正常。
- embedding_mode: "fallback" → 模型没加载 / API 不可用,在用关键词检索,按上面步骤修。
- memory_search 返回分数普遍在 0.2+(且同义改写也能命中)→ 语义模式正常。

嵌入模型 API 后端(可选,免下载本地模型)

不想下载/运行本地 384 维模型时,设 MEMORY_EMBED_PROVIDER=api 即可切到 OpenAI 兼容的 /v1/embeddings(覆盖 OpenAI、智谱、通义、月之暗面、Ollama、PPInfra 等):

MEMORY_EMBED_PROVIDER=api
MEMORY_EMBED_API_URL=https://api.openai.com/v1 # 必填,含 /v1 的 base URL
MEMORY_EMBED_API_KEY=sk-xxxx # 必填
MEMORY_EMBED_API_MODEL=text-embedding-3-small # 可选,默认这个
MEMORY_EMBED_API_MAX_TOKENS=8191 # 可选,文档预算上限
MEMORY_EMBED_API_DIM=1536 # 可选,固定维度;缺省则首次编码自动探测
MEMORY_EMBED_API_MAX_RETRIES=4 # 可选,429/5xx/网络异常的退避重试次数
MEMORY_EMBED_API_RETRY_BASE_MS=2000 # 可选,重试退避基数(指数增长,上限 60s)
MEMORY_EMBED_API_DELAY_MS=0 # 可选,相邻请求最小间隔;严格限流档(如 5/min)设 12000+

要点:

- API 模式不做本地分词:文档预算截断用字符近似计数(tokenizer_id = char-approx-v1),不下载任何模型文件。
- API 模型与本地 MiniLM 的向量不可混用:切换模型后 representation_identity_hash 变化,必须 migrate_embeddings.mjs build/validate/switch 重建;建议用 --representation single(multiview 证据门阈值是按 MiniLM 384 校准的,不随 API 迁移)。
- 失败语义分层:检索路径(编码失败)快速回退关键词,不等待重试;构建/迁移路径严格失败,绝不出半成品向量。429/5xx/网络异常自动指数退避重试(优先 Retry-After 头)。
- 免费档限流:如 PPInfra 免费档 5 请求/分钟,建库必须配 MEMORY_EMBED_API_DELAY_MS=12000+(76 片段 ≈ 16 分钟)。

回填历史片段

如果某段时间跑在降级模式,那期间的片段没有向量(或为空),且当前存在 active embedding generation 时不能直接运行旧回填脚本。D0 会保护性拒绝对 active generation 的写入,避免把不可变快照当作可写目录。

cd # 必须,存储根相对 CWD
node /backfill_embeddings.mjs

脚本仅在没有 active generation 时回填 legacy .embedding;如果检测到 active generation,会以非零状态退出并提示使用:

node /migrate_embeddings.mjs build --generation gen_YYYYMMDD_xxx
node /migrate_embeddings.mjs validate --generation gen_YYYYMMDD_xxx
node /migrate_embeddings.mjs switch --generation gen_YYYYMMDD_xxx

当前简化模型下,服务器启动不会自动做 orphan reconcile 或后台修复;如果你怀疑 delta/base 状态不一致,直接走手动 rebuild + switch。

Multiview evidence calibration(离线维护者流程)

多窗口 evidence gate 只允许使用通过 development 与 hold-out 验证的、版本化 fixture calibration artifact;不能把 src/search/retriever.ts 中的旧候选阈值当作 production policy。评测工具只读取 bench/datasets/,不会读取或修改任何 memory/ root;它不切 active pointer,也不生成真实 generation。

node bench/run-multiview-eval.mjs calibrate \
--max-fpr 0 \
--min-evidence-recall 1 \
--output

从 candidate-report.json 提取 candidate_artifact 后,使用 untouched hold-out:
node bench/run-multiview-eval.mjs validate \
--artifact \
--output

node bench/run-multiview-eval.mjs evaluate \
--threshold \
--output

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。

新的 multiview generation、activation、delta 写入与 compaction 都必须携带并校验该 immutable validated snapshot;compaction 的 artifact 还必须与 active generation 的 snapshot 完全一致。历史 policy-less multiview generation 仍可读取,并在 search 中保持 summary-only shadow;它们不能重新激活或创建/重置/写入 delta。

本项目采用简单、手动维护优先的落地策略,不把大规模生产级 calibration、长时间 shadow observation 或复杂自动运维作为首次启用的前置条件。真实库首次启用时只需在维护窗口完成 multiview build → validate → switch,保留旧 generation,并用少量真实查询做 sanity check;必要时手动回切旧 generation。fixture artifact 不能冒充真实生产阈值,但不再阻塞首次使用。
Compaction 日常维护流程(手动维护)

日常写入走 delta 增量层(generation 是不可变快照,写入只更新 memory/embedding_delta/)。delta 条目数 D 增长后:① 每次 create_fragment 重写 delta_index.json 的写放大 ≈ O(D²);② 检索多一层校验。compaction 把 base + delta 合并进一个全新 generation 并清空 delta(两层变一层)。

什么时候做:delta 条目数(memory/embedding_delta/delta_index.json 的键数)≥ 100~300、create_fragment/memory_search 明显变慢、或按使用强度定期(如每月/每 200 片段)。全程在维护窗口执行,先备份 memory 根。

cd # 存储根相对 CWD,必须
node /compact_embeddings.mjs preflight --generation gen_YYYYMMDD_compaction --representation multiview --evidence-policy
node /compact_embeddings.mjs build --generation gen_YYYYMMDD_compaction
node /compact_embeddings.mjs validate --generation gen_YYYYMMDD_compaction
node /compact_embeddings.mjs switch --generation gen_YYYYMMDD_compaction

- --representation 必须与当前 active generation 一致;multiview 时必须携带 validated evidence policy(run-multiview-eval.mjs validate 产出,candidate 不可用)。
- preflight 会上 compaction 锁 + 封存 delta + 写 merge contract;validate 不通过不得 switch;异常中断先用 compact_embeddings.mjs unlock 确认解锁,不要把 unlock 当通用恢复手段。
- switch 后旧 generation 保留在 previous_generation_id,可手动回切。
- 换模型/换表示请用 migrate_embeddings.mjs,不要用 compaction 顶替。
- 详细判定信号、故障处理与操作前检查清单见《项目维护/memory-mcp-server_compaction维护手册_20260809.md》;archive 恢复场景见下一节。

Compaction archive recovery(维护者手动流程)

此流程只用于恢复一个 C3-3B v2 compaction archive:把 archive 中的 sealed delta 和记录的 base active pointer 原样恢复。它不是通用 JSON 修复、migrate_embeddings.mjs 的 rollback、orphan reconcile,也不是面向日常用户的操作。

当前没有公开的 restore CLI 或 MCP tool;仅维护者可在受控环境中调用内部 API:verifyArchivedDelta(archivePath)、restoreArchivedDelta(archivePath)、recoverDeltaRestoreTransaction()。不要手动复制 archive 文件、改写 embedding_active.json、删除 transaction,或把 compact_embeddings.mjs unlock 当作通用恢复手段。

恢复前按顺序完成:

1. 停止 MCP server 和全部写入方,记录绝对 memory root、候选 archive 路径、当前 active pointer、delta manifest/index 摘要、compaction lock,以及 memory/embedding_delta/transactions/restore- 目录。
2. 对整个 memory root 做独立的字节级备份;恢复流程不会替代这一份操作前备份。
3. 只选择 memory/embedding_delta/archive/-into-/ 下的 archive。它必须包含 merge_receipt.json、merge_contract.json、manifest.json、delta_index.json;有 materialized record 时还必须有对应 vectors/ payload。
4. 先执行 verifyArchivedDelta(archivePath),只有返回 valid: true 才能继续。v1 receipt、任意 payload/receipt/contract/pointer 校验失败都必须停止,不能尝试“修好” archive 后继续。
5. restoreArchivedDelta(archivePath) 会再次拒绝 source inventory 漂移、active pointer 不等于 receipt target pointer、非空的 post-compaction target delta、或已有未完成 restore transaction。满足条件后它才会恢复 archive 的 sealed delta,并最后写入 receipt base pointer。
6. 成功后确认:active pointer 等于 receipt.pointer_snapshots.base;live delta 的 ID/payload 等于 archive、状态为 sealed、兼容性正常;target generation 与 archive 均仍存在;没有遗留 restore- transaction。
正常调用返回 { 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。

当没有有效 archive、source 已变化或 pointer 状态不满足恢复前提时,走受控 rebuild:

node /migrate_embeddings.mjs build --generation gen_YYYYMMDD_xxx
node /migrate_embeddings.mjs validate --generation gen_YYYYMMDD_xxx
node /migrate_embeddings.mjs switch --generation gen_YYYYMMDD_xxx

对真实 memory root 的复制副本演练、自动启动恢复、公开 restore CLI 和 MCP restore tool 都是后续独立授权事项;本文档不启用它们。

MCP 工具一览

| 工具 | 作用 |
| memory_store_turn | 追加一轮对话到 raw(全量原文) |
| memory_create_fragment | 把若干轮打包成 L1 片段,自动算 embedding |
| memory_create_daily_summary | 写 L2 每日总结 |
| memory_upsert_topic | 创建/更新 L3 跨天主题索引 |
| memory_search | 语义检索 → 命中 L1 并回填 L2/L3 上下文 |
| memory_get_fragment / memory_get_daily / memory_get_topic | 按 ID 读取完整内容 |
| memory_list_dates | 列出所有有记录的日期 |
| memory_get_raw_turns | 按 exact/range/recent/all 四种互斥模式读取 L0 逐轮原文,可先按 agent_id 过滤 |
| memory_consolidate_topics | 检测中文相似 Topic;经审阅后支持 dry-run、整批预检、执行合并与 fragment 回指修复 |

Topic 合并说明

memory_consolidate_topics(action="execute") 会先做整批校验。任一 active 合并组存在 source/target 冲突、非法 fragment ID、路径越界、fragment 缺失或旧 Topic 回指不唯一时,整批返回 validated: false 和 MCP isError: true,不会改写 live 文件。

dry_run: true 使用与正式执行相同的计划和预检,只返回 changes,不写文件。正式执行会更新 target、改写 fragment 回指,并把 source 主题备份到 .trash 后删除。

这是面向个人项目的简化维护模型:优先保证行为直白、出问题后可人工检查;不承诺工业级自动恢复或复杂维护编排。

和宿主自带记忆的分工(避免双写)

很多 Agent 宿主(如 Claude Code)自身已有一套"始终加载进上下文"的轻量记忆。本 MCP 与它职责不同,不要重复存:

- 宿主自带记忆 = 蒸馏后的常驻规则/偏好,需要每个会话都在上下文里、无需检索。少而精,一条一行。
- 本 MCP = 可检索的情节档案:完整对话、任务片段、每日/主题脉络。按需 memory_search 取用,不常驻。

一条经验值得记时问自己:它需要每个会话都在场,还是只在我去翻的时候才要? 前者进宿主记忆(一行),后者进本 MCP(带证据的片段)。宿主里的那一行可以引用 MCP 的主题名做下钻,但不要复制正文。

仓库卫生

memory/ 里是原始对话逐字记录。若把本服务器的记忆库放在某个 git 项目内,记得在该项目 .gitignore 忽略它,别把对话原文和向量提交进版本库:

/memory/

记忆重要性评分

新建 fragment 时请保守填写 importance,不要把普通记忆默认评为 0.7 以上:

- 0.35~0.4:临时、局部、低复用信息
- 0.5:普通可复用记忆
- 0.6~0.7:持续有帮助或明确重要
- 0.8:关键架构、重要约束
- 0.9~1.0:核心事实,错误代价高,应该很少使用

历史 fragment 的 importance 不因这次规则调整而批量改写。P3 Phase 1c 检索时使用 max(importance, earned_importance),earned 只提升有效重要性,不会降低已有权重。

已知取舍

- MiniLM 的相似度整体偏低,0.2–0.35 就是可靠命中,不要按 0.8 的直觉设阈值。
- 检索质量高度依赖写入方给的 task_desc/result_desc/片段浓缩质量——工具负责结构与召回,浓缩得好不好看用的人。
- embedding 文本 = task_desc + result_desc + turns_text(查询多针对结论,纳入后召回更准)。

开发

npm run dev # tsx 直跑 src/index.ts
npm run check # tsc --noEmit 类型检查
npm run watch # 文件监听(如启用 watcher)
预览分享卡片长什么样 ↓BingoAgentTouch/Personal_MCP
分享 · DeepSeek Harness Hub
BingoAgentTouch/Personal_MCP

把对话沉淀成三层可检索的长期记忆

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部