Durable Thinking

io.github.linxule由 GitHub 帳號 linxule 發布v3.2.0更新於 Nov 8, 2026

Self-hosted persistent sequential thinking with private history and MCP App visualization.

已驗證Streamable HTTP可網頁執行雲端與基礎設施知識與記憶AI 與機器學習

概覽

AI 產生的概覽

一個自架的 Cloudflare Workers 伺服器,為助理提供可持久保存的循序思考,每一步推理都私密儲存,並可透過不可猜測的 ID 取回。

可以做什麼
記錄推理步驟,支援可調整總數、續接、修訂與分支,每一步都以首次呼叫回傳的序列 ID 持久保存。重新載入已存歷史,可分頁並依分支篩選,以便刻意回顧先前的想法。刪除整個序列及其儲存文字,需要明確確認。在支援 MCP Apps 的宿主中把每個想法呈現為卡片,最後一張卡片顯示完整過程。
適用情境
適合希望助理的逐步推理在單次工作階段之後仍然保留並可日後回顧,且願意自行執行 Cloudflare 部署的情況。適合希望跨用戶端與工作階段擁有私密、持久思考歷史的單一使用者。
執行需求
需要自行部署的 Cloudflare Worker,啟用 Workers 與 Durable Objects,並從專案範本部署;沒有公開的託管端點。部署需要 Node.js 22+、已驗證的 Wrangler、一個 OAuth KV 命名空間,以及密鑰 MCP_API_TOKEN、GITHUB_CLIENT_ID、GITHUB_CLIENT_SECRET 和 ALLOWED_GITHUB_LOGIN。用戶端透過 GitHub 登入或 Authorization bearer 標頭連線至 worker 的 /mcp-compat 或 /mcp 路徑。
安裝前請注意
思考文字可能包含私密提示內容、複製的憑證或個人資訊,預設情況下序列會無限期保留,除非設定 THOUGHT_RETENTION_DAYS 或刪除序列。序列 ID 是存取某段歷史的唯一鑰匙,持有它的人即可讀取該序列。請對 MCP_API_TOKEN 與 GitHub OAuth 密鑰保密;CORS 與應用程式可見性中繼資料不是身分驗證。刪除序列是永久性的。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Durable Thinking,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Durable Thinking

[CI]

Persistent sequential thinking for MCP clients, on Cloudflare Workers.

The canonical Sequential Thinking server keeps thoughts in process memory and forgets them when the process exits. This one gives them somewhere durable to live — the same reasoning model (adjustable totals, continuation, revision, branching), just persisted instead of discarded. Every step is written to a SQLite-backed Cloudflare Durable Object, addressable later by an unguessable id, and — for clients that support MCP Apps — rendered as a card of its own.

It's a single-user deployment: one GitHub account allowed through the sign-in gate, one bearer token for header-capable clients, one private store, and a deploy-button template for standing up your own copy.

What a thought looks like

A normal sequentialthinking call stays readable in any client:

text
Thought 3/5
A Durable Object keeps the application history persistent while the MCP HTTPtransport remains stateless.
Sequence: seq_... · 3 thoughts stored

The structured result stays deliberately small — the thought itself isn't repeated in it:

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

MCP Apps-capable hosts get the same thought delivered separately, to a UI resource: ui://sequential-thinking/process.html. Hosts render one card per tool call, so the App leans into that instead of fighting it — each card shows only its own thought, no polling, no state shared with other cards, and the chat transcript itself becomes the timeline. When the sequence finishes (nextThoughtNeeded: false), that last card loads the full stored history and renders the entire process at once: every thought in order, branches and revisions marked, earlier steps collapsed and expandable.

The App is one self-contained HTML document — no external scripts, fonts, or network calls. It reaches history only through the host's authenticated MCP connection. Clients without MCP Apps support just get the plain text result.

Thoughts aren't retransmitted on every write, either — only the current one. The model reloads earlier ones on purpose, with get_thought_history.

Capability-scoped history

There's no tool to list sequences, and none is coming. The sequenceId handed back from the first call is the only way in — long enough to be unguessable, and the sole credential its history checks. Hold the id, read the sequence; don't have it, and it doesn't exist for you.

That's what lets one deployment serve many clients and sessions at once without any of them seeing each other's reasoning: authentication gets you in the door, the sequence id gets you into a room.

Tools

sequentialthinking

Persists one reasoning step. Omit sequenceId on the first call; carry the returned id through every continuation.

text
thoughtnextThoughtNeededthoughtNumbertotalThoughtssequenceId?isRevision?revisesThought?branchFromThought?branchId?branchFromBranchId?needsMoreThoughts?

Branch by pairing branchId with branchFromThought (forking from the main path) or adding branchFromBranchId (forking from inside another branch), then keep passing that branchId on later steps. Revise with isRevision: true and revisesThought.

Thought numbers are scoped to the branch writing them, so two branches can each have their own thought 3 — a reference resolves against the branch being written, then its ancestors back to each fork point, nearest scope wins.

Two edge cases are accepted and flagged in the result rather than treated as errors: continuing a sequence after a thought said nextThoughtNeeded: false just reopens it, and reusing a thought number on the same branch resolves later references to its newest occurrence.

get_thought_history

Returns full-text history, oldest-first and paginated — pass nextCursor back as cursor to continue (cursor values are opaque; don't compute them). Pass branchId to restrict the page to one branch; sequence.branches lists every branch with its parent and fork point.

delete_thought_sequence

Permanently deletes a sequence and its stored text. Requires confirm: true.

Architecture

text
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

The MCP transport is stateless — no Mcp-Session-Id is used as a database key or continuity mechanism. All application state lives in the Durable Object instead, keyed by the sequenceId passed explicitly in tool arguments.

Only text submitted through the public thought argument is ever stored; the server has no access to a model's private or hidden reasoning.

Deploy your own

One click

[Deploy to Cloudflare]

Deployment requires three secrets: MCP_API_TOKEN (the static bearer — generate at least 32 random bytes), plus GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET from the OAuth app described under GitHub sign-in below.

bash
openssl rand -hex 32

You'll also need your own OAuth KV namespace — npx wrangler kv namespace create OAUTH_KV, then put its id in wrangler.jsonc (namespace ids aren't secrets).

You'll get three endpoints:

text
https://<worker>.<account>.workers.dev/mcphttps://<worker>.<account>.workers.dev/mcp-compathttps://<worker>.<account>.workers.dev/healthz

GitHub sign-in

Browser-based clients authenticate by signing in to GitHub; access is granted only to allowlisted accounts.

  1. Create an OAuth App under GitHub Developer settings — Homepage URL https://<worker-host>, callback URL https://<worker-host>/callback.
  2. Store its credentials as Worker secrets: npx wrangler secret put GITHUB_CLIENT_ID, then GITHUB_CLIENT_SECRET.
  3. Set the allowlist: npx wrangler secret put ALLOWED_GITHUB_LOGIN — one or more comma-separated GitHub logins, matched case-insensitively. Empty or missing fails closed: nobody can complete authorization. It's a secret rather than a wrangler.jsonc var so continuous deploys never overwrite it.

The sign-in flow reads only your GitHub identity, checks it against the allowlist, and discards the GitHub token. Authorization is keyed to the immutable account id, not the renameable login.

Continuous deployment

GitHub Actions runs npm run verify on every pull request and every push to main; a verified push to main deploys the Worker with Wrangler. Deploys never overlap, and the deploy job skips gracefully when its credentials are absent — as in a fork.

Set these under Settings → Secrets and variables → Actions:

  • CLOUDFLARE_API_TOKEN — Workers Scripts: Edit permission;
  • CLOUDFLARE_ACCOUNT_ID — the account that owns the Worker.

These authorize deployment and are separate from the runtime secrets above.

Registry publication

GitHub Releases publish Durable Thinking metadata to the official MCP Registry through .github/workflows/publish-mcp.yml. The job uses GitHub OIDC, so it needs id-token: write but no long-lived Registry credential. server.json advertises a required worker_host variable and the complete https://{worker_host}/mcp-compat URL, reflecting the project's deploy-your-own model rather than directing strangers to one private deployment.

This repository is deliberately not published to npm. Its package.json describes a Cloudflare application and has no bin or local stdio transport; an npm artifact would not give clients an installable MCP server. If a supported local runtime is added later, npm Trusted Publishing can be introduced then, with a real executable, package ownership metadata, and provenance.

Smithery URL publication is also separate from the release workflow. Smithery expects one concrete upstream URL, while each Durable Thinking owner deploys a private Worker with a GitHub allowlist. Add Smithery only if the service gains a multi-user hosted access model or Smithery supports the deploy-your-own URL template directly.

By hand

Requirements: Node.js 22+, a Cloudflare account with Workers and Durable Objects enabled, Wrangler authenticated.

bash
npm installnpm run verifynpm run secrets            # generates a local token

Copy the result into an uncommitted .dev.vars (see .dev.vars.example for the GitHub fields):

dotenv
MCP_API_TOKEN=<generated token>
bash
npm run dev

When ready to ship:

bash
npx wrangler secret put MCP_API_TOKENnpm run deploy

Configuration

wrangler.jsonc declares the Durable Object and KV bindings. Optional Worker variables, set via Cloudflare or a local .dev.vars:

VariableDefaultPurpose
THOUGHT_RETENTION_DAYS00 retains sequences until explicit deletion; a positive value enables sliding expiration.
ALLOWED_HOSTNAMESautomaticOptional comma-separated host allowlist, for custom domains.
ALLOWED_ORIGIN_HOSTNAMESsupported web clients and same-hostOptional comma-separated browser-Origin hostname allowlist; setting it replaces the default Claude and ChatGPT web origins.

There's deliberately no public mode, tenant selector, configurable storage id, thought-logging switch, or automatic recent-history return — one user, one hard-coded Durable Object name: personal. Rotating MCP_API_TOKEN or the OAuth credentials doesn't orphan history; storage identity is independent of both.

Connect your clients

Two doors, one server.

Browser sign-in — for hosted clients that can't send custom headers, including Claude and ChatGPT. Add a custom connector or MCP app pointing at the complete compatibility URL:

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

Keep the /mcp-compat path: it is part of the protected resource identifier, not an interchangeable routing detail. The compatibility endpoint supports the 2025-era Streamable HTTP protocol used by current hosted clients. The host discovers the OAuth endpoints, dynamically registers its own callback, and opens the Durable Thinking consent page. Continue to GitHub; if your login is on the allowlist, the host receives its own Durable Thinking access and refresh tokens.

The GitHub OAuth App still uses https://<worker-host>/callback, as configured during deployment. That is the Worker's upstream GitHub callback; it is separate from the redirect URI that Claude or ChatGPT registers with the Worker.

Bearer header — for CLIs and anything header-capable:

http
Authorization: Bearer <MCP_API_TOKEN>

An exact token match routes straight to the MCP handler; the OAuth machinery never sees it.

Use /mcp only for clients that explicitly support MCP 2026-07-28. Use /mcp-compat for current hosted web clients and other 2025-era Streamable HTTP clients.

OAuth troubleshooting

The browser consent step does not depend on third-party cookies. If connection fails, check the protocol surfaces in order:

  1. POST /mcp-compat without credentials must return 401 and a WWW-Authenticate header whose resource_metadata URL ends in /oauth-protected-resource/mcp-compat.
  2. That metadata document's resource value must exactly equal https://<worker-host>/mcp-compat.
  3. /.well-known/oauth-authorization-server must advertise /authorize, /token, /register, and S256 PKCE support.
  4. If ALLOWED_ORIGIN_HOSTNAMES is set, include the hosted client's hostname. Leaving it unset permits the server's own host plus the supported Claude and ChatGPT web origins; unrelated origins remain rejected.
  5. The consent page's CSP must allow form-action 'self' https://github.com. Earlier deployments allowed only 'self', so Chrome accepted the form POST but blocked its redirect to GitHub.

Worker logs use fixed stage and reason fields without recording authorization codes, state values, access tokens, client secrets, or thought text.

Retention and privacy

Thought text can contain private prompt context, copied credentials, personal information, or uncertain conclusions. The server treats it accordingly:

  • every MCP request authenticates — an issued OAuth token or the bearer secret;
  • thought text is never logged;
  • one private Durable Object, owned by you alone;
  • the App's CSP blocks all outbound network access;
  • sequences can be deleted explicitly, and are retained indefinitely by default.

CORS and MCP App visibility metadata are not authentication controls — keep the bearer token secret.

Development

bash
npm run check:app       # validates the self-contained MCP App and protocol surfacenpm run check:contract  # guards the compact tool and visibility contractnpm run check:registry  # guards the official Registry manifest and version syncnpm run typecheck       # Worker and test TypeScript projectsnpm run test            # Durable Object, auth, routes, and App invariantsnpm run build           # Wrangler dry runnpm run verify          # all checks above

src/ui/thought-process.html is the App's source of truth; Wrangler imports it as a text module via the rule in wrangler.jsonc.

text
src/index.ts                 Worker routes, authentication boundary, MCP handlersrc/server.ts                tools, compact return shapes, MCP App resourcesrc/thought-store.ts         SQLite Durable Object implementationsrc/oauth.ts                 GitHub sign-in and consent flow around the OAuth providersrc/ui/thought-process.html  per-thought MCP App card with final process viewsrc/auth.ts                  fixed personal bearer authenticationsrc/model.ts                 storage commands and recordstest/                        Worker, storage, auth, and App tests

License

MIT. See LICENSE and NOTICE.

來源:README.md,提交 99618ce

工具

0
SourceWeft 尚未讀取此伺服器的工具。

版本歷史

1
  1. v3.1.3Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式必需10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分