mcpField
D
Durable Thinking

Durable Thinking

远程服务
github.comAI 与智能体25 周前更新

关于 Durable Thinking

Durable Thinking 是面向需要持久化顺序推理记录的客户端的自托管 MCP 服务。它保存提交的思考内容,支持续写、修订和分支,并可通过 MCP App 展示过程。

主要功能

  1. 01持久保存顺序思考记录
  2. 02续写、修订和分支序列
  3. 03分页读取历史记录
  4. 04删除已存储序列
  5. 05MCP App 可视化

适用场景

  1. 01稍后继续推理序列
  2. 02查看分支与修订过程
  3. 03隔离不同客户端会话的历史

MCP 相关

它向 MCP 客户端提供顺序思考、历史读取和删除工具。支持 MCP Apps 的宿主可显示思考卡片及完整历史。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://{worker_host}/mcp-compat
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

持久化思考

CI

面向 MCP 客户端的持久化顺序思考,运行于 Cloudflare Workers。

官方的 Sequential Thinking 服务会将思考内容保存在进程内存中,并在进程退出时将其遗忘。这个服务为思考内容提供了持久存储之处——采用相同的推理模型(可调整总数、继续、修订、分支),只是改为持久化存储,而不是丢弃。每一步都会写入由 SQLite 支持的 Cloudflare Durable Object,可通过一个不可猜测的 ID 在之后访问;对于支持 MCP Apps 的客户端,每一步还会单独渲染为一张卡片。

这是单用户部署:只允许一个 GitHub 账户通过登录验证,只为支持请求头的客户端提供一个 bearer token,使用一个私有存储,并提供一个部署按钮模板,方便你搭建自己的副本。

思考内容是什么样的

普通的 sequentialthinking 调用在任何客户端中都易于阅读:

Thought 3/5

A Durable Object keeps the application history persistent while the MCP HTTP
transport remains stateless.

Sequence: seq_... · 3 thoughts stored

结构化结果有意保持简短——其中不会重复包含思考内容本身:

{
  "sequenceId": "seq_...",
  "thoughtNumber": 3,
  "totalThoughts": 5,
  "thoughtHistoryLength": 3
}

支持 MCP Apps 的宿主会将相同的思考内容单独发送到 UI 资源:ui://sequential-thinking/process.html。宿主会为每次工具调用渲染一张卡片,因此 App 顺势采用这种方式,而不是试图与之对抗——每张卡片只显示自己的思考内容,无需轮询,也不会与其他卡片共享状态,而聊天记录本身则成为时间线。当序列结束(nextThoughtNeeded: false)时,最后一张卡片会加载完整的存储历史,并一次性呈现整个过程:按顺序显示每条思考内容,标记分支和修订,并将较早的步骤折叠起来,供用户展开。

App 是一个独立完整的 HTML 文档——没有外部脚本、字体或网络请求。它仅通过宿主经过身份验证的 MCP 连接获取历史记录。不支持 MCP Apps 的客户端只会收到纯文本结果。

每次写入时也不会重新传输所有思考内容——只传输当前这条。模型会有意重新加载较早的内容,使用 get_thought_history 即可。

能力范围限定的历史记录

没有用于列出序列的工具,也不会添加此类工具。首次调用返回的 sequenceId 是唯一的访问方式——它足够长,无法被猜出,也是检查历史记录时唯一使用的凭证。持有该 ID,就能读取对应序列;没有它,该序列对你而言便不存在。

这让一次部署可以同时服务许多客户端和会话,且彼此看不到对方的推理过程:身份验证让你进入大门,序列 ID 则让你进入房间。

工具

sequentialthinking

持久化一个推理步骤。首次调用时省略 sequenceId;继续时,每次都传入返回的 ID。

thought
nextThoughtNeeded
thoughtNumber
totalThoughts
sequenceId?
isRevision?
revisesThought?
branchFromThought?
branchId?
branchFromBranchId?
needsMoreThoughts?

将 branchId 与 branchFromThought 配对(从主路径分支),或添加 branchFromBranchId(从另一分支内部创建分支),即可创建分支;之后的步骤继续传入该 branchId。使用 isRevision: true 和 revisesThought 进行修订。

思考编号仅在写入它们的分支内有效,因此两个分支可以各自拥有思考 3——引用会先在当前写入的分支中解析,再沿其祖先分支回溯到每个分叉点,并采用最近作用域中的匹配项。

有两种边界情况会被接受,并在结果中标记,而不会被视为错误:在某条思考内容将 nextThoughtNeeded: false 设为 false 后继续序列,只会重新打开该序列;在同一分支上重复使用思考编号时,后续引用会解析到该编号最新的一次出现。

get_thought_history

返回按时间从早到晚排列的完整文本历史记录,并支持分页——将 nextCursor 作为 cursor 传回以继续(游标值是不透明的;不要计算它们)。传入 branchId 可将页面限制为单个分支;sequence.branches 会列出所有分支及其父分支和分叉点。

delete_thought_sequence

永久删除一个序列及其存储的文本。必须提供 confirm: true。

架构

MCP client
    │
    │ POST /mcp or /mcp-compat
    │ OAuth access token or static bearer token
    ▼
Cloudflare Worker
    │
    │ static token → straight to the MCP handler
    │ anything else → workers-oauth-provider validation
    │ fresh MCP server for each request
    ▼
ThoughtStore Durable Object: "personal"
    │
    ▼
SQLite tables for sequences, thoughts, and branches

MCP 传输是无状态的——不会将 Mcp-Session-Id 用作数据库键或连续性机制。所有应用状态都存储在 Durable Object 中,并通过工具参数中显式传入的 sequenceId 作为键。

服务器只会存储通过公开的 thought 参数提交的文本;服务器无法访问模型的私有或隐藏推理。

部署自己的实例

一键部署

部署到 Cloudflare

部署需要三个密钥:MCP_API_TOKEN(静态 Bearer 密钥——至少生成 32 个随机字节),以及下文 GitHub 登录部分所述 OAuth 应用的 GITHUB_CLIENT_ID 和 GITHUB_CLIENT_SECRET。

openssl rand -hex 32

你还需要自己的 OAuth KV 命名空间——运行 npx wrangler kv namespace create OAUTH_KV,然后将其 id 填入 wrangler.jsonc(命名空间 id 不是密钥)。

你将获得三个端点:

https://<worker>.<account>.workers.dev/mcp
https://<worker>.<account>.workers.dev/mcp-compat
https://<worker>.<account>.workers.dev/healthz
GitHub 登录

基于浏览器的客户端通过登录 GitHub 进行身份验证;只有列入允许列表的账户才能获得访问权限。

  1. 在 GitHub Developer settings 中创建 OAuth App——Homepage URL 为 https://<worker-host>,callback URL 为 https://<worker-host>/callback。
  2. 将凭据保存为 Worker 密钥:运行 npx wrangler secret put GITHUB_CLIENT_ID,然后运行 GITHUB_CLIENT_SECRET。
  3. 设置允许列表:运行 npx wrangler secret put ALLOWED_GITHUB_LOGIN——填写一个或多个以逗号分隔的 GitHub 登录名,匹配时不区分大小写。为空或缺失时将默认拒绝:无人可以完成授权。它被设为密钥而非 wrangler.jsonc 变量,因此持续部署不会覆盖它。

登录流程只读取你的 GitHub 身份,将其与允许列表进行核对,然后丢弃 GitHub 令牌。授权依据不可更改的账户 id,而非可以更改的登录名。

持续部署

GitHub Actions 会在每个拉取请求以及每次推送到 main 时运行 npm run verify;通过验证的 main 推送会使用 Wrangler 部署 Worker。部署不会重叠;如果缺少部署凭据,部署任务会正常跳过,例如在 fork 中就是如此。

在 Settings → Secrets and variables → Actions 下设置以下内容:

  • CLOUDFLARE_API_TOKEN——Workers Scripts:Edit 权限;
  • CLOUDFLARE_ACCOUNT_ID——拥有此 Worker 的账户。

这些凭据用于授权部署,与上文的运行时密钥分开。

发布到注册表

GitHub Releases 会通过 .github/workflows/publish-mcp.yml 将 Durable Thinking 元数据发布到官方 MCP Registry。该任务使用 GitHub OIDC,因此需要 id-token: write,但不需要长期有效的 Registry 凭据。server.json 声明了必需的 worker_host 变量和完整的 https://{worker_host}/mcp-compat URL,体现了项目由用户自行部署的模式,而不是引导陌生用户使用某个私有部署。

本仓库有意不发布到 npm。其 package.json 描述的是 Cloudflare 应用,没有 bin 或本地 stdio 传输;发布 npm 包并不能为客户端提供可安装的 MCP 服务。如果将来添加受支持的本地运行时,可以届时引入 npm Trusted Publishing,并提供真正的可执行文件、包所有权元数据和来源证明。

Smithery URL 的发布也与发布工作流分开。Smithery 需要一个具体的上游 URL,而每位 Durable Thinking 所有者都会部署一个带有 GitHub 允许列表的私有 Worker。只有当服务支持多用户托管访问模式,或 Smithery 直接支持由用户自行部署的 URL 模板时,才添加 Smithery。

手动部署

要求:Node.js 22+、已启用 Workers 和 Durable Objects 的 Cloudflare 账户,以及已完成身份验证的 Wrangler。

npm install
npm run verify
npm run secrets            # generates a local token

将结果复制到未提交的 .dev.vars 中(GitHub 相关字段请参阅 .dev.vars.example):

MCP_API_TOKEN=<generated token>
npm run dev

准备好发布时:

npx wrangler secret put MCP_API_TOKEN
npm run deploy
配置

wrangler.jsonc 声明了 Durable Object 和 KV 绑定。可选的 Worker 变量可通过 Cloudflare 或本地 .dev.vars 设置:

变量默认值用途
THOUGHT_RETENTION_DAYS00 表示序列会一直保留,直到显式删除;正值则启用滑动过期。
ALLOWED_HOSTNAMES自动可选的逗号分隔主机名允许列表,用于自定义域名。
ALLOWED_ORIGIN_HOSTNAMES支持的 Web 客户端和同主机可选的逗号分隔浏览器 Origin 主机名允许列表;设置后会替换默认的 Claude 和 ChatGPT Web 来源。

这里有意不提供公开模式、租户选择器、可配置的存储 ID、思考记录开关或自动返回近期历史记录的功能——只有一个用户,且 Durable Object 名称硬编码为 personal。轮换 MCP_API_TOKEN 或 OAuth 凭据不会导致历史记录失联;存储身份独立于这两者。

连接客户端

两种入口,一个服务。

浏览器登录——适用于无法发送自定义标头的托管客户端,包括 Claude 和 ChatGPT。添加一个自定义连接器或 MCP 应用,并将其指向完整的兼容 URL:

https://<worker-host>/mcp-compat

保留 /mcp-compat 路径:它是受保护资源标识符的一部分,并非可互换的路由细节。兼容端点支持当前托管客户端使用的 2025 年前后的 Streamable HTTP 协议。主机会发现 OAuth 端点,动态注册自己的回调,并打开 Durable Thinking 授权页面。继续前往 GitHub;如果你的登录名在允许列表中,主机就会获得自己的 Durable Thinking 访问令牌和刷新令牌。

GitHub OAuth App 仍使用 https://<worker-host>/callback,与部署时的配置一致。这是 Worker 的上游 GitHub 回调,与 Claude 或 ChatGPT 向 Worker 注册的重定向 URI 不同。

Bearer 标头——适用于 CLI 和任何支持标头的客户端:

Authorization: Bearer <MCP_API_TOKEN>

令牌完全匹配时会直接路由到 MCP 处理程序;OAuth 机制不会处理该请求。

仅对明确支持 MCP 2026-07-28 的客户端使用 /mcp。对当前托管 Web 客户端和其他 2025 年前后的 Streamable HTTP 客户端使用 /mcp-compat。

OAuth 故障排查

浏览器授权步骤不依赖第三方 Cookie。如果连接失败,请按顺序检查以下协议端点:

  1. 不带凭据向 POST /mcp-compat 发送请求,必须返回 401,并包含一个 WWW-Authenticate 标头,其中的 resource_metadata URL 以 /oauth-protected-resource/mcp-compat 结尾。
  2. 该元数据文档的 resource 值必须与 https://<worker-host>/mcp-compat 完全一致。
  3. /.well-known/oauth-authorization-server 必须公布 /authorize、/token、/register 和 S256 PKCE 支持。
  4. 如果设置了 ALLOWED_ORIGIN_HOSTNAMES,请加入托管客户端的主机名。未设置时,允许服务自身的主机以及支持的 Claude 和 ChatGPT Web 来源;其他来源仍会被拒绝。
  5. 授权页面的 CSP 必须允许 form-action 'self' https://github.com。早期部署只允许 'self',因此 Chrome 虽然接受了表单 POST,却阻止了其重定向到 GitHub。

Worker 日志使用固定的阶段和原因字段,不会记录授权码、状态值、访问令牌、客户端密钥或思考文本。

保留期限与隐私

思考文本可能包含私密提示词上下文、复制的凭据、个人信息或不确定的结论。服务会据此妥善处理:

  • 每个 MCP 请求都需要通过身份验证——使用已签发的 OAuth 令牌或 Bearer 密钥;
  • 绝不记录思考文本;
  • 一个仅由你拥有的私有 Durable Object;
  • 应用的 CSP 会阻止所有出站网络访问;
  • 可以显式删除序列,默认则会无限期保留。

CORS 和 MCP 应用可见性元数据不是身份验证控制措施——请对 Bearer 令牌保密。

开发

npm run check:app       # validates the self-contained MCP App and protocol surface
npm run check:contract  # guards the compact tool and visibility contract
npm run check:registry  # guards the official Registry manifest and version sync
npm run typecheck       # Worker and test TypeScript projects
npm run test            # Durable Object, auth, routes, and App invariants
npm run build           # Wrangler dry run
npm run verify          # all checks above

src/ui/thought-process.html 是应用的唯一可信来源;Wrangler 根据 wrangler.jsonc 中的规则将其作为文本模块导入。

src/index.ts                 Worker routes, authentication boundary, MCP handler
src/server.ts                tools, compact return shapes, MCP App resource
src/thought-store.ts         SQLite Durable Object implementation
src/oauth.ts                 GitHub sign-in and consent flow around the OAuth provider
src/ui/thought-process.html  per-thought MCP App card with final process view
src/auth.ts                  fixed personal bearer authentication
src/model.ts                 storage commands and records
test/                        Worker, storage, auth, and App tests

许可证

MIT。请参阅 LICENSE 和 NOTICE。

评论

支持 Markdown

第一次接触 MCP?

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

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