mcpField
C
chamber

chamber

本地服务
github.com/abm9111记忆与知识33 天前更新

关于 chamber

chamber 是面向使用本地笔记的 AI Agent 的 MCP 服务,用确定性字符串匹配检查回答中的数字、名称等是否出现在引用文本中。它还可索引笔记、跟踪引用内容变化并验证已记录的主张;检查本身不使用模型或网络。

主要功能

  1. 01核对数字、名称、域名和文件名
  2. 02索引本地笔记并检索内容
  3. 03验证引用段落是否发生变化
  4. 04记录无来源主张的引用债务
  5. 05按句检查带引用的回答

适用场景

  1. 01检查 Agent 引用笔记时是否错报数字
  2. 02发现笔记修改后已引用依据发生变化
  3. 03为笔记问答生成可核验的来源引用

MCP 相关

MCP 服务向 MCP 客户端提供 chamber_check,用于检查主张与引用笔记之间的术语匹配。配置启用后也可提供 chamber_ask;该问答功能需要模型。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"abm9111-chamber": {
"command": "npx",
"args": [
"-y",
"@bu7umaid/chamber"
],
"env": {
"CHAMBER_PYTHON": "<CHAMBER_PYTHON>",
"CHAMBER_API_KEY": "<CHAMBER_API_KEY>"
}
}
}
}
启动命令npx -y @bu7umaid/chamber
需要配置的环境变量
CHAMBER_PYTHONPath to a Python interpreter with onnxruntime, used by the local embedder. Optional: defaults to python3 on PATH; without onnxruntime, semantic search degrades and Chamber says so.
CHAMBER_API_KEY密钥API key for the configured model endpoint. Only read when model.base is not a loopback address; a local endpoint needs no key.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@bu7umaid/chamber0.2.2

工具

4

收录的工具列表 · 更新于 3 天前

参数类型必填说明
claimsarray是要核查的主张及其各自的来源笔记。
recordboolean否将 SUPPORTED 主张作为信念提交,并固定来源,以便 chamber_verify 检查内容漂移。默认值为 false:不会写入任何内容。

详细介绍

Chamber

发现 AI Agent 引用了其所引用笔记中没有的数字或名称。当 Claude Code(或任何 MCP 宿主)根据你的笔记作答时,系统会要求它先用 chamber_check 检查每条主张。实际输出(已精简):

2 claim(s): 1 supported · 1 terms absent · 0 nothing to check · 0 not judged

[TERMS_ABSENT] Q3 revenue was $420k, up 18% on Q2.
     the cited text does not contain: 420k
     checked: q3-review.md#p0
[SUPPORTED] Enterprise renewals moved to Dana Ortiz in August.
     every term Chamber recognises occurs in the cited text
     checked: q3-review.md#p0

笔记中写的是 $240k。Agent 写成了 $420k。之后编辑笔记,同一项检查会针对新文本进行判断,结果还会显示 index is behind this file,因为索引中仍保留着旧副本。

在 Claude Code 中,以插件形式使用。它会询问你的笔记文件夹,并添加服务和 chamber-check 技能:

/plugin install chamber --marketplace abm9111/chamber

在低于 2.1.275 的 Claude Code 版本中,请先运行 /plugin marketplace add abm9111/chamber,然后运行 /plugin install chamber@chamber。插件需要一个文件夹路径,可以是绝对路径,也可以以 ~/ 开头;还需要一个以逗号分隔的跳过文件夹列表(.obsidian,*sync-conflict*;名称中不能含逗号)。使用 /plugin configure chamber@chamber 可更改其中任一项。它会运行版本固定的 Chamber 发布版,通过小型启动器(plugin/launch.mjs)在不使用 shell 的情况下启动 npm 的 npx。原生 Windows 上无法启动裸 npx。

Claude Code 不会自动更新第三方市场。要获取较新的固定版本,请开启自动更新(/plugin,切换到 Marketplaces 标签页,选择 chamber,然后选择 Enable auto-update),或运行 claude plugin update chamber@chamber。如果你还通过 claude mcp add 手动添加了服务,chamber_check 会列出两次:保留插件添加的那项,并运行 claude mcp remove chamber。

或者,仅在任意 MCP 宿主中运行服务:

claude mcp add -s user chamber -- npx -y @bu7umaid/chamber mcp --notes ~/Notes
{
  "mcpServers": {
    "chamber": {
      "command": "npx",
      "args": ["-y", "@bu7umaid/chamber", "mcp", "--notes", "/absolute/path/to/Notes"]
    }
  }
}

在 Codex 中,命令行、IDE 扩展和桌面应用都读取同一个 ~/.codex/config.toml。使用命令行添加服务:

codex mcp add chamber -- npx -y @bu7umaid/chamber mcp --notes /absolute/path/to/Notes

也可以手动编辑该文件。首次运行时会下载软件包,耗时可能超过 Codex 为服务启动预留的 10 秒,因此配置表中设置了更长的超时时间:

[mcp_servers.chamber]
command = "npx"
args = ["-y", "@bu7umaid/chamber", "mcp", "--notes", "/absolute/path/to/Notes"]
startup_timeout_sec = 60

此格式来自 OpenAI 的 Codex MCP 页面:codex mcp add、包含 command 和 args 的 [mcp_servers.<name>] 表,以及默认值为 10 的 startup_timeout_sec。Chamber 尚未在 Codex 中测试。

无需模型、账号或网络:这项检查会使用 node:sqlite 和你磁盘上的文件,进行确定性的字符串匹配。它会检查数字、首字母大写的名称、域名、文件名和数量。它不会检查含义,因此,即使是根据笔记原文构造出的否定句或反转句,也仍会通过。请参阅经过验证的引用能证明什么、不能证明什么。

不止于检查:提供带来源引用的回答,并运行每日任务,告知你某个来源何时发生变化,而你此前已经信任的结论仍基于该来源。

运行检查

上面的 npx 命令行足以满足大多数人的需求。在 --notes 后可重复使用 --exclude <pattern>。配置中的摄取根目录及其排除项也会计入。还有另外两种使用方式:

从代码检出目录运行(Node 23.6+)。 TypeScript 可直接从代码仓库运行,无需构建步骤。try 会构建一个临时工作区,运行实际代码路径,然后将其删除。已发布的软件包可在 Node 22 上运行(实测版本为 22.23.1,会显示 Node 的 experimental-SQLite 警告)。Node 20.20.2 会因缺少 node:sqlite 而以 ERR_UNKNOWN_BUILTIN_MODULE 退出。代码检出运行仍要求 Node 23.6 或更高版本。

git clone https://github.com/abm9111/chamber.git && cd chamber && npm ci && node --experimental-strip-types src/cli.ts try

**如果 /mcp 未列出 chamber_check,**说明宿主启动服务时使用了精简的 PATH。从你自己的 shell 中运行 command -v node 获取解释器路径,并让它指向已发布版本的 bin 文件,或代码检出目录中的 src/mcp_server.ts。这两者是不同的文件:

# published bin: bin/chamber.js loads dist/. This is not src/mcp_server.ts.
claude mcp add -s user chamber -- "$(command -v node)" /path/to/node_modules/@bu7umaid/chamber/bin/chamber.js mcp

# checkout only. src/mcp_server.ts is not in the npm install.
claude mcp add -s user chamber -- "$(command -v node)" --experimental-strip-types /path/to/chamber/src/mcp_server.ts

摄取和 chamber_ask 需要配置。如果已设置配置中的摄取根目录,检查也会读取它们。请参阅配置:摄取、chamber_ask 和检查的配置根目录。

人们的实际做法

目前还没有公开的 Chamber 用户记录。以下是 X 上相关的失败案例,也是这项检查存在的原因。

  • 将 Obsidian 文件夹交给 Claude Code,只会读取文件,不会检查句子。Richard Kovacs,2026 年 9 月 28 日:Claude 会返回来源列表,由他来检查。他指出,剩下的问题是确认偏误,并把应对方式归结为自律。
  • 必须由 Agent 记得调用的工具,并不能充当关卡。 Saksham Arora,2026 年 10 月 2 日:共享记忆 MCP 只有在另一个 Agent 决定搜索时,才会回想起某个会话,因此他在每条消息之前都加了一个钩子。chamber_check 也是同样的形式。MCP instructions 会要求 Claude 调用它。如果 Claude 跳过,整个回合不会受到阻拦。缺少的关键环节是一个要求提供回执的 Stop 钩子;它目前还不在这个仓库里。
  • 传播广泛的知识库帖子(99.7% 召回率、几分钟内加入数千个链接)并不是测量结果。这个仓库里的数字来自 docs/KNOWN_LIMITATIONS.md 第 2 节中的 200 条声明集:大多能抓出编造的值,但抓不出否定句。

两分钟了解它

上面的检出命令会构建一个一次性工作区,在其中运行真正的代码路径,然后将其删除(加上 --keep 即可查看)。它不会打开数据库。

chamber 试用

这段录制是根据 assets/demo.tape 脚本生成的,而不是手动录制的,因此输出变化时会重新生成,不会悄悄展示一个已经不存在的 Chamber 版本。以下内容都是该检出命令的实际输出,经过了删减:

$ chamber believe belief "Customers may return any purchase within 30 days of delivery."
  committed blf_ddcf4f3c9b2e81b8
  an unsourced assertion is not refused — it mints citation debt.

$ chamber debts
  dbt_18bd1c1171cdbfcb  [pending]

$ chamber pay-debt
  proposed 2 source(s), 2 pinned; best=0.694

$ chamber verify
  blf_ddcf4f3c9b2e81b8  2/2 pins verified

这是常见状态:一个有证据支撑且证据仍然成立的信念。接着,有人编辑了它所依据的笔记——30 days 变成了 14 days:

$ chamber ingest ./notes
  ingested 2 file(s) as 4 passage(s)

$ chamber verify
  blf_ddcf4f3c9b2e81b8  1/2 pins verified
    hash_mismatch: refunds.md#p0

没人要求它重新审视这个信念。结论没有变化;变化的是它赖以成立的依据,而且退出码非零,因此计划任务可以据此采取行动。这就是整个产品。

另外四种场景——由外部锚点发现已回滚的账本、沙箱拒绝运行而不是降级、拒绝恶意工具目录——位于 demos/ 中,并会在 CI 中运行,确保它们不会偏离代码。

上述词语的定义

Chamber 的所有操作都记录在一个 SQLite 文件的行中。对话记录中的每个术语都对应一个表或哈希值:

词语实际含义
passage一个 Markdown 文件中的一个片段。refunds.md#p0 表示文件路径 + 片段索引。
beliefbelief 表中的一行:一条断言句,关联到为其提供支撑的片段。
pin对引用片段存储的标题、正文和 ref 计算出的 SHA-256 哈希值,在引用时生成并保存在 belief_source 中。
verify重新读取每个已固定的片段,重新计算哈希值并进行比较。任何不匹配都会以非零状态退出。不涉及模型。
citation debtcitation_debt 表中的一行,在某条断言没有来源却提交时创建。同一条声明必须先还清欠账,才能再次提交。
pay-debt检索为欠账的声明推荐片段;接受后会固定这些片段。
APORIA没有检索到任何支持答案的片段时给出的判定。回复为“我不知道”,并以此记录。
gate在同一个 SQLite 事务中执行检查和写入——要么两者都提交,要么都不提交。
audit log只追加的 audit_event;每一行的哈希值都涵盖上一行的哈希值,因此编辑历史会使其后每个哈希值都失效。
anchor存储在数据库之外的日志根哈希,因此可以检测到日志被截断,而不是悄无声息地发生。
the scheduler运行 ingest + verify 的 launchd/systemd 任务,只在出现偏差时发出通知。

这些都不是隐藏机制:运行 sqlite3 ~/.local/share/chamber/chamber.sqlite '.tables' 即可查看全部内容。

为答案提供来源引用

配置模型后,chamber ask 会逐句检查引用。使用同样的两篇示例笔记,在本地 30B 模型上:

$ chamber ask "summarise our refund policy"

Customers may return any purchase within 30 days of delivery [2]. Refunds
are issued to the original payment method, usually within five working days
of the returned item arriving at the warehouse [2]. However, perishable goods
and personalised items cannot be returned once dispatched [1].

  [ALLOWED] Customers may return any purchase within 30 days of delivery [2]. Refu
     sources: refunds.md#p0 — refunds › Refund policy, refunds.md#p1 — refunds › Refund policy › Exceptions

模型看到的是 [1]…[k],而不是文档 ID 或哈希,因此从原理上说,它无法伪造引用——答案生成后,系统会将这些编号解析回对应文件。没有引用的句子会标记为 UNSUPPORTED:系统会记录,但不会将其视为关键依据。如果句子中的编号、名称或领域不在它引用的段落中,该引用也会被移除,并指出缺少哪些术语(terms_absent)——真实的段落并不能为其中未提及的主张提供证据。答案中的标题会显示为 [HEADING],不会被记录。

语料库无法回答的问题更值得关注:

$ chamber ask "what should a customer do if they want to return a perishable
               item after the office has closed?"

I don't know

  [APORIA] I don't know

两篇笔记都已编入索引,且都与问题相关。但它们都无法回答这个问题,因此系统不会拼凑内容来作答。

配置:ingest、chamber_ask 和检查所用的配置根目录

npm link                 # puts `chamber` on your PATH
chamber init             # writes ~/.config/chamber/config.json

然后编辑该配置,添加笔记文件夹和模型:

{
  "database": "~/.local/share/chamber/chamber.sqlite",
  "model": { "base": "http://127.0.0.1:8087/v1", "name": "your-model", "mode": "openai" },
  "ingest": [{ "root": "~/Notes", "exclude": ["transcripts", "attachments"] }]
}

--exclude <pattern> 可在 --notes 后重复指定;配置中的 ingest 根目录及其排除规则也会被视为已声明文件夹,若某条排除规则没有匹配任何内容,就会拒绝该文件夹。仅保存在索引行中的根目录,不会授权读取索引中没有的文件。

model.base 可以指定任何兼容 OpenAI 的端点。回环地址无需 API 密钥;其他地址会从环境中读取 CHAMBER_API_KEY,绝不会从文件中读取。

chamber ingest           # index every configured root
chamber ask "..."        # ask, with citations
chamber verify           # re-check stored pins against the corpus
chamber corpus           # what is actually in the index

你使用的嵌入器取决于安装方式。 npm 或 Docker 安装会使用 local-hash-v1 向量进行嵌入,且不会发出警告;但如果本地 Ollama 服务在 127.0.0.1:11434 上响应,或设置了 CHAMBER_EMBEDDER=ollama,则会改用 Ollama:npm 包和两个 Dockerfile 都不包含 models/minilm/(23 MB 的 MiniLM 权重),因此使用哈希向量时,chamber ingest 及 chamber_ask 背后的检索会根据字符 n-gram 匹配,而非根据含义匹配。chamber_check 不受影响;它不使用模型。 如需使用 MiniLM,请克隆此仓库,使用 pip install --require-hashes -r scripts/requirements-embed.txt 安装其 Python 依赖,并将 CHAMBER_PYTHON 设置为安装了这些依赖的解释器。若克隆仓库所用的解释器缺少 onnxruntime,也会退回到哈希向量,并在 stderr 中发出警告。

首次 ingest 前请设置排除规则。 默认没有排除列表。如果将导出的聊天记录文件夹作为目标,Chamber 会照单全收并据此作答——请参阅 chamber corpus 和 docs/KNOWN_LIMITATIONS.md 中的第 11 条。 如果根目录是 Obsidian 库,请在首次 ingest 前排除 .obsidian、.trash 和 *sync-conflict*。符号链接文件夹会按链接路径编入索引。检查也会读取真实路径,因为它使用与 ingest 相同的逐条规则。若链接指向已声明文件夹之外,则不会读取。

将其用作 CI 漂移门禁

同样的验证流程也适用于仓库:将文档中的主张固定到代码或策略段落上,当依据发生变化时,让 chamber verify --json 使构建失败。只需在工作流中添加一行——此仓库提供了对应的 action:

- uses: abm9111/[email protected]

docs/CI_DRIFT_GATE.md 是一页式操作指南; demos/06_ci_drift_gate.ts 是可运行的操作记录。

每日运行

deploy/launchd/com.chamber.verify.plist(macOS)和 deploy/systemd/ (Linux)会按计划运行 ingest 和 verify,并且只在发生漂移时发出通知。如果检查大多数日子都能正确报告“无变化”,你就会不再查看它;因此它会保持安静,直到确有变化。

在 Obsidian 中呈现

配套插件 Chamber Drift 会将 verify --json 的报告呈现为库侧边栏面板和每篇笔记的横幅,仅此而已。它从不验证,也从不写入;这两件事都由 Chamber 在 Obsidian 之外按自己的计划完成。设置说明,包括用于写入报告的单行命令和 Obsidian Sync 的注意事项:docs/OBSIDIAN.md。

在 AI 编码 Agent 中使用

使用自身工具读取你的库的 Agent,可以检查自己即将告诉你的内容。chamber_check 接收 Agent 的说法及其声称依据的笔记,并按说法逐条作答(简略版):

[SUPPORTED] One NVIDIA A100 80GB or an L40S can serve about 1,000 users for code completion.
     found in: ai-coding-setups-march-2026.md#p25
[TERMS_ABSENT] One NVIDIA A100 80GB can serve about 2,000 users for code completion.
     the cited text does not contain: 2000

检查不使用模型。路径为绝对路径且文件位于已声明文件夹中时,它会读取磁盘上的文件。已编入索引的笔记即使后来发生变化,仍会根据磁盘文本进行判断,结果还会添加 index is behind this file。段落引用依据已编入索引的文本进行判断。SUPPORTED 表示识别出的术语出现在该文本中,并不表示句子由此成立。然后,它会检查说法中的每个数字、大写名称、域名、文件名和计数是否出现在笔记中,以此捕捉捏造的值。它不会检查小写名称或普通词语,也无法捕捉由笔记自身词语拼成的否定句或反转句——关于它经测量能够捕捉的内容,见 docs/KNOWN_LIMITATIONS.md §2。除非以 record: true 调用,否则它不会写入任何内容。此时,受支持的说法会通过门控提交,并固定到支持它们的段落;笔记重新摄取后,chamber_verify 会报告固定段落发生变化的说法。 服务会通过 MCP instructions 将这些信息告知宿主,Claude Code 会将其放入 Agent 的上下文中。这是提示词约定,而非运行时门控。

工具有四个,不是三个。上面介绍的是 chamber_check。其余三个负责其他工作:chamber_ask(Chamber 配置的模型作答,并提供相同的逐条说法判定)、chamber_verify(检查已记录说法的漂移)和 chamber_corpus(查看已编入索引的内容)。CHAMBER_PYTHON 是可选项,仅供 chamber_ask 的语义检索使用;缺少 onnxruntime 时会回退到哈希向量。摄取仍通过 CLI 执行,以免模型重新索引自己的证据。

使用上面的命令注册服务。该 npx 会运行已发布的 bin(dist/)。

服务会在每次工具调用时重新读取配置,因此编辑 model 后,下次调用就会生效,无需重新连接;但服务自身环境中设置的 CHAMBER_* 变量仍优先于文件。数据库是例外:它会在进程整个生命周期内保持固定,因为调用可能会在数据库打开时等待模型响应——要切换数据库,请重新连接服务。首次使用以及解析后的数据库、模式和基地址发生变化时,这些信息都会输出到 stderr,因此宿主的 MCP 日志可以确认服务正在使用的配置。

这些接口都无法激活技能、批准待处理的写入或执行摄取——设置这些门控是为了让人类通过它们;把批准权限交给模型只会颠倒门控的作用,而非削弱它们。

chamber_ask 不是只读操作,写入也不只是记账:每条说法都会经过提交门控,因此带有已验证引文的说法会作为带有固定引用的信念记录下来——这正是 chamber verify 之后会重新检查是否漂移的内容。没有来源的断言会产生引文债务;支出也会被记录。这与命令行中的 chamber ask 行为一致。这里的保证是不会绕过门控,而不是不会写入任何内容。

已验证的引用能证明什么,不能证明什么

Chamber 能证明被引用的段落就是它声称的那个段落——未经修改、仍然存在,而且表达的内容仍与引用所说的一致。

它无法判断某项主张是否能从该段落推导出来。模型可能引用真实来源却误读它,而这里的每一层都会放行。这是明确声明的非目标,也已观察到此类情况,且尚未解决。

信任任何输出前,请阅读 docs/KNOWN_LIMITATIONS.md。其中记录了 21 项限制,包括最不光彩的两项。默认情况下必须使用沙箱,且默认行为是拒绝:工具代码(tool-run、tool-synth、sandbox-test、MCP 工具验证)只有在 bubblewrap 下运行,且探测确认 bubblewrap 能实现隔离后才会运行。没有这样的后端时,程序会拒绝运行;CHAMBER_SANDBOX_REQUIRED=0(或 false、no、off)是明确的退出选项,会在清理过的环境中运行普通子进程。该选项不提供隔离:一次经探测的运行读取了 $HOME 并解析了 DNS(docs/KNOWN_LIMITATIONS.md §1)。macOS 没有 bubblewrap,因此无法在 macOS 上测试隔离。该路径不属于 chamber_check。使用退出选项时,不要把“沙箱”理解为隔离。引用欠账能可靠地阻止逐字复述,但其上的释义环节只是启发式判断:校准发现,没有任何余弦相似度阈值能区分改述与矛盾。现在,数值和否定检查排除了其中最严重的问题——操作者纠正一项欠账主张时,不会再因为复述该主张而遭拒——但五个真实释义中仍有两个会漏过,而既非数值相关也未使用否定表述的矛盾仍会被判定为重复内容。

不变量

任何断言只有经过一道门才能变为可执行、可引用或可作为依据;这道门必须在同一事务中完成检查和写入——其他任何内容都可能衰退、搁置或被推翻,但绝不能在不知不觉中通过。

门在以下情况下阻止
commitBelief存在尚未解决的阻断性引用欠账的断言;缺少标记或无法验证标记;将反证作为来源;快速路径上的信念类型提交
tryActivateSkill存在未解决的保留项;存在过时且作为依据的信念;内容 ≠ 最近一次经审查清除问题的哈希;能力清单请求超限

两道门都会写入哈希链式审计日志——entry_hash = sha256(prev_hash || canonical JSON),并配有增量 Merkle 树——因此,篡改过去的决策会破坏其后的每个哈希。撤回类型(defeater、unknown)可自由提交,且绝不会产生阻断性欠账。

默认行为是拒绝:记忆和技能写入需要审批;学习到的技能会进入隔离区,而不是被静默应用;过期的待处理写入不算已获批准。

开发

npm test        # 308 tests
npm run typecheck
npm run probes  # adversarial probes; each one asserts a defect is absent

目前,npm run probes 可以通过,但这句话从写下那一刻起就已过时——请实际运行,而不要盲目信任。两个探测(sandbox_escape、debt_paraphrase)在修复合入前,曾连续数周因真实存在且尚未解决的缺陷而报红;它们之所以被设为门,正是因为之后仍可能再次报红。无法失败的门,只会宣称它从未检查过的安全性。

目录结构

src/ask.ts              retrieval → prompt → per-claim citation gate
src/mcp_server.ts       MCP surface: ask, check, verify, corpus
src/commit_belief.ts    the belief gate; check and write in one transaction
src/pins.ts             content pins and drift verification
src/audit.ts            hash-chained log + incremental Merkle
src/config.ts           settings: flag → env → config file → default
src/db.ts               opens the database, loads every schema
probes/                 adversarial probes, run by npm run probes
demos/                  the four scenarios above, run in CI so they cannot rot
docs/KNOWN_LIMITATIONS.md   what does not work, and what it costs
docs/NEXT_LEVEL_PLAN.md     historical plan; several items already shipped

MIT。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。