MemPersist

io.github.ravhirizaldi由 GitHub 帳號 ravhirizaldi 發布v1.0.1更新於 Oct 25, 2026

Durable, revision-pinned memory storage and retrieval for AI conversations.

已驗證Streamable HTTP可網頁執行檔案與儲存知識與記憶

概覽

AI 產生的概覽

MemPersist 是一個遠端 MCP 伺服器,把 AI 對話保存為持久、依修訂版本固定的記憶,並讓助理搜尋、讀取和寫入這些記憶。

可以做什麼
搜尋與脈絡組裝:帶篩選和游標分頁的混合記憶搜尋、查看某筆結果前後的脈絡,以及在 token 與位元組預算內產生確定性、依修訂固定的脈絡包。讀取對話:列出對話、依精確標題查找、分頁檢視某段對話的時間軸或完整圖,並依節點或鍵批次讀取對話與訊息。檢視封存狀態:列出命名空間與修訂、取得統計、匯入狀態和已部署的能力契約。寫入記憶:儲存、附加、取代、依鍵批次插入或更新訊息、編輯訊息、原子提交多對話批次、還原修訂、複製對話和更新標籤。管理:在精確確認後刪除對話和清空命名空間。
適用情境
當你希望助理跨工作階段、跨用戶端長期記住過往對話,或想匯入 ChatGPT 資料匯出並查詢,或需要檢索並固定確切的歷史修訂而不是依賴模型摘要時,適合使用。
執行需求
透過 Streamable HTTP 存取的遠端 MCP 端點,使用 OAuth 2.1(PKCE S256,scope 為 memory);授權需透過寄到電子郵件的一次性魔法連結完成。非互動式用戶端也可改用 Authorization Bearer 權杖。使用託管端點不需本機執行環境。
安裝前請注意
伺服器會在其自有的 Cloudflare 託管基礎設施上儲存並索引對話內容,包括上傳的 ChatGPT 匯出資料。寫入類工具會建立、取代、編輯、還原和複製記憶,管理類工具會在精確確認後刪除對話或清空命名空間。切勿把開發者權杖貼到連接器中,它只應用於指令碼。帳號刪除有七天寬限期,期間寫入為唯讀。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 MemPersist,將其新增到工作區。
  2. 連接 所需的 憑證。它們會被私密儲存,絕不會在公開頁面上展示。
  3. 為需要使用其工具的對話啟用該服務。

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

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.ravhirizaldi%2Fmempersist/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。 客戶端會在首次連接時完成 OAuth 登入。

{
  "mcpServers": {
    "mempersist": {
      "type": "http",
      "url": "https://mempersist.codifiedtech.id/mcp"
    }
  }
}

README

MemPersist

Long-term memory for AI conversations, running entirely on Cloudflare. Original ChatGPT exports and normalized conversation graphs live in R2, a D1 catalog makes them queryable, lexical and semantic indexes stay disposable, and MCP exposes compact retrieval plus intentional writes.

MCP endpointhttps://mempersist.codifiedtech.id/mcp
Registryio.github.ravhirizaldi/mempersist — version 1.0.1
RuntimeWorkers, D1, R2, Queues, Workers AI (BGE-M3), Vectorize, OAuth KV
ProtocolMCP v2 over stateless Streamable HTTP, OAuth 2.1 with PKCE S256
ScopeSingle-operator V1, one Worker, one TypeScript package

What it does. Preserves every uploaded ChatGPT export byte-for-byte, normalizes branches and node metadata into revision-pinned canonical JSONL, indexes derived FTS and vector data, and answers search, context, and batch reads with deterministic IDs. Writes are intentional, revision-checked, and durable before indexing is queued.

What it refuses to do. It does not intercept ChatGPT traffic, extract replacement "facts", summarize with a model, or treat any index as canonical. No billing, organizations, or speculative multi-tenancy; no Durable Objects, Workflows, cron triggers, or containers. Deleting every chunk, FTS row, and vector does not delete memory. "Unlimited" means no application-level message quota — Cloudflare limits and billing still apply.

Architecture

mermaid
flowchart TD  IMP["ChatGPT data export (conversations.json)"] --> V  WRITE["MCP writes from any client"] --> V  V["Validation and stable IDs"] --> R2[("R2 canonical archive<br/>raw import + immutable revisions")]  R2 --> D1[("D1 catalog<br/>imports, revisions, graph, R2 pointers")]  D1 --> Q["Cloudflare Queues<br/>import and index jobs"]  Q --> FTS[("D1 FTS5<br/>lexical chunks")]  Q --> AI["Workers AI BGE-M3"] --> VEC[("Vectorize<br/>embeddings")]  FTS --> SEARCH["Normalized hybrid search<br/>plus recent-canonical fallback"]  VEC --> SEARCH  SEARCH --> OUT["HTTP API and OAuth-protected MCP"]  R2 --> EXPORT["Lossless export and recovery"]

Two ingestion paths, and they stay independent: the ChatGPT data export parser accepts the native conversations.json format only, while writes arrive through MCP from whichever client the caller uses. Both converge on the same canonical revision model, so a memory created by a tool call and one imported from an export are read, pinned, and restored identically.

R2 is the source of truth. A canonical write completes before its index job is queued, and an indexing failure never reports that durable memory was lost. Rebuilds read R2, so an export never needs to be uploaded twice. Full detail in ARCHITECTURE.md and docs/storage-and-indexing.md.

Quickstart

bash
yarn installcp .dev.vars.example .dev.vars   # set a long random MEMORY_API_TOKENyarn types:bindingsyarn db:migrate:localyarn dev

Requires WSL2/Linux, Node.js 22+, Yarn 1.22, and Wrangler 4.x authenticated with yarn wrangler whoami. Use Yarn only. Local D1, R2, KV, and Queues are simulated; Workers AI and Vectorize point at real remote bindings in the main configuration, while unit and integration tests never call remote AI.

Connect any MCP client

MemPersist is a standard remote MCP server: stateless Streamable HTTP at https://mempersist.codifiedtech.id/mcp, OAuth 2.1 authorization code with PKCE S256, scope memory. Nothing in the endpoint is client-specific — the same handshake, tool contracts, and server instructions serve every caller. Point a client at the URL and it works:

ClientHow to add it
Claude Codeclaude mcp add --transport http mempersist https://mempersist.codifiedtech.id/mcp, then finish the email prompt
Codex CLI, ChatGPT desktop, IDE extension~/.codex/config.toml (or project .codex/config.toml), then codex mcp login mempersist
Cursor, Claude Desktop, VS Code, Zedadd the URL as a remote (HTTP) MCP server in the client's MCP settings; the client starts the OAuth flow
ChatGPTDeveloper mode, then add the URL as a custom MCP app
MCP Inspector, custom SDK clientsnpx @modelcontextprotocol/inspector, or the official SDK client; use the URL and either OAuth or the developer token
stdio-only clientskeep the server remote and bridge stdio to HTTP with an OAuth-capable proxy; MemPersist itself never needs npx

Codex configuration:

toml
[mcp_servers.mempersist]type = "remote"url = "https://mempersist.codifiedtech.id/mcp"# auth = "oauth" is the default; run `codex mcp login mempersist` to authorize

The client discovers OAuth from the 401 challenge, opens the consent page, and stores the issued access and refresh tokens. The consent page takes an email and sends a single-use, 15-minute magic link through the EMAIL binding; the connection completes only after that link is opened, and an existing email reconnects to its archive. The single scope is memory, and the sender address is configuration (AUTH_EMAIL_FROM, LEGACY_AUTH_EMAIL_FROM), not part of the API contract. Never paste MEMORY_API_TOKEN into a connector.

Already-configured connections keep working across upgrades without re-authorization; the legacy hostname stays supported, and moving one client to the primary hostname costs exactly one new authorization.

Developer token

Scripts, the CLI, and non-interactive automation may send Authorization: Bearer <MEMORY_API_TOKEN> instead of OAuth, which always maps to the owner archive. Every account may own multiple namespaces; the same namespace name in two accounts is separate data, and a supplied namespace is honored only when the caller owns it.

Local, without deploying

The MCP audience is deployment configuration, so point a development server at itself:

bash
yarn dev --local --port 8787 --local-protocol https \  --var MCP_ORIGIN_OVERRIDE:https://127.0.0.1:8787

Discovery, consent, and token audiences then use https://127.0.0.1:8787, and both the .dev.vars developer token and the full OAuth flow work. Local send_email writes each magic link to .wrangler/tmp/email/<id>/email-text/. See docs/development.md.

Tools

24 tools, each carrying a human-readable title and read-only or destructive annotations. Retrieve first, then expand only what you selected.

Read

ToolTitleNotes
memory_searchSearch memoriesHybrid search, 1–20 references; filters and opaque cursor pagination
memory_get_contextGet memory contextCanonical messages around one result chunk, up to 10 each way
memory_get_conversationGet conversationPage one conversation's active timeline or full graph
memory_get_messagesGet messagesExact source-node or optional keyed lookup, revision-pinned, ordered batch with opaque cursor and byte budget
memory_get_conversationsGet conversationsRevision-pinned batch read of 1–20 conversations, cursor-paged
memory_list_conversationsList conversationsMetadata and tags only, no bodies
memory_list_revisionsList revisionsImmutable revision history, newest first
memory_resolve_conversationsResolve conversationsExact-title lookup, no semantic search
memory_list_namespacesList namespacesOwned namespaces with conversation counts
memory_statsGet memory statisticsPer-namespace counts and indexing health
memory_import_statusGet import statusImport progress, duplicate, or failure
memory_get_capabilitiesGet capabilitiesThe deployed contract: versions, limits, per-tool bounds, and message_keys / atomic_multi_conversation_commit feature flags

memory_get_messages accepts 1–100 ordered selectors. Each selector names a conversation_id, optionally pins a revision_id, and uses exactly one of source_node_id (up to 200 characters) or the forward-compatible message_key (1–128 lowercase ASCII letters, digits, ., _, /, or -, starting and ending with a letter or digit). Omitted revisions pin each conversation's current head before any canonical R2 body is loaded; canonical loads are deduplicated by unique pinned revision, while duplicate selectors retain duplicate ordered results. The read-only lookup does not use FTS or Vectorize. Missing, foreign, deleted, or unknown conversations, revisions, nodes, and keys share the same bounded NOT_FOUND result. Duplicate canonical message keys return a bounded canonical-storage error and are never resolved by choosing one. Whole messages are admitted within the 32 KiB default, 4 KiB minimum, and 48 KiB maximum serialized budgets; an oversized message is not truncated and returns only bounded identity/byte diagnostics. Continuations use an opaque, HMAC-signed, tenant-bound cursor that preserves selector order and revision pins.

The optional message_key selector reads keyed fields written by memory_upsert_messages (and any canonical data that carries them). memory_upsert_messages is the stable-key writer for logical records; its contract is documented in the Write section below.

Context assembly

ToolTitleNotes
memory_build_contextBuild memory contextDeterministic, revision-pinned pack from 1–20 required conversations, optional hybrid evidence, explicit token and byte budgets

Write

Each write returns a bounded durable receipt with separate indexing and verification status, and accepts verify: true to reload the committed R2 revision. memory_commit_batch applies 1–20 append or complete-replace operations across distinct conversations in one same-account atomic commit; every operation supplies an explicit base_revision_id.

memory_upsert_messages accepts 1–100 unique keyed text messages for one owned conversation. Every request requires base_revision_id and a role; keys are exact 1–128-character lowercase ASCII strings matching [a-z0-9._/-], starting and ending with a letter or digit. Existing keys replace text while preserving source identity, role, creation time, graph, and metadata; a role mismatch is rejected. Missing keys append in request order with server identity and timestamps. All entries are validated before one atomic revision is committed. An all-unchanged request returns no_change without a revision or index job; mixed inserts, updates, and unchanged entries create one revision. verify: true checks the committed canonical revision and reports per-key results in the durable receipt; indexing starts only after a successful head transition. The deployed capability response advertises features.message_keys: true.

Batch replay with the same idempotency key and material returns the existing result without duplicate revisions or jobs. Changed material under a used key conflicts, and a stale operation prevents every operation in that batch from committing. Owned namespaces may be mixed in one batch; accounts remain isolated.

ToolTitleNotes
memory_storeStore memoryNew intentional memory; first write claims a namespace you name
memory_upsert_messagesUpsert keyed messagesAtomic 1–100 insert/update/no-op by exact key; required base revision
memory_appendAppend memoryContinue a conversation with base_revision_id
memory_replaceReplace memorySupersede with a complete transcript, preserving identity and tags
memory_commit_batchCommit memory batchAtomically append/replace 1–20 conversations with explicit base revisions
memory_edit_messagesEdit memory messagesEdit 1–100 known source nodes in place; structured content is rejected
memory_restore_revisionRestore memory revisionMove the head back to a historical revision, no duplicate revision
memory_copy_conversationsCopy conversationsLossless R2 copy into another owned namespace, idempotency-keyed
memory_update_tagsUpdate memory tagsAdd or remove tags under optimistic concurrency

Admin

ToolTitleNotes
memory_delete_conversationsDelete conversationsUp to 100, canonical and derived data together after exact confirmation
memory_empty_namespaceEmpty namespaceBounded, resumable batch empty after exact confirmation

Retry, reindex, and integrity commands stay HTTP/CLI only so a model cannot trigger expensive maintenance. Full tool contracts, receipts, and batch semantics live in docs/mcp.md.

Search pagination

The first memory_search call requires query and accepts limit (1–20, default 8), an optional namespace, tags, tag_mode (all or any), and optional max_serialized_bytes. The byte budget defaults to 32 KiB and accepts 4–48 KiB. A response may include next_cursor; continue with that opaque cursor, the next limit, and the byte budget. Do not resubmit the query or change filters on a continuation.

Compatibility responses that do not request pagination may omit the pagination-only metadata.

Search cursors identify a short-lived, tenant-bound snapshot. The snapshot preserves the exact ranking, scores, and order from the first call, pins each result's revision, and carries the original degraded and unavailable diagnostics forward. Its metadata reports the ranking version, candidate count and cap, creation and expiry times, and bounded omission counts/reasons. Expired cursors are cleaned up when read. Malformed, forged, expired, incompatible, or cross-account cursors return a bounded validation error; cursors expose no internal storage or account identifiers.

Search is scoped to the authenticated account. A namespace filter is valid only for a namespace the account owns; omitting it searches the account's owned namespaces. Deleted, stale, or no-longer owned snapshot candidates are omitted with safe bounded diagnostics rather than replacing the snapshot or exposing another account's data. Search cursors are for MCP/HTTP search pagination only; they are not export or canonical-read cursors.

Limits

memory_get_capabilities is the single contract: it reports the constants the transports enforce, so a quoted figure cannot drift from its enforcement. Deployed values:

LimitValue
MCP tool output guard65,536 bytes (64 KiB)
Recommended tool output / receipt ceiling49,152 bytes (48 KiB)
Inline JSON write on both transports1,048,576 bytes (1 MiB)
Direct import body, and each multipart part16,777,216 bytes (16 MiB)
Single message content1,000,000 characters
Batch conversation read response32 KiB default, 48 KiB max
Search response32 KiB default, 4 KiB min, 48 KiB max
Exact message lookup response32 KiB default, 4 KiB min, 48 KiB max

Aggregate limits are the UTF-8 bytes of the complete serialized request, measured before any canonical work. An oversized request writes nothing and fails with REQUEST_TOO_LARGE (retryable: false) plus a conservative suggested_max_items estimate — never a silent truncation.

ChatGPT import

Export your data from ChatGPT, extract conversations.json, then:

bash
MEMPERSIST_URL=http://localhost:8787 \MEMPERSIST_TOKEN='your-token' \yarn import:chatgpt /path/to/conversations.json
MEMPERSIST_TOKEN='your-token' yarn import:status <import-id>

The uploaded bytes are stored unchanged and hashed server-side; exact duplicates are marked duplicate and never reprocessed. One queue turn processes 25 conversations from an ordinal checkpoint, so retries are safe and resumable. Larger files use R2 multipart upload. Unknown fields, alternate branches, and graph anomalies stay recoverable. See docs/chatgpt-import.md.

Dashboard

Open /login for passwordless access to the server-rendered dashboard: archive totals, the deterministic memory map, revision-pinned canonical reading, display-name editing, and a streamed lossless export. Namespace emptying runs asynchronously; account deletion has a seven-day cancelable grace period and makes writes read-only while pending. No frontend framework or extra Cloudflare resource is required. See docs/dashboard.md and ADR 0028.

The public site, OAuth pages, and magic-link email are available in English and Bahasa Indonesia; API, MCP, and CLI contracts remain English.

Development

bash
yarn verify

Runs formatting, the binding-type freshness check, lint, strict TypeScript for the Worker and the web/mindmap/ browser project, the memory-map bundle check, unit and MCP tests, Workers-runtime D1/R2 integration tests, and a Wrangler deploy dry run. Nothing deploys unless yarn deploy is invoked. After editing anything under web/mindmap/, run yarn build:mindmap so the generated bundle matches its sources.

bash
yarn admin search 'api.internal.example'   # CLI search against canonical datayarn retry <job-id>                        # re-run a failed import or index jobyarn reindex                               # rebuild derived indexes from R2yarn verify:integrity                      # check catalog, R2 pointers, and revision hashes

Schema changes are numbered SQL migrations applied through Wrangler, never edited after they are applied. Architecture changes require an ADR in docs/adr/. See CONTRIBUTING.md and AGENTS.md before opening a pull request.

Documentation

DocumentContents
ARCHITECTURE.mdSystem shape, canonical versus derived, write order, retrieval
CONTRIBUTING.mdSetup, per-change requirements, tests, authorization gates
SECURITY.mdThreat model, trust boundaries, limits, rotation, reporting
docs/mcp.mdTool contracts, receipts, batches, capabilities, rejection shapes
docs/development.mdLocal loop, local MCP clients, browser pages, memory map client
docs/deployment.mdProvisioning, migration, deploy, post-deploy checks
docs/cloudflare-resources.mdRequired resources and manual provisioning steps
docs/chatgpt-import.mdImport guarantees, upload paths, parser ceilings
docs/dashboard.mdDashboard, export, and deletion flows
docs/storage-and-indexing.mdCanonical storage layout and index generations
docs/operations-and-recovery.mdRecovery procedures and deletion-job re-enqueue
docs/rp-workflow.mdReviewable runtime-rule workflow
docs/adr/Decision log, newest first
docs/adr/0040-atomic-multi-conversation-commit.mdAtomic multi-conversation commits, replay, recovery

來源:README.md,提交 dbb45a7

工具

0
該伺服器需要登入,因此 SourceWeft 無法在沒有帳號的情況下讀取其工具,也未收錄。已連接帳號所能看到的內容可能因帳號及其權限而異。

版本歷史

2
  1. v1.0.1最新Sep 29, 2026
  2. v1.0.0Sep 21, 2026

評分

已滿足適用檢查項的 75%

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

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具15 分

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

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

    請在儲存庫或註冊中心條目中宣告授權條款。