关于 Context Keeper (remote)
Context Keeper (remote) 是运行于 Cloudflare Workers 的 MCP 服务,将项目决策、流程和约束存入 D1 并供查询。它通过 Streamable HTTP 接入 Claude 会话,还提供只读手机视图以浏览决策依据。
主要功能
- 01记录和查询项目上下文
- 02基于 D1 的决策依据存储
- 03只读移动端项目视图
- 04自动迁移数据库架构
适用场景
- 01在 Claude 会话中查阅项目决策
- 02通过手机查看决策依据和约束
MCP 相关
它通过 Streamable HTTP 暴露 `record_entry`、`get_context` 和 `query_entries` 等 context-keeper 工具。Claude 可通过自定义连接器接入。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://context-keeper-remote.{account}.workers.dev/mcp/{token}claude mcp add --transport http jarmstrong158-context-keeper-remote https://context-keeper-remote.{account}.workers.dev/mcp/{token}{"mcpServers":{"jarmstrong158-context-keeper-remote":{"type":"http","url":"https://context-keeper-remote.{account}.workers.dev/mcp/{token}"}}}在 Cursor 中打开{"servers":{"jarmstrong158-context-keeper-remote":{"type":"http","url":"https://context-keeper-remote.{account}.workers.dev/mcp/{token}"}}}在 VS Code 中打开{"mcpServers":{"jarmstrong158-context-keeper-remote":{"type":"http","url":"https://context-keeper-remote.{account}.workers.dev/mcp/{token}"}}}{"mcpServers":{"jarmstrong158-context-keeper-remote":{"serverUrl":"https://context-keeper-remote.{account}.workers.dev/mcp/{token}"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
context-keeper-remote
xylem 技术栈的一部分。
一个运行在 Cloudflare Workers 上的远程 MCP 服务,通过 Streamable HTTP 提供 context-keeper 的决策存储(决策、流水线、约束)。它可用作 claude.ai 自定义连接器,也支持移动设备, 因此你可以在任何 Claude 会话中访问项目的决策和约束——无需让电脑保持运行,也无需隧道。
它还提供一个**手机应用**,供你自行查看该 存储:只需将它安装到主屏幕一次,之后打开即可使用,无需登录,URL 中也没有令牌。应用包含最近活动、各项目计数、cambium 知识和存储状态等标签页;点击任意条目即可查看完整的决策依据, 而不只是标题。此功能可选、需主动启用,并使用独立的只读凭据。
只需点击上方按钮,即可自托管一份副本——Cloudflare 会将此仓库复制到你的 GitHub 账户,为你新建一个 D1 数据库,并 部署 Worker。然后添加一个密钥,再将 URL 粘贴到 Claude 中。下方提供完整步骤;每一步都只需点击,无需使用命令行。
维护者自己的实例运行于
https://context-keeper-remote.jarmstrong158.workers.dev。部署后,你的实例将位于你自己的 子域名下。
为什么采用这种构建方式
- 使用 Worker,而非隧道——无需依赖“电脑必须开机”。
- 使用 D1,而非 KV——支持按行写入和
WHERE查询;两个写入方(桌面端 + 移动端)不会像对整个 JSON 文件进行读取-修改-写入那样互相覆盖。 - 无状态处理程序,不使用 Durable Objects——这些工具是针对 D1 的无状态 RPC,因此 Worker 可在 Cloudflare 免费计划上运行。
- 密钥路径身份验证——claude.ai 自定义连接器无法可靠地发送自定义 bearer 标头,因此令牌是 URL 的最后一个路径段。URL 本身就是 凭据。
- 自动迁移——Worker 会在运行时创建自己的 D1 架构,因此全新的空数据库无需手动运行 SQL(已通过冷启动测试验证)。
自托管(单击部署,无需命令行)
第 1 步——点击“部署到 Cloudflare”
点击本页面顶部的部署到 Cloudflare按钮。Cloudflare 将会:
- 请求你授权 GitHub 并选择一个账户——它会将此仓库复制到 你的 GitHub 账户(你将拥有自己的仓库)。
- 自动在你的 Cloudflare 账户中创建一个新的 D1 数据库,并将其绑定到 Worker。(之所以可行,是因为 Worker 的配置声明了数据库 绑定,但没有硬编码的 id,因此 Cloudflare 会为你创建一个全新的数据库。)
- 设置 Workers Builds,让你每次推送到新仓库时都能自动重新部署。
- 构建并部署 Worker。
部署完成后,你的 Worker 将运行在
https://context-keeper-remote.<your-subdomain>.workers.dev。记下这个 URL——第 3 步会用到。
(你也可以随时在控制面板的 Workers & Pages 下找到它。)
无需配置仓库,也无需运行 SQL——数据库初始为空,Worker 会在收到第一个请求时创建数据表。
步骤 2 — 添加 AUTH_TOKEN 密钥(Cloudflare 控制面板)
在设置身份验证令牌之前,Worker 会拒绝所有请求,因此请先设置一个:
- Cloudflare 控制面板 → Workers & Pages → 你的 context-keeper-remote Worker。
- Settings → Variables and Secrets → Add。
- 类型:Secret。名称:
AUTH_TOKEN。值:一串较长的随机字符串(32 个字符以上 — 请像密码一样妥善保管)。保存/部署。
该值就是连接器的密码。请妥善保存;下一步需要粘贴它。
还要部署配套的 agentsync-remote Worker 吗?
agentsync-remote 使用相同的 AUTH_TOKEN 方案,并且还需要在
它的 Worker 的 Variables and Secrets 中设置:
- 一个名为
GH_PAT的 Secret — GitHub 个人访问令牌,以及 - 一个名为
REPO的 Variable — 设置为它应同步的owner/repo。
这两项不适用于 context-keeper-remote(本仓库)——它只需要
AUTH_TOKEN。具体信息请参阅 agentsync-remote README。
步骤 3 — 在 claude.ai 中添加自定义连接器
-
claude.ai → Settings → Connectors → Add custom connector。
-
粘贴 Worker URL,并将令牌作为最后一个路径段:
https://context-keeper-remote.<your-subdomain>.workers.dev/mcp/<AUTH_TOKEN>将
<your-subdomain>替换为你的 Worker 子域名(步骤 1),并将<AUTH_TOKEN>替换为你设置的准确值(步骤 2)。 -
保存。现在,你可以在 Claude 会话中使用这些工具(
record_entry、get_context、query_entries……)。
**检查是否正常:**让 Claude 调用 get_project_summary。如果它能给出回答,说明整条链路(部署 → 自动配置 D1 → 自动迁移 → 身份验证)均正常运行。
步骤 4 — 迁移现有本地数据(可选)
如果你已经在运行本地版 context-keeper,请在启用连接器的情况下,让 Claude 调用
import_entries,并粘贴每个文件的内容:
decisions.json→import_entries(project, kind="decision", entries=[...])pipelines.json→import_entries(project, kind="pipeline", entries=[...])constraints.json→import_entries(project, kind="constraint", entries=[...])
导入的 ID 会保留;已存在的 ID 会被报告,但绝不会被覆盖。
步骤 5 — 安装手机视图(可选)
以上内容介绍的是 MCP 连接器,用于让 Claude 读取数据。步骤 5 则是让你通过手机读取数据。此步骤需要克隆本仓库并安装 Node 22+,这是整个设置过程中唯一需要使用命令行的环节——连接器本身完全不需要使用命令行。
请参阅下文的手机视图。
手机视图
/view 是一个只读的服务端渲染页面,展示每个项目的决策和约束。将它添加到主屏幕后,打开时就像一个应用:无需登录,URL 中没有令牌,也没有任何需要记住的内容。
![]() | ![]() |
| 最近 — 所有项目近期的变化 | 任意条目 — 查看决策依据,而不只是标题 |
![]() | ![]() |
| 项目 — 每个项目的计数,包括各规则集有多少内容可强制执行 | 健康状况 — 乱码、依据过少、未标记、过时 |
合成数据。上方的所有项目和条目均为虚构内容 — 数据集及重新生成方法请参见 docs/screenshots。
它有四个标签页,与桌面仪表板一致:
| 标签页 | 回答的问题 |
|---|---|
| 最近 | 所有项目近期有哪些变化 |
| 项目 | 每个项目的计数:条目、有效条目、约束、限定范围、替代关系链接、过时内容、乱码 |
| 知识 | cambium 的团队/组织计数(如果已接入,见下文) |
| 健康状况 | 乱码、依据过少、未标记、过时 — 按比例展示,并按项目排名 |
轻点任意行即可查看完整条目:问题、选择该方案的原因、最初尝试过的方法、权衡、备选方案及其被否决的原因;如果是约束,还会显示范围、强度和强制执行方式。搜索涵盖所有字段,包括决策依据,而答案通常就在其中。已被替代的条目仍可访问,每个条目都会链接到它替代的内容以及替代它的内容。
安装
1. 创建凭据。 双击 scripts/set-view-token.cmd
(macOS/Linux:scripts/set-view-token.sh)。在终端中使用绝对路径 — 不要使用 npm run,因为它要求当前目录为仓库目录:
powershell -NoProfile -ExecutionPolicy Bypass -File "/full/path/to/context-keeper-remote/scripts/set-view-token.ps1"
运行一次即可生成令牌、安装令牌、等待路由返回 200、复制 URL、在浏览器中打开 URL,并打印二维码。
2. 用手机扫描二维码,然后安装:
- Android / Chrome — 横幅会提供安装选项,也可以使用 ⋮ → 安装应用。 如果菜单中只有添加到主屏幕,说明清单未满足 Chrome 的安装条件;通常是缺少 192x192 图标,导致 Chrome 不提示地降级为普通快捷方式,并在浏览器标签页中打开。
- iPhone — 必须使用 Safari(iOS 上的 Chrome 无法安装 Web 应用)。 分享 → 添加到主屏幕。
趁有网络时,依次打开“最近”“项目”“知识”和“健康状况”一次 — 离线缓存只会缓存你实际打开过的页面。
添加 -DryRun 可运行除安装之外的所有步骤,这是在进行任何更改前检查设置是否正确的最快方式。
离线可用,轻点即开
Service worker 会缓存你打开的每个页面,优先使用缓存,同时在后台重新验证。以下是在线实例上的实测数据:
| 从缓存提供 | 1 ms |
| 强制通过网络加载 | 278–383 ms |
因此,即使没有信号也能打开,切换标签页也是瞬间完成,而不必等待一次往返。决策日志不是实时动态流——立即显示昨天的答案,再过一会儿将其更正,总比等 300ms 什么都看不到好;页眉会标注“8h ago”,因此不会把过期数据显示成当前数据。
只缓存 200 响应。 对于未经身份验证或已轮换的凭据,此 Worker 会返回 404;如果缓存了这个响应,就意味着轮换令牌的设备会一直被告知已退出登录——响应来自本地磁盘,无需网络,也没有明显的方法清除它。已验证这两种情况。
令牌仍然永远不会传到 JavaScript。 Cookie 设置了 HttpOnly,因此 service worker 无法读取它;它只会发起同源请求,由浏览器附加 Cookie。放弃的是“完全不使用客户端 JS”,而不是凭据隔离。CSP 会添加 script-src 'self',并有意不添加 'unsafe-inline'——注册代码放在单独的文件中,因此不需要允许内联脚本;这种许可会作用于整个文档,包括任何通过转义器混入的记录条目。
如何保持登录状态
令牌 URL 是一个注册步骤,而非日常操作。访问该 URL 会设置一个长期有效的 HttpOnly Cookie;之后,该设备就可以直接访问 /view 路径——主屏幕图标打开的正是这个路径。
- 不会扩大权限范围。 Cookie 携带的机密与路径中的相同,比较方式也相同,因此轮换
VIEW_TOKEN仍会立即撤销所有设备的访问权限。只有一种撤销方式,没有会话表,也无需跟踪过期时间。 - 使用独立凭据。 查看页面从不接受
AUTH_TOKEN,/mcp也从不接受VIEW_TOKEN。泄露查看 URL 会暴露决策摘要,但无法写入、弃用或删除内容。 - 未设置即视为失效。 如果没有
VIEW_TOKEN,/view/<anything>会返回纯404,与从未部署过的路由无法区分。
之后运行 npm run view 可重新打开页面(URL 会保存到 .view-url,并由 git 忽略)。
运行 npm run view -- --qr 可为另一台设备注册,而不会轮换令牌——重新运行设置会生成一个新令牌,并悄无声息地移除所有已添加设备的访问权限。
将 Knowledge 标签页连接到 cambium-remote(可选)
仅当你也运行 cambium-remote 时才相关。
scripts/connect-cambium.cmd
它会生成一个仅用于状态的凭据,将其安装到 cambium-remote 并设为
STATUS_TOKEN,验证路由返回真实计数,然后才在此处设置
CAMBIUM_STATUS_URL。无需查找或粘贴任何内容。
**为什么要使用第二个凭据,而不是 cambium 的连接器 URL:**该 URL 是
cambium-remote 的 AUTH_TOKEN,它可以对所有已提升的项目执行
recall——其所在 Worker 的团队范围可触及 TEAM_OWNER 下的所有仓库,
包括私有仓库。将它复制到此处只为显示三个整数,意味着这个 Worker 一旦泄露,
就会暴露 cambium 的全部访问范围。STATUS_TOKEN 只能读取计数,不能做其他操作。
它还可以自动生成,这正是设置能够自动完成的原因;AUTH_TOKEN 只能手动
重新输入,因为 Cloudflare 以只写方式存储密钥。
**自托管用户必须添加服务绑定。**Worker 无法通过提取另一个
Worker 的 workers.dev 主机名来访问它——Cloudflare 边缘会返回 404,
目标 Worker 根本不会运行,这看起来就和令牌被拒绝完全一样。在你的
wrangler.toml 中添加:
[[services]]
binding = "CAMBIUM"
service = "cambium-remote"
本仓库仅在 [env.production] 下声明它,这是有意为之:服务绑定会指定其目标,
因此若在顶层声明,就会导致没有 cambium-remote 的用户无法一键部署。
面板会优雅地处理失败。如果 cambium 响应缓慢(预算为 10s)、宕机或未连接, 页面仍会渲染并说明情况。只有 Knowledge 标签页会发起该调用,因此其他标签页 不会受影响。
推送时部署,无需 API 令牌
git push 可以直接部署 Worker,使用你已有的 wrangler 登录状态——无需
Cloudflare API 令牌、GitHub 密钥或控制面板:
scripts/install-deploy-hook.cmd
它会安装一个 git pre-push 钩子。先部署,再推送:如果部署失败,推送就会中止,
因此 origin 永远不会收到无法部署的提交。这正好与它所替代的失败情况相反——
cambium-remote 的 CI 接受了每一次合并,却一次也没有部署,导致 main 超前于
正在运行的 Worker,而且没有任何迹象表明这一点。
仅针对 Main,跳过分支删除;git push --no-verify 可跳过一次,-Remove 可卸载。
如果仓库有命名环境,没有 -Env 就拒绝安装,这项限制事关安全,并非吹毛求疵。
不带参数的 wrangler deploy 会使用顶层配置——而本仓库的顶层配置是自托管配置,
它有意省略了 database_id,因此 Cloudflare 会创建一个全新的空数据库。
如果在此处不带 -Env 安装钩子,下一次推送时就会将线上 Worker 绑定到一个空 D1。
因此:
# cambium-remote -- no named environments, bare deploy is correct
scripts/install-deploy-hook.cmd
# a repo whose real deploy lives under [env.production]
scripts/install-deploy-hook.cmd -Env production
本仓库完全不需要这个钩子——它的 GitHub Actions 部署正常运行,而钩子会让每次推送 都部署两次。
**为什么不直接修复 CI?**因为这一步确实无法自动化。
GitHub Actions 需要 CLOUDFLARE_API_TOKEN,而通过 API 创建 Cloudflare API 令牌
需要已有一个具备 User API Tokens: Edit 权限的令牌。
Wrangler 的 OAuth 登录没有该权限——它的 29 个权限范围涉及 workers/d1/pages/
queues 操作以及 account:read,没有任何与令牌管理相关的权限。**你机器上的任何凭据
都无法创建这个凭据。**粘贴令牌是 Cloudflare 权限模型所要求的,并非工具存在缺陷。
在本地部署可以完全绕过这个问题。
如果你还是想使用 GitHub Actions CI
如果 connect-cambium 发现缺少状态路由,就会使用你已有的 wrangler 登录自行部署 cambium-remote,因此 Knowledge 标签页正常工作并不需要 GitHub Actions 部署成功。
只有在你希望 cambium-remote 每次推送时自动部署,才需要它。其工作流需要两个 Cloudflare 密钥,其中任意一个为空都会悄无声息地失败:每次合并看起来都是绿色,但不会部署任何内容。
scripts/fix-cambium-ci.cmd
CLOUDFLARE_ACCOUNT_ID 会从 wrangler whoami 读取并自动设置——它是标识符,不是凭据;每个仪表板 URL 中都有它。
CLOUDFLARE_API_TOKEN 需要由你粘贴一次,这一步确实无法省略:创建 Cloudflare API 令牌需要一个具有 User API Tokens: Edit 权限的现有令牌,而 wrangler 的 OAuth 登录不具备该权限。你机器上的任何凭据都无法创建这个凭据。除此之外,所有步骤都会自动完成——浏览器会打开正确的页面,读取令牌时不会回显,存储前会先通过 Cloudflare API 验证令牌,两个密钥都会通过 stdin 而非 argv 传递,并且会重新触发之前失败的运行,让你亲眼看到它变成绿色,而不是只听脚本保证。
设置 Worker URL(自托管用户)
没有任何 wrangler 命令会报告 workers.dev 主机名——whoami、deployments list、versions list 和 deployments status 都不会——因此它保存在 package.json 中:
node -e "const p=require('./package.json');p.contextKeeper.workerUrl='https://<worker>.<account>.workers.dev';require('fs').writeFileSync('package.json',JSON.stringify(p,null,2)+'
')"
设置脚本会在安装任何内容之前读取该值,如果没有 URL 就会拒绝运行。这个顺序是有意安排的:如果安装令牌时没有可写入的 URL,就无法恢复,因为 Cloudflare 不允许读取已保存的密钥。
坦诚说明平台支持情况
| 脚本 | Windows | macOS / Linux |
|---|---|---|
set-view-token | .cmd / .ps1 | .sh |
connect-cambium | .cmd / .ps1 | 尚未移植——见下文 |
install-deploy-hook | .cmd / .ps1 | 尚未移植——见下文 |
fix-cambium-ci | .cmd / .ps1 | 尚未移植——见下文 |
尚未移植的三个脚本只是对少量命令的简单封装,因此手动执行也很简单。连接 cambium:
TOKEN=$(head -c 32 /dev/urandom | base64 | tr '+/' '-_' | tr -d '=
')
printf '%s' "$TOKEN" | (cd ../cambium-remote && npx wrangler secret put STATUS_TOKEN)
# wait ~60s for the new version to roll out, then check it answers with counts:
curl -s "https://cambium-remote.<account>.workers.dev/status/$TOKEN" | head -c 200
printf '%s' "https://cambium-remote.<account>.workers.dev/status/$TOKEN" | npx wrangler secret put CAMBIUM_STATUS_URL --env production
推送时部署——在目标仓库中编写 .git/hooks/pre-push,使用 LF 换行符,并运行 chmod +x 和 npx wrangler deploy(如果该仓库有命名环境,则添加 --env <name>——在这种情况下直接执行部署会指向 self-host 配置,并将线上 Worker 绑定到一个全新的空数据库)。
修复 CI——在仓库中执行 gh secret set CLOUDFLARE_ACCOUNT_ID 和 gh secret set CLOUDFLARE_API_TOKEN,并分别从 stdin 读取值。
编辑设置脚本
这些脚本面向 Windows PowerShell 5.1——也就是随 Windows 附带的版本,也是 .cmd 启动的版本。有五处关键设置看似可以现代化,但实际不能:
- 使用
RNGCryptoServiceProvider,而不是RandomNumberGenerator::Fill——后者仅适用于 .NET Core,会抛出异常。 - 手动提取
WebException状态,而不是使用-SkipHttpErrorCheck——它仅适用于 PowerShell 7。 - 不使用
??、?.或三元运算符——它们都仅适用于 PowerShell 7,在这里会导致解析错误。 - 所有 wrangler 调用都通过
Invoke-Wrangler执行。在 5.1 中,对原生命令使用2>&1会将每一行 stderr 包装为 ErrorRecord;在$ErrorActionPreference = 'Stop'的情况下,第一条就会成为终止错误——所以普通的 wrangler 通知也会中断运行。 - 确认步骤使用
[Console]::IsInputRedirected作为判断条件,绝不使用[Environment]::UserInteractive(它始终为 true);并且会先将Read-Host转换为[string]再进行匹配——$null -notmatch '...'的结果是 empty,而不是$true,所以看似显而易见的保护条件会默认放行。
每次运行都会写入一份已清除敏感信息的日志(.view-setup.log、.cambium-setup.log),并遮蔽令牌,因此即使窗口关闭后,也能查看失败原因。
⚠️ 安全:连接器 URL 就是凭据
你粘贴到 Claude 中的 URL 会在最后一个路径段中嵌入 AUTH_TOKEN。
任何拿到完整 …/mcp/<AUTH_TOKEN> URL 的人,都可以读取和写入你的整个存储。
请像对待密码一样对待它:
- 不要分享、截图,也不要粘贴到任何可能记录它的位置。
- 请求任何其他路径或使用错误令牌的请求,都会得到不含任何详情的
404(有效令牌用于非 POST 方法时,会得到405)。 - 轮换令牌:在 Cloudflare 控制面板中更改
AUTH_TOKEN(第 2 步)。这会立即使所有旧 URL 失效——使用旧令牌的任何连接器都会开始收到404,直到你在 claude.ai 中更新连接器(第 3 步),填入新值。
本节中的所有内容也适用于查看 URL,但有一点对你有利:VIEW_TOKEN 只能读取。泄露查看 URL 会暴露此实例中每个项目的所有决策摘要,这很可能是更敏感的一半——但它无法写入、弃用或删除任何内容。这就是两者使用不同凭据而非共用一个凭据的全部原因。
为什么令牌位于 URL 路径中,以及这样做的代价
这是经过深思熟虑的设计选择,并非疏忽。claude.ai 自定义连接器无法可靠地发送自定义标头,因此不能依赖 Authorization: 标头这一显而易见的替代方案。将凭据放入路径中,才能让连接器正常工作。
请清楚了解这样做的代价,因为它与使用标头不同:
- URL 会被记录在请求正文永远不会出现的地方。浏览器历史记录、Shell 历史记录、代理和 CDN 访问日志、崩溃报告、错误报告、截图、“复制链接”按钮,以及Agent 会话记录。在生成本节内容的审计过程中,在一台机器上的 13 份本地会话记录中发现了约 54 处这些 Worker 的连接器 URL——没有一处是刻意粘贴的;它们只是 Agent 回显的工具配置的一部分。
- **Worker 本身不会记录令牌。**每条日志都会将路由记录为
/mcp/***。泄露面是 Worker 周围的一切,而这些正是你无法审计的部分。 - **令牌一旦泄露就意味着拥有完整访问权限,没有第二重验证,也没有逐个调用方的身份信息。**除了令牌本身,没有其他内容可以撤销;也没有日志能告诉你是谁使用了它。
实用建议:
- 按计划轮换令牌,不要等到怀疑令牌泄露时才轮换——假设 URL 已被记录在某个你无法控制的地方。轮换成本很低:更改
AUTH_TOKEN,然后更新连接器。 - 如果你分享过终端录屏、会话记录、屏幕截图,或来自已配置该连接器的机器的错误报告,请立即轮换令牌。
- 使用足够长的随机令牌(至少 32 字节,例如
openssl rand -hex 32)。无论内容还是长度,比较都采用恒定时间,因此无法通过观察获知长度——但熵仍然是你抵御猜测的唯一保障。 - 如果你有机会改用标头或 OAuth,就这么做。这是客户端迫使我们做出的权衡,而非首选方案。
工具
每个工具都接受可选的 project;如果省略,则使用已配置的
default_project(通过 config 设置一次:op='set',键为 default_project)。
统一工具(config、record_entry)是当前接口;旧的按操作划分的工具仍作为已弃用别名保留,以便现有调用方继续使用。新开发应优先使用统一工具。
| 工具 | 用途 |
|---|---|
config | 读取或写入配置:op='get' 读取键,op='set' 写入键(需要 value)。使用键 default_project(全局范围,不带 project)来指定未提供 project 时调用所用的项目。 |
set_config / get_config | config(op='set') / config(op='get') 的已弃用别名。 |
record_entry | 统一写入:记录 decision、constraint 或 pipeline。必填字段因类型而异——decision 需要 summary,constraint 需要 rule,pipeline 需要 name。 |
record_decision | record_entry(kind='decision') 的已弃用别名:summary、problem、why_chosen、what_we_tried、tradeoffs、tags。 |
record_constraint | record_entry(kind='constraint') 的已弃用别名:必须遵守的规则——rule、reason、tags。 |
record_pipeline | record_entry(kind='pipeline') 的已弃用别名:可复用流程——name、purpose、steps(额外字段会原样保留)。 |
get_context | 根据查询进行相关性排序检索(关键词评分;除非设置 include_deprecated,否则排除已弃用条目)。取代其他条目的记录会附带一行 predecessor——说明前一条记录的内容及其变更原因;此内容与本地服务中的字节完全一致,因此通过任一传输方式查看历史记录时都相同。 |
query_entries | 结构化筛选:id、kind、tags(必须全部匹配)、status(active/deprecated/all)、自由文本 text 和 limit。 |
get_project_summary | 一次调用即可了解项目概况:按类型和状态统计的条目数量、已有的 ID、当前生效的约束(精简版)以及最近的决策。 |
list_projects | 组织注册表:列出每个含有条目的项目,以及各项目当前生效条目的数量(decisions/constraints/pipelines)、当前生效/已弃用条目总数和最后更新时间。一次调用即可列举整个组织,查找准确、区分大小写的项目名称,无需猜测。 |
update_entry | 将 patch 字段合并到条目的载荷中;也可选择更改 status。 |
deprecate_entry | 将条目标记为已弃用;可选择关联 superseded_by 并记录 reason(前置条目行引用的就是此原因)。 |
reload_constraints | 当前生效约束的精简列表。 |
prune_stale | 删除较旧的已弃用条目(默认试运行;传入 dry_run=false)。 |
verify_quality | 标记缺少说明理由字段的条目。 |
export_markdown | 将条目渲染为 DECISIONS.md 风格的文档。 |
import_entries | 从本地 JSON 存储格式批量导入(保留 ID 和生命周期状态,包括 superseded;报告冲突,绝不覆盖)。 |
upsert_entries | 使用本地存储格式批量 upsert——用于镜像同步。插入新 ID;仅当传入的 updated_at 严格更新时才替换已有 ID(按时间戳采用最后写入者胜出),否则跳过。在镜像存储间传递编辑和弃用状态;绝不删除。 |
条目约定
- 决策使用
summary、problem、why_chosen、what_we_tried、tradeoffs、tags。输入中接受已弃用的rationale字段;若未提供why_chosen,则将其映射到why_chosen。 - 约束使用
rule、reason、tags。 - 流程使用
name、purpose、steps,以及你传入的任何额外字段。 - ID按项目和类型划分:
dec-001、pipe-003、con-012。由于不同项目中可能出现相同 ID,D1 主键采用复合键(project, id)。
面向维护者 / 贡献者
以上内容面向可自托管用户。本节介绍如何参与代码本身的开发。
配置布局:一个仓库如何同时服务于按钮和 CI
wrangler.toml 有两个配置档:
- 默认(顶层) — D1 绑定声明时不带
database_id。 部署按钮、wrangler dev和本地测试套件都会使用此配置。没有 ID 时,Cloudflare 会为每个自托管用户自动配置一个全新的数据库。 [env.production]— 固定维护者的实际database_id和 Workername。维护者的 CI 使用wrangler deploy --env production部署,因此始终连接到同一个数据库和同一个 URL。自托管用户绝不会使用此环境。
cambium 服务绑定仅存在于 [env.production] 中,这种拆分至关重要,而不只是为了整洁。服务绑定会指定目标 Worker,因此顶层的 [[services]] service = "cambium-remote" 会导致一键部署在没有此 Worker 的任何账户中失败——也就是除维护者账户之外的所有账户。出于同样的原因,任何指定其他 Worker、通过 ID 指定其他数据库或指定其他账户的配置,都应放在命名环境中。
命名环境不会继承任何配置。生产部署需要的每个绑定都必须在 [env.production.*] 下重复声明,包括 [observability]。只存在于顶层的绑定,在 CI 实际部署的环境中会被静默忽略。
部署流水线(仅限维护者)
.github/workflows/deploy.yml 会在推送到 main 时运行,并受
if: github.repository == 'jarmstrong158/context-keeper-remote' 条件限制,这样分支仓库(通过 Workers Builds 部署)就不会运行失败的 Actions。步骤:检出代码 →
Node 22(Wrangler 需要 ≥ 22)→ npm ci → npm test → wrangler deploy --env production。测试通过后才会部署。它会读取两个 GitHub 仓库密钥:
CLOUDFLARE_API_TOKEN(需要 Workers Scripts: Edit)和 CLOUDFLARE_ACCOUNT_ID
——这两个都不同于 Worker 自身的 AUTH_TOKEN。
本地开发
无需网络,也不需要 Cloudflare 凭据——测试通过 @cloudflare/vitest-pool-workers,在本地 workerd D1 上运行。需要 Node ≥ 22。
npm install
npm test # vitest: migrations, cold-start, CRUD, id sequencing, auth, import, ...
npm run typecheck # tsc --noEmit
线上冒烟测试
部署后,可在任何能访问网络的机器上运行:
WORKER_URL="https://context-keeper-remote.<subdomain>.workers.dev/mcp/<AUTH_TOKEN>" \
node scripts/smoke-test.mjs
它会针对线上 Worker 依次运行 initialize → tools/list → record_decision → query_entries。
目录结构
src/index.ts fetch handler: token check -> MCP dispatch (schema ensured lazily on first tools/call, not on the handshake)
src/mcp.ts stateless Streamable HTTP MCP server (createMcpHandler)
src/db.ts D1 access + runtime migration runner + id generation
src/entries.ts payload normalization, insert-with-retry, keyword scoring
src/tools/*.ts one module per tool group
src/view.ts the phone view: shell, tabs, knowledge panel, dispatch on ?e/?p/?q/?t
src/detail.ts entry detail, project drill-down, search, supersession trail
src/health.ts quality flags + the Projects and Health tables
src/install.ts enrolment cookie, web app manifest, home-screen icon
src/icon-data.ts GENERATED by scripts/make-icon.mjs -- do not hand-edit
schema.sql reference copy of the DDL the migration runner embeds
wrangler.toml default (auto-provision) + [env.production] (pinned) config
.github/workflows/deploy.yml test-then-deploy on push to main (maintainer repo)
scripts/smoke-test.mjs live JSON-RPC round-trip check
scripts/set-view-token.* create VIEW_TOKEN, verify, QR, save the URL (.cmd = double-click)
scripts/connect-cambium.* generate STATUS_TOKEN on cambium-remote and wire it here
scripts/make-icon.mjs regenerate the home-screen PNG (npm run make-icon)
test/ vitest suite (local workerd D1, no network)
维护者部署故障排查
| Actions 日志中的症状 | 原因 | 修复方法 |
|---|---|---|
Wrangler requires at least Node.js v22.0.0 | Node < 22 | 已在 deploy.yml 中设为 Node 22。 |
it's necessary to set a CLOUDFLARE_API_TOKEN environment variable | 缺少部署密钥 | 添加两个 GitHub 仓库密钥。 |
No route for that URI [code: 7000] / object identifier is invalid [code: 7003] | API token 缺少 Workers 权限,或 CLOUDFLARE_ACCOUNT_ID 错误 | 使用“Edit Cloudflare Workers” token;确认账户 ID。 |
部署成功,但每次调用都返回 404 | 未设置 Worker AUTH_TOKEN,或 URL 中的 token 与其不匹配 | 在 Cloudflare 控制面板中设置/验证 AUTH_TOKEN。 |
相关项目
- context-keeper — 此 Worker 以远程传输方式托管的本地 stdio 原版。
- xylem — 此项目所属的技术栈。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。



