
Verified Memory
io.github.python1由 GitHub 帳號 python1 發布v0.4.1更新於 Nov 1, 2026
Offline read-only search over a checksum-verified, optionally signed memory pack, with exact quotes
發布方自己的服務:Memory.fit
概覽
本機離線、唯讀的 MCP 伺服器,可在經雜湊校驗(可選簽章)的記憶包中搜尋,並回傳附出處的原文引用。
- 可以做什麼
- 以關鍵字搜尋記憶包,要求所有查詢詞都出現在陳述、主題或引用中,最多回傳 10 筆排序結果
- 依記錄 ID 取得單筆記錄,包含引用、日期、說話者以及核准、取代等中繼資料
- 在結果中一併回報驗證狀態,例如簽章、簽署者、序號與新鮮度
- 只從單一記憶包的記憶體快照提供服務,啟動後若記憶包資料夾有變動就拒絕回答
- 適用情境
- 適合讓助理從經過整理、可防竄改的記憶包中回想事實(例如帳戶或付款資訊),並希望取得原文引用而非自由生成的回想。也適合在可信機器上建置並簽署記憶包、由主機固定簽署者指紋的情境。
- 執行需求
- 需要 Node.js 22 或更新版本,透過 npx 或直接以 node 在本機以 stdio 執行;必須以 --pack 指定記憶包資料夾(npm 套件本身不含記憶包)。可選參數包括 --trusted-fingerprint、--trusted-keys、--revoked-keys、--min-sequence、--require-signature、--strict。建置與簽署記憶包還需內建建置工具,簽署另需 OpenSSH 8.1+ 與 Ed25519 金鑰。不需帳號、API 金鑰或網路存取。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Verified Memory,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
verified-memory-mcp
Why
AI agents are starting to pay invoices and buy things. An agent pays wherever its memory says to pay. If someone swaps a remembered account number, the agent pays the attacker. This is vendor-payment fraud moving from fooling clerks to fooling AI.
Verified Memory serves only facts signed by a key you pin, and refuses anything changed after signing. An AI attacker red-teamed it with 12 tampering attacks (swapped files, broken signatures, fake clocks, a 5,000-file flood, the folder replaced while running). None got tampered data served (full log). Latest release: Verified Memory 0.4.1.
Free, MIT-licensed local stdio MCP server exposing verified_memory_search
and verified_memory_get using the official
MCP TypeScript SDK
(@modelcontextprotocol/sdk 1.32.1). Published on npm as @python1/verified-memory-mcp
and in the MCP Registry as io.github.python1/verified-memory.
Runtime is read-only and offline: no network transport, sockets, telemetry, embeddings, accounts, filesystem writes, subprocesses or shell execution. It reads one configured pack at startup and serves an isolated in-memory snapshot. On every request it checks, from file metadata only, that the pack folder is still the one it verified, and stops serving if it is not (no watchers, nothing re-read). Stdout is exclusively MCP protocol output; startup errors go to stderr and exit nonzero. Only these two tools are exposed; no resources, prompts, filesystem or command tools.
Run with npx
The npm package contains only dist/, the pack builder, this README and LICENSE. It ships no pack,
so --pack is required:
Claude Code: claude mcp add verified-memory -- npx -y @python1/verified-memory-mcp --pack /absolute/path/to/pack.
Running through npx does not apply Node's permission mode, because npx starts its own
Node process. For the read-only filesystem allowlist described below, install the
package and run its dist/index.js with node directly.
Build your own pack
A pack is a directory with exactly four files: records.jsonl, MEMORY.md,
README.md and SHA256SUMS, plus an optional PACK.json (creation and expiry dates)
and an optional signature, SHA256SUMS.sig
(see Signed and dated packs). The easiest way to make one is the bundled offline
builder. It reads your messages and the records you want to remember, finds every
quote in its message, computes offsets and hashes, writes the pack, and then loads it
with the server's own verifier. If any quote is not verbatim in its message, it writes
nothing.
From a ChatGPT or Claude export, in your browser
Pack maker (beta): https://python1.github.io/data-lore-hive/. Load your data export, search your chats, select
the exact sentences to remember, and download a ready pack. It runs entirely in the
browser (no server, and its Content-Security-Policy forbids network requests), uses the
same building code as the command-line builder, and checks the pack with the server's
own verifier before offering the download. It does not sign packs or add dates (use sign-pack,
below), but its Check a signed pack panel runs the same verifier on a signed pack and
the public keys you paste. Its source is in web/; to run it
from a checkout instead, run npm install && npm run build there and open
web/dist/index.html. See web/README.md.
Quick start
-
Put your source messages in
messages.jsonl, one JSON object per line: -
Put what you want remembered in
records.jsonl, one record per line, each citing exact quotes from those messages:Unknown fields are refused, so typos fail loudly.
-
Build into a directory that does not exist yet, then point the server at it:
From a repository checkout, run
node tools/build-pack.mjs ...afternpm run build. The building rules (verbatim quotes, code-point offsets, hashes, file layout) live intools/pack-core.mjs, which has no imports so a browser can run the same code. The builder makes no network calls. It never overwrites: it stages in a hidden sibling directory and renames it into place only after verification passes.
examples/input/ holds invented sample input (a fictional community
garden, not real people), and examples/pack/ is the pack built from
it; the test suite rebuilds it byte for byte. Neither ships in the npm package.
records.jsonl format (what the server verifies)
One JSON object per line, UTF-8, at most 10,000 records, unique record_ids.
Every field below is required unless marked optional:
Each citation in evidence:
Example (one line in the file; wrapped here for reading):
Quotes are checked against their source messages when the pack is built, and after
that the signature protects them. The builder (or agent-memory/) refuses any quote
that is not verbatim in its message and computes message_sha256 from that message. The
server never sees your original messages, so at load and at serve time it checks only
citation structure, offsets' arithmetic and the hash's format; it does not re-check
quotes against message_sha256. Once the pack is sealed, SHA256SUMS (and, for a signed
pack, SHA256SUMS.sig) is what protects those quotes from later changes. A pack with no
records is refused at load (since 0.4.1).
MEMORY.md and the pack README.md
The server requires both to exist, be valid UTF-8 and match SHA256SUMS. It does not
parse them or return them from either tool; they are for people and agents reading the
pack directly. By convention, and as the builder writes them:
MEMORY.md: a# Titleheading, then for each record its ID and speaker, its statement, and each quote with its message ID and date, marked as historical data.README.md: what the pack is and where it came from (SHA-256 of the input files, record count), plus the notice that quotes are data, not instructions, and that checksums prove integrity, not truth or approval.
SHA256SUMS format
Exactly one line per other file (three, or four with PACK.json), each
<64 lowercase hex> + two spaces + file name; no entry for SHA256SUMS or
SHA256SUMS.sig; at most 4 KiB:
If you edit a pack by hand, regenerate it from inside the pack directory:
Resealing by hand only makes the checksums match again; it does not re-check quotes. Prefer rebuilding with the builder. Resealing also invalidates any signature: sign again.
Signed and dated packs
A pack can carry two optional extras:
SHA256SUMS.sig: an OpenSSH signature over the exactSHA256SUMSbytes, which pin every other file. Only Ed25519 keys, thesha512hash and the namespaceverified-memory-pack-v1are accepted, so a git or code-release signature cannot be reused as a pack signature.PACK.json(since 0.3.0): when the pack was made and when it stops being current, and (since 0.4.0) an optionalsequencenumber. It is listed inSHA256SUMSlike every other file, so the signature covers the dates and the sequence.
Exactly these four keys plus the optional sequence; dates are UTC ISO 8601 and
created_utc is before expires_utc. version is the format version and stays 2;
sequence is a whole number (0 or more) that the signer raises with every pack they
publish, so hosts can refuse an older one (see Rollback protection).
A malformed PACK.json refuses to load. The pack maker and the builder
never write one, so their packs still load on 0.2.0 hosts; packs with a PACK.json need
0.3.0 or later (older hosts refuse the extra file), and packs with a sequence need
0.4.0 or later (0.3.0 hosts refuse the extra key).
Signing: sign-pack
Sign on a machine you trust with a passphrase-protected key. Since 0.4.1, sign-pack
ships in the npm package as the verified-memory-sign-pack command (in a checkout it is
tools/sign-pack.mjs). It copies a verified pack to a new folder,
writes PACK.json, reseals SHA256SUMS and runs ssh-keygen -Y sign. It never opens
the private key itself: ssh-keygen reads it and asks for the passphrase (or uses
ssh-agent). Before it moves the result into place, it loads it with the hosts' own
verifier in strict mode, trusting only your .pub. It needs Node 22+ and OpenSSH 8.1+.
From a repository checkout, run npm ci && npm run build once, then
node tools/sign-pack.mjs ... with the same arguments.
--expires is a number of days (90d, at most 1825d) or an exact UTC time
(2027-01-31T00:00:00Z). --sequence (optional, since 0.4.0) is written into
PACK.json; raise it every time you publish a new pack (1, 2, 3, …). --out must not
exist yet. On any failure (wrong passphrase, a pack that does not verify) nothing is
written. Signing an already signed pack replaces its dates, sequence and signature. The
script prints the key fingerprint, the --trusted-fingerprint line to pin it on hosts,
and a trusted-keys line.
Keep the private key out of the pack, out of any repository and off shared machines.
Share only the .pub file.
Plain ssh-keygen -Y sign -f KEY -n verified-memory-pack-v1 pack/SHA256SUMS still makes
a valid signature, but the pack then has no expiry date (freshness: unknown) or
sequence, and --strict and --min-sequence refuse it.
Recommended setup: pin the signer
--trusted-fingerprint names the one key allowed to sign your packs, by the
fingerprint sign-pack (or ssh-keygen -l -f KEY.pub) prints. Repeat the flag, or
separate fingerprints with commas, to allow several. When any is set, a pack signed by
any other key is refused, even if that key is in --trusted-keys; an unsigned pack is
refused too (a pin implies --require-signature). --trusted-keys then only supplies
your name for the pinned key; without it the signer is reported as "pinned".
Why: in red-team round 4, an attacker bot on a shared machine that could rewrite the
trusted keys file listed its own key and re-signed a poisoned pack, and a host trusting
that file served it as verified. A pin lives in the host's own configuration (the MCP
client config or the Claude Desktop setting), not in a file next to the pack, so that
attack is refused: pack is signed by SHA256:…, which is not a pinned signer fingerprint. Keep the host configuration writable only by you; nothing here can
protect a host whose own configuration an attacker can edit.
Revoking a key: --revoked-keys
--revoked-keys /absolute/path/to/revoked_keys lists fingerprints you no longer trust,
one per line, as ssh-keygen -l prints them; # comments and a trailing comment after
the fingerprint are allowed:
A pack signed by a revoked key is always refused, even when the key is pinned or
trusted, and even without any signature requirement: pack is signed by SHA256:…, which is revoked. Revocation does not by itself require a signature, so unsigned packs still
load unless you also pin or require one. The file is read once at startup, like the
trusted keys file; keep it where only you can write.
Rollback protection: --min-sequence
--min-sequence N refuses any pack whose signed PACK.json sequence is missing or
lower than N, so an older pack, however validly signed and unexpired, cannot be
swapped in for the current one: pack sequence 3 is lower than the minimum 5; refusing a possible rollback to an older pack. You set N, and raise it when you install a
newer pack; the server keeps no state file and never writes anything, so it cannot
remember the highest sequence it has seen. A sequence counts only when a key you pinned
or trusted signed it, so --min-sequence implies --require-signature.
Order of checks
Every refusal gives one specific error, from the first check that fails:
- the pack's files, checksums and records (any edit fails here);
- the signature, if present, must be valid;
- revoked (refused whatever else is set), then pinned (with pins set, only a
pinned signer passes), then trusted keys (
verified,untrustedorunsigned, and--require-signaturerefuses all butverified); - sequence against
--min-sequence; - expiry under
--strict(also judged again on every request).
Stop on change
The server reads and verifies the pack once, at startup. On every tool call it compares
the pack folder's file list and each file's size, modification time, change time and
identity (device and inode) with what it verified. If anything differs (an edit, an
added or removed file, a file or the whole folder replaced), both tools return
isError with verified-memory: pack files changed on disk since startup, so the verified snapshot no longer matches them; restart to verify the pack again, and no
record data, until you restart. The refusal is latched in memory: removing the added
file or putting the folder back does not resume serving; only a restart, which verifies
the pack again, does. This is metadata only: no background watchers, no
re-reads, no writes. Change time cannot be set back by a normal user, so restoring a
file's modification time does not hide an edit; an administrator who can change the
system clock or the filesystem itself is outside what this detects.
Choosing whom to trust
Trust is only ever a public key you list. There is no built-in key, network, key server
or registry. Put keys in a file, one per line in allowed_signers form,
name ssh-ed25519 AAAA… [comment] (blank lines and # comments are allowed):
The maintainer's pack-signing public key is in keys/ for anyone who
chooses to trust packs signed with it. No host trusts it unless you list it.
--flag=value, --require-signature=true|false and --strict=true|false forms are
accepted too; an empty --trusted-keys=, --trusted-fingerprint=, --revoked-keys= or
--min-sequence= means that setting is off. --require-signature keeps its 0.2.0 meaning: a signature by a key you
listed is required, and freshness is reported but not enforced, so packs signed with
plain ssh-keygen for 0.2.0 keep loading under it. --strict requires a trusted
signature and a fresh PACK.json (it implies --require-signature).
What hosts do
Every tool result carries verification.signature and verification.freshness.
Freshness is judged against this computer's clock on every call, not only at startup.
With the 0.4.0 options, in any of the modes above:
freshness.authenticated is true only when a key you listed signed the dates; dates in
an unsigned or untrusted pack could have been written by anyone. --require-signature
or --strict with no pinned fingerprint or trusted key, or a trusted key line that is not a single-name ssh-ed25519 entry,
refuses to start. The signer name always comes from your file, never from the pack, and
fingerprints match ssh-keygen -l. Anyone can check a pack without this server:
A signature proves who signed, not that the content is true. It shows that the
holder of that key signed these exact bytes. It does not show that the quotes are
accurate or complete, or that the key's owner is who you think. "Fresh" means the signer
set an expiry that has not passed, not that this is their latest pack: without
--min-sequence, an older pack from the same key still loads until it expires.
Revocation and the minimum sequence are only as current as your configuration: with no
network, a newly revoked key or a newer sequence reaches a host only when you edit its
settings. Freshness relies on this computer's clock. Version 0.1.0 refuses signed packs (five files);
remove SHA256SUMS.sig to load one there.
Build and run
From a checkout of this repository, using Node 22.0.0 or newer (use the
latest patch release of your chosen Node line), in plugins/verified-memory-mcp:
The last command starts the stdio server, waiting for an MCP client on stdin.
It is not an interactive terminal search interface. Connect it through Claude
Desktop or another MCP client, then request a pottery search and retrieve
M-sample-2. Node's permission mode grants only reads under this project directory;
filesystem writes, subprocesses, workers and native addons are denied. The
--experimental-permission spelling works at the Node 22.0.0 floor; early Node 22
releases emit an experimental warning on stderr. On Node 22.13+ you can use
--permission instead. Node 22 does not enforce network permissions; this server
makes no network calls. Node 25.8.0 additionally passes the socket-denial probe.
See the Node 22.0 permission documentation
and Node 22.13 permission documentation.
Use direct node invocation at runtime, not npm/npx or a shell wrapper.
Builds, dependency installation and tests are development operations: they write local output; installing dependencies accesses the npm registry. Runtime does neither. The test harness launches local Node processes and makes isolated temporary copies of the fictional pack; the server itself never launches another process.
Claude Desktop one-click install
Download verified-memory-<version>.mcpb from the
latest release.
verified-memory-<version>.mcpb is an MCP Bundle
for Claude Desktop on macOS and Windows; it has been tested by hand on macOS and Windows.
It runs on Claude Desktop's built-in Node.js, so you need no Node install and no Terminal.
- Double-click the
.mcpbfile. Windows may ask which app opens it: choose Claude. Alternatively, drag the file into Claude Desktop → Settings → Extensions, or use Settings → Extensions → Advanced settings → Install Extension…. - Unzip the pack first (Windows: right-click → Extract All). Point the add-on at the folder
that contains
MEMORY.md,README.md,records.jsonlandSHA256SUMS. The folder picker shows folders only, so the pack folder will look empty; that's normal. You can also paste the folder path. - Make sure the extension is switched on (Settings → Extensions → Enabled) before asking. Example question: "Using verified memory, what did … ?"
The settings form has these fields:
For a signed pack, paste the fingerprint sign-pack printed into Pinned signer
fingerprint; you then need no trusted keys file. Raise Minimum pack sequence when you
install a newer pack. Turn on Strict for packs signed with an expiry date (sign-pack
always adds one). Every new setting defaults to off, so an add-on upgraded from 0.3.0
behaves as before (apart from stop on change).
Change these later in Settings → Extensions → Verified Memory. The bundle holds the
same dist/ as the npm package plus its production dependencies, and nothing else: no pack,
keys, signatures or tests. It is not code-signed with mcpb sign, because that would need a
private key. It does not use Node's permission mode, because Claude Desktop starts the server itself.
Build it locally with npm ci && npm run build:mcpb (output: build/verified-memory-<version>.mcpb).
npm run test:mcpb builds it and runs test/mcpb/. Those tests unpack the bundle with
@anthropic-ai/mcpb and start the server with the arguments that its getMcpConfigForManifest
produces from sample settings.
Claude Desktop configuration example
Merge this example into your Claude Desktop MCP configuration and restart Claude Desktop after building. All paths below are placeholders, not real user paths. Replace them with absolute paths to the Node executable and this built directory. No configuration is installed or edited automatically.
In a repository build, omitting --pack uses the bundled fictional Juniper Vale/Wren
sample regardless of the client's working directory. An npm install has no sample and
refuses to start without --pack. To use your own pack, append
"--pack", "/absolute/path/to/pack" to args, and also add
"--allow-fs-read=/absolute/path/to/pack" before the entry-point argument. With
--trusted-keys, also allow reading that file the same way.
Choose a pack that the connecting client is permitted to read.
Relative pack paths and unknown CLI flags are rejected. Tools cannot choose paths.
There is no discovery of home directories, other agents, real memory or configuration.
There are no watchers or reloads: if the pack folder changes while the server runs, the
tools stop answering with an error, even if the change is undone, until you restart to
verify the new pack. Add
--trusted-fingerprint, --revoked-keys (and its --allow-fs-read) and
--min-sequence to args the same way.
Tool contracts
verified_memory_search:
Returns matches, matched, verification, and notice. Search requires all
normalized Unicode words, at most 32 unique terms, across statement/topic/quotes.
Returns at most 10 matches, ordered by term occurrences, newest date, then record
ID. Matches preserve exact quotations, source message IDs, dates and speakers.
No stemming, semantic inference or network lookup. No match is not proof of absence.
verified_memory_get:
Returns found, full record (or null), verification, and notice, preserving
citation, provenance, audit, approval and supersession metadata as historical data.
Successful MCP results contain JSON text in content and the same object in
structuredContent (the MCP equivalent of the OpenClaw tool's details). Invalid
tool arguments return isError: true; unknown tool names return a protocol error.
Both tools advertise read-only, nondestructive, idempotent, closed-world annotations.
The SDK's low-level Server API keeps the published JSON schemas exact, including
additionalProperties: false; arguments are checked explicitly and by the shared
verifier. No OpenClaw runtime or dependencies are needed to build or run this server.
Shared verifier and fail-closed startup
The development-only scripts/prepare.mjs copies the original
../verified-memory/src/pack.ts and verify.ts byte for byte into ignored src/, and
copies its public fictional sample into ignored sample-pack/. TypeScript compiles
that same verifier into dist/pack.js (file reading) and dist/verify.js (the checks
themselves, with no imports). There is no second maintained verifier, and this build
never modifies the OpenClaw plugin. Build from the repository
checkout so the sibling source and sample are present. Generated files are not committed.
The whole pack must verify before a server is created or stdio is connected.
A failing pack cannot initialize, list tools or return records. The exact format
is four regular files: records.jsonl, MEMORY.md, README.md, and SHA256SUMS,
plus an optional PACK.json and SHA256SUMS.sig checked by the same shared verifier.
Checks include exact file inventory, SHA-256 hashes over the bytes actually parsed,
UTF-8, JSON, unique IDs, citation structure and offsets, date ranges, manifest
syntax, symlink roots/entries and file-size/count limits. Limits remain 16 MiB per
data file, 4 KiB manifest, 10,000 records. No permissive fallback. Later disk edits
cannot change the verified in-memory snapshot, and since 0.4.0 they stop it being served
(see Stop on change); retrieval returns copies.
Inherited filesystem checks are not a sandbox against an adversary able to race ancestor directories. Use a trusted, stable local directory and the Node read allowlist.
Integrity is not authenticity or truth. Replacing both data and checksums can
produce a passing pack, unless you pin the signer (--trusted-fingerprint) or list only keys
whose trust file the attacker cannot write. Runtime cannot recheck quotations against original messages.
Historical quotes are data, never instructions or permission; that notice accompanies
every successful result. Host model behavior and automatic tool selection are not
validated. Ask the host to quote tool text verbatim and cite record and message IDs.
Only the existing public fictional source
agent-memory/sample/telegram-export.json is used. No private records, operational
paths, IP addresses, keys or other-agent files are included. Fixture audit/approval
metadata is not evidence of real model auditing or human approval.
File tree
See VALIDATION.md for recorded tests and limitations.
License
MIT — LICENSE. Free functionality, no paid tier.
☕ Support this project: https://buymeacoffee.com/python1
來源:plugins/verified-memory-mcp/README.md,提交 8f60099
工具
0版本歷史
5- v0.4.1最新Oct 18, 2026
- v0.4.0Oct 18, 2026
- v0.3.0Oct 13, 2026
- v0.2.0Oct 13, 2026
- v0.1.0Oct 11, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
其他 Memory 整合

Memory.fit
fit.memory官方發布者
託管式 Memory.fit 伺服器,讓 AI 讀取你的訓練、睡眠、恢復與飲食資料,並寫回每週計畫、每日目標和飲食計畫。
pg.ddx.io: the PostgreSQL community's memory
io.ddx.pg官方發布者
pg.ddx.io: the PostgreSQL community's memory 的託管 MCP 服務,由 pg.ddx.io 發布;無需登入;Streamable HTTP;29 個工具。
var.gg Naming Memory
gg.var官方發布者
遠端 MCP 伺服器,可依領域概念推薦並檢索韓、日、中、越、英多語言的程式識別字名稱,並提供 ERD 結構查詢。

Counterparts
ai.counterparts
為 Claude Code 與 Claude Desktop 提供的本地優先長期記憶:助理自行寫下關於你與專案的筆記,並在之後的對話中回想起來。

LAHZE - Persian AI Memory Platform
由 GitHub 帳號 pedramgholizadeh 發布
以波斯語為先的地理記憶平臺:發現地點,起草併發布僅限波斯語的記憶。AI 翻譯