Skip to main content
Glama

memory-agent

给 agent 用的记忆层:把已有的记忆汇总成一份可快速检索的本地索引,同时给没有记忆系统的 agent 提供一个。

它解决什么

记忆散落在各处 —— 有的 agent 自带记忆系统(各自的 Markdown、JSON、数据库),有的完全没有,关掉会话就忘光。

memory-agent 做两件事:

  1. 汇总 —— 把已有记忆读出来,建成一份本地 SQLite 索引。原文件不动,只读。

  2. 提供 —— 给没有记忆系统的 agent 一套写入 + 检索能力,通过 MCP 或 CLI 接入。

Markdown 是给人看的。但当记忆成百上千条时,模型靠逐个读文件既找不准也找不快 —— 索引解决的正是这一步。汇总与检索全程在本机完成,内容不出网。

Related MCP server: Markdown Memory Context MCP Server

设计承诺

承诺

实现方式

原文件只读

索引端只读取源文件,从不修改、从不删除。真相始终在你自己手里

真相源与索引分离

原格式(Markdown 等)是真相源,SQLite 只是可重建的索引。删库可 index --rebuild 重建

存储区独立于项目

记忆在 ~/.memory_agent(路径可任意指定),代码在仓库。项目更新或程序失误不威胁记忆;重新克隆项目后配好 config.json 即可继续访问

⚠️ 一条如实的例外:访问统计不可重建。 cards(卡片内容 + 全文索引 + priority/ttl)全部能从 Markdown 重新解析出来, 所以删库重建是无损的。但 card_stats 表记录的读取次数与最后读取时间没有第二个来源 —— 它一旦丢失就是永久丢失。这也是 index --rebuild 会清空 cards/cards_fts特意保留 card_stats 的原因(判据不是「表名像不像索引」,而是 能否从真相源重新算出来)。删掉 .db 文件这种损坏下,统计确实会丢。 卡片内容本身不受影响。 | 零运行依赖、内容不出网 | 仅用 Python 标准库;不做任何 LLM 调用,蒸馏交给调用方 agent | | 面向 agent 而非人 | 输出以机器可读为先(--json),不做展示层 |

实现范围

已实现:单源 Markdown 的采集 / 索引 / 检索、MCP 查询端、CLI、检索质量基准。

尚未实现:多源整合(当前只接受一个 vault)、Markdown 以外的格式适配。


架构

agent 会话 ──采集端──> 记忆源(Markdown)──索引端──> SQLite ──查询端──> agent
                        真相源 · 只读            (可重建)      (MCP)

本仓库实现采集端mcore/capture.py)、索引端mcore/importer.py)与 查询端mcore/mcp_server.py),外加检索质量基准bench/retrieval_quality.py)。


路径

数据默认在 ~/.memory_agent,与代码仓库完全分离:

~/.memory_agent/
├── memory.db           索引库
├── config.json         本机配置(不进仓库)
├── bench_queries.json  检索基准真值(含本机卡片路径,不进仓库)
└── vault/              Markdown 卡片(默认位置)

解析优先级:CLI 参数 > 环境变量 > config.json > 默认值。

CLI

环境变量

config.json

数据根

MEMORY_AGENT_HOME

索引库

--db

MEMORY_AGENT_DB

db

vault

--vault

MEMORY_AGENT_VAULT

vault

安装

需要 Python 3.10+,运行期不安装任何第三方依赖

pip install .
memory --help

开发时可安装测试与静态检查工具(只属于开发依赖,不进入运行路径):

pip install -e ".[dev]"
python -m pytest tests/ -q
python -m ruff check .

即使不安装包,也保留从仓库直跑的路径:

python memory.py mcp
python tests/test_mcp.py

接口

python memory.py paths                # 当前生效路径
python memory.py index [--rebuild]    # 同步 / 重建索引
python memory.py search <query>       # 检索
python memory.py capture --title T --body B   # 写入一张卡片
python memory.py stats                # 统计
python memory.py show <id>            # 卡片全文(长卡默认分片,见下)
python memory.py mcp                  # 启动 MCP server

所有命令支持 --json。退出码:0 成功,1 无结果,2 环境错误, 3 标题撞车被拒绝(--on-conflict reject)。

长卡分片读取

卡片会长(蒸馏出来的会话卡常有数千字符),所以取全文的默认带长度上限

python memory.py show 8                      # 默认最多 20000 字符
python memory.py show 8 --offset 20000       # 续读下一页
python memory.py show 8 --max-chars 500      # 自定义窗口
python memory.py show 8 --full               # 不分片,返回完整正文

返回值里有 offset / length / returned / has_more / next_offset, 文本末尾会写明「还有 N 字符未显示」以及续读要用的 next_offset

截断永远显式:宁可多一行提示,也不静默砍掉后半段再当成全文返回 —— 那会让调用方以为卡片就这么短。MCP 的 memory_get 参数与语义完全一致 (offset / max_chars / full),两个入口共用 mcore/readtext.py 一份实现。 max_chars=0 等价于 --full

search -n 的取值范围是 [1, 20],越界会被钳制 —— SQLite 的 LIMIT -1 表示无上限, 不钳制就会把整张表倒出来。

search 输出字段:id path title kind source score matched coverage snippet


采集端

python memory.py capture --title "标题" --body "正文" [--kind knowledge] [--tags a,b]
# 正文也可从 stdin 读

写入一张 Markdown 卡片到 vault,落盘后立刻索引本卡 —— 不需要再手动跑 index, 写完即可被 search 检索。frontmatter 与既有卡片格式一致,因此新旧卡片共存、互相可检索。

蒸馏交给调用方,本模块不调 LLM

记忆的价值在于压缩。把整段会话原样倒进 vault 只会制造噪音,检索时反而更难找到重点。

所以 capture.py 不做任何 LLM 调用 —— 蒸馏由调用方完成:agent 本身就是 LLM, 让它先想清楚「什么值得记、怎么写以后才看得懂」,再交给这里落盘。

这样做的收益:零额外成本、零 API key、内容不出网

行为

情况

结果

新卡片

写入并索引本卡,返回 created + indexed: true

标题与正文都相同

跳过,返回 unchanged(幂等)

正文 < 20 字符

拒绝,返回 rejected

标题相同、正文不同

不覆盖已有卡;默认另存为 -2,并回传 conflict: true + existing_path + collision_paths

--on-conflict reject 下的标题撞车

不写盘,返回 conflict,退出码 3

正文/标题含疑似凭据

仍然写入,但回传 secrets_found + warnings(默认只告警)

--reject-secrets 下含疑似凭据

不写盘,返回 rejected,退出码 1

索引失败

卡片仍在磁盘(真相源优先),返回 indexed: false + warning

敏感内容:默认只告警,不阻断

正文与标题都会扫一遍常见凭据形态:私钥头(-----BEGIN ... PRIVATE KEY-----)、 AWS Access Key ID、GitHub / Slack token、Google API Key、OpenAI 风格 key、JWT、 以及 password = xxx 这类明文赋值。

命中后默认照常写入,只在结果里回传 secrets_foundwarnings。 需要更严时加 --reject-secrets(MCP 的 memory_capturereject_secrets: true)。

为什么默认不拦:本库的正当用途就包含渗透测试记录,而这类记录里天然会出现密钥、 连接串、凭据 —— 硬拒会把项目本身的用途一起拒掉。这是刻意的取舍,不是漏做。

两条实现上的约束,都是有意为之:

  1. 告警不复述凭据。只报「命中了哪一类 + 位置区间」,不回显原文 —— 把密钥抄进告警里等于又写了一遍到返回值与日志里,反而扩大暴露面。

  2. 宁可漏报,不要误报~/.ssh/id_ed25519密钥见 ~/.ssh/xxxtoken: 见上一条记录 这类引用式写法不会被标记;赋值式还要求值同时含字母与数字 (password: 已改成用密钥登录 是说明文字,不是凭据)。误报多起来,告警会被所有人忽略, 那比没有告警更坏。

这是提醒,不是安全边界。真要严格管控凭据请用专门的扫描工具,不要让「顺手的正则」 承担安全职责。

为什么标题撞车要显式回传:同标题不同正文过去会静默多出一个 slug-2.md —— 调用方只看到「写好了」,不知道库里已经有两张同标题的卡,此后检索会同时命中两张, 而没有任何信息能判断该信哪张。现在冲突会出现在返回值里,并且永远不覆盖已有卡片。

想表达「事实变了」不要用 --on-conflict:修正既有事实用 update, 事实已变而旧值仍需留存用 supersede(见 ROADMAP 阶段 3)。 on_conflict 只回答「标题撞了怎么办」这一个问题。

索引只作用于刚写入的这一张卡,不触发全量同步(全量是 O(语料) 的)。 索引失败不回滚 Markdown —— 真相源优先,索引随时可用 index --rebuild 重建。

CLI 的 capture 与 MCP 的 memory_capture 行为一致:两个入口,同一种结果。

  • 文件名由标题生成,中文原样保留(如 nginx-站点根目录位置.md

  • 重名自动加序号后缀(-2-3),不覆盖已有卡片

  • 原子写入(临时文件 + 改名),中途失败不会留下半截文件

  • kind 决定归入哪个分类目录:

kind

目录

kind

目录

system

00-System

prompt

05-Prompts

project

02-Projects

business

06-Business

knowledge

03-Knowledge

tool

07-Tools

content

04-Content

mistake

08-Mistakes


MCP 查询端

python memory.py mcp

stdio 传输,每行一条 JSON-RPC 2.0 消息。协议版本 2025-06-18 / 2025-03-26 / 2024-11-05(按请求协商,未知版本回落到 2024-11-05)。

stdout 是协议通道,日志一律走 stderr。 往 stdout 多写一个字符就会破坏握手。

工具

工具

用途

memory_search

检索记忆,返回摘要 + id。参数 query limit(上限 20)kind source

memory_get

用 id 取卡片全文(长卡分片返回,见下)

memory_capture

写入一条知识并立即索引本卡。参数 title body kind tags

memory_stats

库概览(总数、类型/来源分布、最近更新)

memory_reindex

手动补建索引(增量或 rebuild 全量)。正常写入已自动索引,此工具用于索引丢失或外部改动后补建

工具描述是接口的一部分 —— LLM 靠它判断何时调用,写得含糊 agent 就不会用。

客户端配置

{
  "mcpServers": {
    "memory-agent": {
      "command": "python",
      "args": ["/path/to/memory-agent/memory.py", "mcp"]
    }
  }
}

测试

python tests/test_mcp.py

覆盖握手、版本协商、工具列表、五个工具调用、错误码(-32700 / -32601 / isError)、 采集端闭环(写入 → 幂等 → 索引 → 检索到,隔离在临时 vault 中运行), 以及 stdout 纯净性 —— 逐行校验输出全部是合法 JSON-RPC。


中文分词(关键设计)

SQLite FTS5 的内置分词器都不能用于中文。 本机实测(SQLite 3.53.1):

查询词

字数

trigram

unicode61

bigram 预分词

私钥

2

0

0

1

阿里云

3

1

1

1

ecs-prod

8

语法报错

语法报错

1

  • unicode61 把连续中文当作单个 token(「登录使用私钥」是一个词),搜不到子串。

  • trigram 要求查询至少 3 字符,中文词多为 2 字,因此大量漏召回。

做法:入库前把中文按 2 字滑窗切分(阿里云阿里 里云),英文整词小写化。 见 mcore/tokenize.py

⚠️ 一个容易误解的点cards_fts 用的是 tokenize='unicode61',所以预分词的 结果会被 FTS5 再切一遍 —— - _ . / 都是分隔符。用 fts5vocab 查实际 词表可以确认:id_ed25519 存进去是 id + ed25519 两个 token,不是一整串。 所以「保留 _ . / - 使标识符保持完整」这个说法不成立 —— 它只是让查询侧把 整串转成相邻短语,因此整串仍能命中;但搜 id 同样会命中。

另注:FTS5 的 MATCH 语法中 - 会被解析为列名过滤,含连字符的词必须加引号。 tokenize.to_query_expr() 已统一处理。


检索行为

匹配档位从精确到宽松,前一档零召回才降级 —— 保证精确匹配的既有行为不被 放宽匹配污染:

档位

含义

matched

1

AND 精确:全部词整词命中

all

2

AND 前缀:全部词前缀命中

all-prefix

3

OR 精确:任一整词命中

any

4

OR 前缀:任一前缀命中

any-prefix

为什么需要前缀档:FTS5 的 MATCH整词匹配,正文里写了 sqlite3 就搜不到 sqlite,写了 requests 就搜不到 request。代码类内容里这种后缀差异极常见。 前缀只对长度 ≥ 2 的词生效 —— 实测 "a"* 在 49 张卡的库里命中 45 张,单字前缀纯噪音。

注意前缀是单向的:搜 sqlite 能命中 sqlite3,反过来搜 sqlite3 命中不了 sqlite* 只能匹配「以查询词为前缀的 term」)。

  • BM25 排序。SQLite 的 bm25() 返回负值,对外取负使「越大越相关」。

  • 已知局限(都是固有特性,不是缺陷):

    • 要求字面一致sqlite 能靠前缀档命中 sqlite3,但 userById 搜不到 getUserById —— 片段在词中间,前缀够不着。

    • 词汇鸿沟无解。查询说「本地装了什么模型」,卡片写「本机 Ollama 已装模型清单」, 字面零重叠,任何词法手段都救不回来。这是向量检索要解决的问题,见「扩展」。

曾给 OR 档加过「先按命中词数重排、再按 BM25」的逻辑,动机是怀疑 OR 档 BM25 失真。 基准实测证伪并发现它是负优化:唯一受影响的查询「本地装了什么模型」,目标卡从 第 4 名被推到第 9 名,封顶 P@5 由 66.7% 降到 55.6%,其余查询无变化。已移除。 不要再加回来,除非基准显示正收益。


检索质量基准

python memory.py bench                      # 人类可读
python memory.py bench --json               # 机器可读
python memory.py bench --save base.json     # 存基线
python memory.py bench --baseline base.json # 对比;任一指标退化则退出码 1

真值文件在数据目录~/.memory_agent/bench_queries.json),不在仓库里 —— 它包含本机卡片路径。实现见 bench/retrieval_quality.py

三条硬规定,每一条都对应一次踩过的坑:

  1. 真值按 rel_path 记录,不按整数 id。 用 id 记过一次,索引重建后 rowid 重排, 真值全部错位(卡 12 从「本机 Ollama」变成「渗透测试复盘」),据此得出的结论是假的。

  2. 真值是一组「可接受卡」,不是一张「标准卡」。 只认一张会把「返回了另一个同样 正确的答案」误判为失败。

  3. 真值为空的查询不计入精确率。 语料里没有这个词,返回空才是正确行为。

指标用封顶精确率:分母取 min(K, 相关卡数)。「相关卡只有 2 张,取满 top5 也填不满」 是相关卡用完了,不是返回了噪音 —— 不封顶的话这个区别看不出来。

本机实测(49 张卡,19 条查询,2026-09-12)

查询类型

条数

首位可接受

封顶 P@5

噪音率@5

实际档位

A

关键词(sqlite / 阿里云 / 运维…)

11

100%

100%

0%

全部 all,从不降级

B

自然语言(「本地装了什么模型」…)

4

50%

66.7%

33.3%

全部 any

结论:关键词查询零噪音,且根本走不到 OR 档;噪音只出现在自然语言查询里。 另有 4 条查询(sqlite3/tokenize/bm25/mcp)在语料里不存在,返回空是正确的。

扩展

检索层抽象为 mcore.search.Searcher 协议。加向量检索时新增一个实现即可, CLI 与调用方无需改动;cards.embedding 列已预留。

若用云端 API 计算嵌入向量,卡片内容会发送给模型厂商。必须使用本地模型。 本库含服务器信息、凭据、渗透测试记录,内容不能出网。

什么时候才值得上向量(满足任一):

  • 卡片数 > 1000,关键词召回的候选池开始失控;

  • 反复出现「明明记过但搜不到」,且措辞差异属于同义/近义而非词形差异 (词形差异前缀档已经覆盖);

  • 需要跨语言检索(中文查询找英文卡片)。

在那之前,四档降级已经覆盖绝大多数场景,而向量的成本是实打实的: 本地模型文件、ONNX runtime 或 sqlite-vec 依赖、每次 capture 都要算嵌入、 重建索引显著变慢。接口已就位,推迟的代价≈0

试过并否决的方案

FTS5 trigram 分词器(SQLite 3.34+ 内置,零依赖,看着像个便宜的中间档)。 本机实测否决,三条理由:

维度

实测结果

2 字中文词

全部 0 召回 —— 词云/分词/快照/运维/记忆 一个都搜不到(trigram 要求查询 ≥ 3 字符)

自然语言查询

全部返回空,比现状更差

唯一优势

英文中段碎片(2551 命中 ed25519),但前缀档已覆盖 ed2551ed25519 这类常见情况

索引体积

0.88x bigram,没有优势

对一个中文优先的记忆库,第一条就是致命的。

同义词/别名表(纯词法,零依赖)。用人工编写的别名表扩展查询后重测, B 类 4 条查询仍然 0/4。词法路线到此为止 —— 而且那张表是「看过测试查询之后」 写的,属于对测试集过拟合,真实泛化只会更差。

使用上的缓解手段(比上向量便宜得多)

  1. 工具描述里要求传实体名/标识符,不要传整句问句。 实测关键词查询零噪音、 首位 100% 正确,而自然语言查询噪音率 33% —— 消灭问句等于消灭噪音来源。 这与项目「蒸馏交给调用方」的原则同源。

  2. 让置信度显式化Hitmatched 档位,调用方看到 any/any-prefix 就知道这批结果不可信,可改用关键词重试。

    放宽档还会带上查询词覆盖率coverage)与一句低置信提示,例如 「置信度偏低:这是放宽档(OR)结果,只命中了部分查询词(覆盖率 33%)」。 精确档(all/all-prefix)覆盖率恒为 1.0,因此不显示 —— 写出来只是噪音。

    ⚠️ coverage 只用于展示与提示,绝不参与排序。本项目曾给 OR 档加过 「按命中词数重排」,bench 实测证伪且是负优化(目标卡从第 4 名掉到第 9 名, 封顶 P@5 由 66.7% 降到 55.6%)。加字段 ≠ 可以用它排序,这两件事必须严格区分。 tests/test_coverage.py 里有直接证据:排序层的行序与检索结果顺序逐条相等。


环境

Python 3.10+(已在 3.13、3.14 验证)。需 SQLite 支持 FTS5,Python 自带版本均满足。


许可证

MIT

Available Tools

5 tools
memory_captureA

把一条值得长期复用的知识写进记忆库,供以后所有会话和其他 agent 检索。写入后本卡会被立即索引,不需要再调用 memory_reindex。触发时机:完成一个任务、解决一个报错、确认一个环境配置、做出一个影响后续的决策之后。写入前请自己先蒸馏——你是 LLM,用一两段话把结论写清楚,不要倒贴整段对话原文。标题要写成「以后你会用什么词去搜它」,正文要写清事实、命令、路径、以及为什么这么做。不要写入:临时状态、一次性的中间过程、密码与私钥等凭据。

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYes蒸馏后的正文:结论、命令、路径、注意事项
kindNoknowledge / project / mistake / prompt / tool / content(默认 knowledge)
tagsNo可选标签
titleYes卡片标题,将被检索命中,写成可搜索的事实描述
sourceNo可选来源标记,默认取调用方 clientInfo
on_conflictNo标题已存在但正文不同时的处理。suffix(默认)另存为 -2 新卡并在结果里回传 conflict 信息;reject 直接拒绝写入。若你要表达「事实变了」,不要靠这个参数 —— 用取代语义。
reject_secretsNotrue 时若正文含疑似凭据(私钥头、AWS/GitHub/Slack token、明文密码赋值等)则拒绝写入;默认 false = 只告警不阻断。默认不阻断是因为本库的正当用途包含渗透测试记录。

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden, and it does disclose a real behavioral trait: the card is indexed immediately on write and becomes visible to all future sessions and other agents, so no reindex call is needed. It also states what must not be persisted (transient state, credentials). It stops short of describing required permissions, failure behavior, or the shape of the returned result, which keeps it at 4 rather than 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place — purpose, indexing side effect, triggers, authoring guidance, and prohibitions are all non-redundant. However it is delivered as one dense run-on block with no line breaks or headers, so the trigger list and the exclusion list are harder to scan than they need to be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter write tool with no annotations and no output schema, the description covers purpose, timing, authoring rules, and prohibitions well. The main omission is what the call returns and how failures surface (e.g. conflict results), though on_conflict handling is at least documented in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description goes further by telling the agent how to author the two required parameters — title must be phrased as the words a future search would use, body must contain facts, commands, paths, and rationale. It adds no semantics for kind/source/on_conflict/reject_secrets beyond what the schema already documents.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb+resource (把一条值得长期复用的知识写进记忆库) and its downstream effect (供以后所有会话和其他 agent 检索). It explicitly names a sibling, memory_reindex, and rules it out ('不需要再调用 memory_reindex'), so the agent can distinguish this from the read-side siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit trigger timing (完成一个任务、解决一个报错、确认一个环境配置、做出一个影响后续的决策之后) and explicit exclusions (不要写入:临时状态、一次性的中间过程、密码与私钥等凭据). It also prescribes how to prepare input (先蒸馏,不要倒贴整段对话原文) and how to phrase title vs body — a complete use protocol rather than an implied one.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_getA

读取某张知识卡的完整内容。先用 memory_search 拿到 id,再调用本工具展开全文。检索结果里的摘要被截断时使用。长卡会按长度上限分片返回:结果末尾会写明还有多少字符未显示,并按需给出继续读用的 offset —— 看到「还有 N 字符未显示」时,若那部分对你有用,就用返回的 offset 再调一次。

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes卡片 id,来自 memory_search 结果
fullNotrue 则不分片,直接返回完整正文(长卡会占用大量上下文)
offsetNo从第几个字符开始读,默认 0。分片续读时用上一次返回的 offset
max_charsNo本次最多返回多少字符,默认 20000;0 表示不限长(等于取全文,长卡慎用)

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden, and it does disclose the key behavioral trait: long cards are chunked, the result footer reports remaining character count, and the agent should re-invoke with the returned offset. It omits any mention of permissions, error behavior, or the read-only nature, but the chunking contract is the important non-obvious detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and prerequisite are front-loaded, followed by the chunking/continuation mechanics. The final sentence is somewhat long but each clause earns its place by describing the pagination loop.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With four parameters, no output schema, and no annotations, the description covers the essential behavior an agent needs (id source, truncation trigger, chunk continuation). It is complete enough to call correctly, though return-shape details are inferred rather than stated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds practical meaning by explaining how offset ties into the chunked-read continuation loop and when full/max_chars matters (长卡慎用). This goes beyond restating the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (读取某张知识卡的完整内容) and distinguishes itself from siblings by naming memory_search as the prerequisite for obtaining the id. An agent can tell it apart from the other memory_* tools immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly prescribes the workflow (先用 memory_search 拿到 id,再调用本工具) and the triggering condition (检索结果里的摘要被截断时). It routes the agent from the search tool to this one with a clear when-to-use rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_reindexA

把 Markdown 记忆源的最新改动同步进检索索引。当确认某事已被记录、但 memory_search 检索不到时调用。

ParametersJSON Schema
NameRequiredDescriptionDefault
rebuildNotrue 则清空索引后全量重建,默认 false(增量同步)

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that this is a sync/index-mutation operation, but says nothing about cost, duration, whether reindexing disrupts concurrent searches, or the side effect of a full rebuild wiping the index (that caveat lives only in the param schema). Adequate but leaves meaningful behavioral gaps for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the second is the usage trigger, the first the action, with zero filler. Front-loaded and appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with no output schema, the description covers purpose and invocation trigger well. It falls short only on mutation-side context (rebuild cost/disruption), which the reader must infer from the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single rebuild parameter is fully documented in the schema, including the destructive clear-and-rebuild behavior. The description adds no parameter meaning beyond that, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — syncing latest changes from the Markdown memory source into the retrieval index — and names the sibling it complements (memory_search). An agent can distinguish this from memory_search/stats/get without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger condition: call it when you've confirmed something is recorded but memory_search fails to retrieve it. That routes the agent away from memory_search effectively, though it doesn't state when NOT to call it (e.g., no need to run routinely or before every search).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_statsA

查看记忆库概览:卡片总数、类型与来源分布、最近更新。不确定库里有什么、或想确认检索范围时先调用它。

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden; '查看' (view) plus the enumeration of read-only summary fields implies a non-mutating diagnostic call, and it tells the agent what data comes back even without an output schema. It does not explicitly state that there are no side effects, permissions required, or cost, which keeps it out of 5 territory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One compact sentence front-loads the resource and its returned contents, and a second short clause supplies the usage cue. No filler, no repetition of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-param read tool with no output schema and no annotations, the description adequately covers both what it returns and when to reach for it. The only minor gap is the absence of any statement about freshness, ordering, or cost of the call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4; there is nothing for the description to clarify beyond what the empty schema already conveys.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ('查看记忆库概览') and enumerates exactly what the overview contains: card totals, type and source distributions, recent updates. That clearly separates it from memory_search/memory_get as a metadata-summary tool, though it never names those siblings explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an actionable trigger: call it first when you are unsure what the library contains or want to confirm retrieval scope. That is real when-to-use guidance but stops short of naming the alternative (e.g. 'then use memory_search to retrieve') or stating when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedmemory_capture
    • First observedmemory_get
    • First observedmemory_reindex
    • First observedmemory_search
    • First observedmemory_stats

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct memory operation: search for retrieval, stats for overview, get for full card content, capture for writing, reindex for sync. Boundaries are clear and the recommended search→get workflow is explicitly documented.

Naming Consistency5/5

All tools use snake_case with a consistent memory_ prefix (memory_search, memory_stats, memory_get, memory_capture, memory_reindex). No deviations or mixed conventions.

Tool Count5/5

5 tools is well-scoped for a memory agent: retrieval, inspection, writing, and indexing are all covered without redundancy. Each tool has a clear purpose and earns its place.

Completeness3/5

Covers read (search/get/stats), write (capture), and index sync (reindex). However, there is no explicit update or delete operation for existing memory cards, which is a notable gap for correcting or removing outdated knowledge. Append-only may be intentional, but agents cannot manage stale entries directly.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides tools for AI agents to manage long-term memories, daily notes, and TODO lists through a structured markdown file system. It enables context awareness by allowing agents to read, write, and search entries for persistent information storage.
    6
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides long-lived, cross-project technical memory for AI agents via markdown cards stored in git and indexed by SQLite, enabling search, retrieval, and human-reviewed knowledge management.
    ISC
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides a durable, Obsidian-compatible knowledge base for agents using markdown notes and wikilinks. Enables agents to store, retrieve, and interlink knowledge persistently, with tools for writing, searching, and managing a graph of notes.
    1
    MIT