关于 echocache
echocache 是用于保存 LLM 结论、供不同会话、项目和 MCP 主机复用的 MCP 服务。它结合精确键的新鲜度检查、语义搜索和图关联,目标是复用推导结果,而非缓存文件内容。
主要功能
- 01精确匹配查询与新鲜度状态
- 02缓存条目的语义搜索
- 03遍历关联条目图
- 04级联失效派生条目
- 05跨项目共享的 SQLite 存储
- 06可选 AES-256-GCM 静态加密
适用场景
- 01在后续会话复用研究结论
- 02用不同措辞查找已保存结果
- 03在不同项目目录间共享代码库概览
- 04源内容变更后使派生结论失效
- 05查看缓存命中和提供的 token 数
MCP 相关
作为 stdio MCP 服务运行,提供存储、读取、搜索、关联、失效和查看缓存结果的工具。注册该服务的多个项目可共享同一个 SQLite 数据库。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
echocache — 用于缓存 LLM 响应的 MCP 服务
一个用于缓存 LLM 响应的 MCP 服务——就像 HTTP 缓存缓存昂贵的服务端响应,而不是浏览器缓存静态资源。再次提出已经回答过的问题,答案就会回响,而不必重新推导。
两种查找路径,分别借鉴了两种不同的缓存方式:
- 精确匹配,HTTP 风格 —
cache_get/cache_set以(model, prompt, params)为键,并通过ttl_seconds和stale_while_revalidate_seconds实现类似Cache-Control的行为:新鲜、过期但可用,或已过期。 - 知识图谱检索 — 每条存储的记录都是一个小型相似度图中的节点。
cache_query按含义查找相关记录,而不仅仅依赖精确键;cache_related沿图边遍历(自动关联的“相似”记录,或明确的“源自”父记录),以便 Agent 从头重做工作之前,先找到所有已有的知识。如果源记录发生变化,cache_invalidate可以沿这些“源自”关系级联失效。
作为标准的 stdio MCP 服务运行,因此可与 Claude Code、Claude Desktop、Cursor、VS Code + Copilot 或其他支持 MCP 的宿主配合使用——请参阅下方的安装,以及 AGENTS.md,了解任何已连接的 Agent 都应遵循的工具使用协议。
适用场景——以及不适用场景
缓存 Agent 得出的结论,绝不缓存它读过的内容。这就是全部设计理念,而且值得开门见山地说明,因为直觉上的用法恰恰是错的:提供缓存的文件读取结果,读者付出的 token 与读取文件时完全相同,因为内容仍然必须进入上下文。因此,无论命中率多高,缓存文件读取都毫无节省;如果 Agent 重新输出文件内容来存储,那就是花费输出 token,却没有任何收益。只有在命中能替代重新生成某些内容时,缓存才有价值。
以下是值得缓存和经测量后发现不值得缓存的场景:
- 最有价值:成本高昂的研究或判断。 在本项目自身的历史记录中,有一条真实的研究链涉及 22 次工具调用,花费 37,119 个输出 token,最终得出 255 个 token 的结论——按输出价格加权后,二者相差 728 倍,而直接返回该结论的成本低得多。只要复用一次,写入成本就能回本约 145 倍。我们还用一次基于全新网页搜索得出的设计决策进行了实时验证:即使措辞不同,也能正确回忆;即使有条目表面用词相似但内容无关,也能正确排在它前面。目前还不能证明这类内容会在本项目自身的历史记录中再次出现——但只需命中一次就有巨大收益,因此频率低并不足以否定它的价值,这与文件读取不同。
- 有条件地有价值:跨会话重新熟悉项目。 Agent 读取代码库以了解其内容,会话结束后,后续会话需要再次了解这些内容。以
express/lib为例——六个文件,共 62KB——重新读取源码需要 15,504 个 token,而提供缓存的概览只需 549 个,约少 28 倍。这只适用于后续会话确实需要全面了解的情况;如果只需要一个具体答案,就会使用 grep 并读取部分内容,耗费约 900 个 token,缓存就没有优势。 - 不值得:在并行任务派发中替代读取。 在一次代码审查派发中,30 个子 Agent 读取了同一批内容,约 374,000 个 token,而这些内容此前已由另一个子 Agent 读取——但它们的 166 次读取中,有 127 次使用了
offset/limit,因此读取的是部分内容而非整个文件。测量结果显示,用共享推导结果替代这些片段,表现差 27%:grep 本来就是成本低、精确的定位方式;缓存的映射结果与它在同一领域竞争,最终落败。
这三种情况共同指向一条规则:缓存 grep 无法还原的内容。 比如结论、判断、某件事为何如此的原因、任何一次搜索都无法揭示的跨文件综合分析、研究发现,以及某件事不存在这一事实。绝不缓存位置——grep 查找位置的成本低于查询缓存的成本——也绝不缓存文件。
如果缓存条目中包含文件路径或行号,那是为了引导读者找到准确细节,而不是替代阅读。查找匹配项时,应优先使用 cache_query,而不是 cache_get:后续会话或其他 Agent 不会像写入者那样措辞提问。
它不是什么:不是避免读取文件的方法,不是真相来源,也不能替代单次对话内部的提示词缓存;后者成本更低,而且不需要服务端。echocache 用于保存必须超出其生成时所处上下文而继续存在的结果。
Claude Code 已经免费提供的功能
如果你唯一使用的宿主是 Claude Code,它自带的持久记忆 已经实现了这一做法的核心:将结论写入记忆文件,而不是写回得出结论的源文件;后续会话会在重复执行工作前读取这些结论。这与本项目最终采用的规则相同,而且免费运行,无需注册服务。本项目在构建过程中得出的发现和测量结果都存储在那里,而不是存储在 echocache 本身中——这一点值得注意,因为这意味着该工具并未用于缓存产生它的研究结果。
真正的不同之处如下,按重要程度排序:
- 跨项目共享。 Claude Code 的记忆仅限于单个项目目录。echocache 使用一个 SQLite 文件,机器上的任何项目都可以注册并访问,因此在一个仓库中得出的结论可以从另一个仓库查询。确实存在这一差异,但尚未得到验证:本项目自身的历史记录显示,结论实际上在会话间被重复使用的情况为零;而跨项目复用的门槛比这还要高。
- 语义检索。
cache_query会根据含义查找匹配项,不受措辞或文件归档位置影响。记忆依靠始终加载的索引,以及 Agent 自行判断要打开什么来检索——没有向量搜索。 - 不依赖特定宿主。 可从 Cursor、VS Code、Claude Desktop 或任何其他 MCP 客户端使用;记忆则是 Claude Code 专属的原生功能。
- 明确的新鲜度管理。 TTL/过期后边用边重新验证的新鲜度管理,以及基于哈希的
derived_from失效机制,可以自动发现源数据过期。记忆两者皆无;只有 Agent 恰好注意到时,才会发现内容过期。
对于单个用户在单个宿主的单个项目中使用,记忆已经免费提供了这里的大部分价值。echocache 真正的适用场景比“LLM 响应缓存”更窄:具体来说,是在尚未共享记忆存储的项目或宿主之间共享推导结果——而这个更窄的场景尚未得到验证;在按照本文档其余内容所采用的方式进行测量之前,它不只是未经测试。
安装
无需克隆或构建——直接从 npm 注册即可。
Claude Code
claude mcp add echocache -- npx -y echocache
Claude Desktop / Cursor / VS Code — 在宿主的 MCP 配置中添加一个 stdio 条目
(claude_desktop_config.json、.cursor/mcp.json、.vscode/mcp.json):
{
"mcpServers": {
"echocache": {
"command": "npx",
"args": ["-y", "echocache"]
}
}
}
OpenCode — 在 opencode.jsonc 中添加一个条目(全局配置:~/.config/opencode/opencode.jsonc,或
在仓库根目录使用项目级配置):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"echocache": {
"type": "local",
"command": ["npx", "-y", "echocache"],
"enabled": true
}
}
}
任何支持 MCP 的宿主都使用相同的启动命令;只有配置文件不同。然后让你的 Agent 参考
AGENTS.md,了解何时使用缓存——协议比接线方式更重要,因为缓存错误的内容只会浪费令牌,而非节省令牌。
使用协议也以技能形式提供(echocache-cache、echocache-gain),并附带一个用于 Claude Code 的
codebase-orienter 子 Agent。在克隆的本仓库中,它们会从
.claude/skills/ 和 .opencode/skills/ 自动发现。
npm 包也包含这些技能,但宿主只会在自己的技能目录中发现技能,因此在执行 npm install -g echocache 后安装一次:
# Claude Code
mkdir -p ~/.claude/skills ~/.claude/agents
cp -r "$(npm root -g)"/echocache/.claude/skills/echocache-* ~/.claude/skills/
cp "$(npm root -g)"/echocache/.claude/agents/codebase-orienter.md ~/.claude/agents/
# OpenCode
mkdir -p ~/.config/opencode/skills
cp -r "$(npm root -g)"/echocache/.opencode/skills/echocache-* ~/.config/opencode/skills/
配置
所有设置都是环境变量,且均为可选项:
| 变量 | 默认值 | 含义 |
|---|---|---|
ECHOCACHE_DB_PATH | ~/.echocache/cache.db | SQLite 文件位置 |
ECHOCACHE_MAX_ENTRIES | 10000 | 保留条目的 LRU 上限 |
ECHOCACHE_MAX_BYTES | 268435456 (256MB) | 保留响应字节数的 LRU 上限 |
ECHOCACHE_DEFAULT_TTL_SECONDS | unset (never expires) | 调用方未指定时的有效期;条目仍受 LRU 上限约束 |
ECHOCACHE_SIMILARITY_THRESHOLD | 0.25 | 自动关联条目的相似度下限 |
ECHOCACHE_LINK_CANDIDATE_POOL | 500 | 新写入条目进行比较的近期条目数 |
ECHOCACHE_ENCRYPTION_KEY | unset | 64 个十六进制字符(32 字节);启用静态 AES-256-GCM 加密 |
数据库目录会以 0700 权限创建,文件则以 0600 权限创建。设置加密密钥还可对静态存储的条目内容进行加密:
export ECHOCACHE_ENCRYPTION_KEY=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
启用或关闭加密需要使用新的数据库——不支持原地迁移;如果密钥与数据库不匹配,服务会在启动时拒绝运行,而不是等到之后读取时才失败。
工具
| 工具 | 用途 |
|---|---|
cache_get | 精确匹配查找,并区分新鲜、过期和已失效状态 |
cache_set | 存储结果;并自动将其关联到相似度图中 |
cache_query | 对所有缓存条目进行语义搜索 |
cache_related | 从一个条目遍历图,查找与其关联的条目 |
cache_invalidate | 删除条目,并可选择级联删除依赖项 |
cache_stats | 精确匹配命中率、queryHits/queryMisses 及已提供的令牌数 |
所有工具都由同一个 SQLite 文件提供支持,该文件由每个注册此服务的项目共享——在一个代码库中得出的结论,可以在另一个代码库中查询。来自不同进程的并发读写是预期场景,而非边缘情况。
开发
git clone https://github.com/kskurtveit/echocache && cd echocache
npm install
npm run check # typecheck + tests
npm start # or: npm run dev
架构和模块参考请参阅 CLAUDE.md。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。