save-forever-mcp
v0.13.0
Published
MCP server for Save Forever: give an agent end-to-end-encrypted permanent storage on Arweave (paid per-use via x402, USDC on Base) PLUS a persistent memory (remember/recall/forget) — archive, retrieve, organize, share, and remember across sessions, as nat
Maintainers
Readme
save-forever-mcp
An MCP server that gives any MCP host (Claude Desktop, Cursor, agent apps) a funded wallet's worth of permanent, encrypted storage as native tools.
Store & read
archive_file— permanently store a file on Arweave, end-to-end encrypted, paying a few cents in USDC via x402. Encrypted locally before upload (zero-knowledge — the service can't read it). Optionalname/folderfile it away. Returns a permanentarchive_id+ Arweave tx and a recovery phrase.retrieve_archive— download a file you own and decrypt it locally — free with your wallet (only$0.01if you use a recovery phrase instead). Writes the file and returns the text inline for text/JSON.
Organize (free)
list_archives— list/search your files by keyword, with decrypted name/folder/type/tags, size, and hidden state. Filter bytags; long lists are capped (default 20, raise withlimit).list_tags— show which tags you've already used, with per-tag counts (case-insensitive) — call it before tagging so you reuse a tag instead of inventing a near-duplicate.update_archive— move to a folder, rename, and/or hide one of your archives (edits encrypted metadata only).
Remember — a persistent, cross-session memory (a reserved AI-managed drawer, separate from your files)
remember— save a memory (text, JSON, or a file) under a keyword-rich name so you can find it later. Addtagsto make it filterable, andas_knowledge: trueto store a structured JSON knowledge object.recall— search your memories by keyword and/ortagsand get the matches back (free; capped at 20, raise withlimit).read_memory— read a memory's full text by id (free, no payment, no disk write).forget— fade a stale memory out of recall (free; hides it, recoverable).
Knowledge objects & tags
Every archive carries a small encrypted manifest ({ v, type, name, folder, contentType, tags }) that the
server never sees. The type discriminator is either sf/file@1 (an opaque file) or sf/knowledge@1 (a structured
JSON object — read it back and parse it directly, rather than treating it as a file stream). Knowledge objects are
stored with contentType: application/json, so read_memory returns the body inline as text for parsing.
tags are free-form strings stored in the manifest (case preserved, de-duped). list_archives and recall filter
by tags with exact, case-insensitive, AND semantics — tags: ["architecture", "critical"] returns only items
carrying both. Tags are set at write time; legacy archives with no tags are treated as untagged. As with names and
folders, tags stay client-side encrypted — the server only ever sees ciphertext.
Use list_tags to discover the tags already in use (with counts) and keep your vocabulary consistent.
list_archives/recall print at most limit rows (default 20) with a visible "…and N more" when trimmed —
the full set is always searched; only the printed output is bounded.
Reading your own files/memories is always free (decrypted locally from the Arweave gateway). The
$0.01 /retrievecharge applies only to the recovery-code / non-owner path.
Share (free, end-to-end encrypted)
my_share_code— yoursfshare…code; give it out so others can share files with you.share_archive— grant a recipient permanent decrypt access to one of your archives by their share code.list_shared_with_me/retrieve_shared— list and download files others have shared with you.
It calls the live Save Forever API.
Setup
Add it to your MCP host config (e.g. Claude Desktop claude_desktop_config.json):
{
"mcpServers": {
"save-forever": {
"command": "npx",
"args": ["-y", "save-forever-mcp"],
"env": {
"SAVE_FOREVER_WALLET_PRIVATE_KEY": "0xYOUR_FUNDED_HOT_WALLET_KEY",
"SAVE_FOREVER_NETWORK": "base"
}
}
}
}Wallet & spending safety
The server pays x402 charges from a wallet you configure — it is never custodied by the service.
- Use a DEDICATED, low-balance hot wallet. Fund it with only the USDC you're willing to spend autonomously. Its balance is your hard cap. Never use a wallet holding significant funds.
SAVE_FOREVER_MAX_USD(default1.00) — per-call spend cap. A quote above this is refused before paying. Raise it to archive large files.SAVE_FOREVER_MAX_OPS(default50) — paid operations per server session (loop guard).
Env vars
| Var | Required | Default | Purpose |
|---|---|---|---|
| SAVE_FOREVER_WALLET_PRIVATE_KEY | ✅ | — | Funded hot wallet (USDC on Base) used to pay. |
| SAVE_FOREVER_NETWORK | | base | base (mainnet) or base-sepolia. |
| SAVE_FOREVER_API_URL | | the live API | Override the Save Forever endpoint. |
| SAVE_FOREVER_MAX_USD | | 1.00 | Per-call spend cap (USD). |
| SAVE_FOREVER_MAX_OPS | | 50 | Paid ops per session. |
| SAVE_FOREVER_RECOVERY_DIR | | ~/save-forever | Where recovery phrases + default retrieved files are written. |
| SAVE_FOREVER_OUTPUT_DIR | | your home dir | Root that retrieved files are confined to (see below). |
Where files land (cross-platform & safe by default)
- Recovery phrases and retrieved files default to
~/save-forever, not the process's working directory — some hosts (e.g. Claude Desktop on Windows) launch the server in a read-only system dir, so writing there would fail. - A retrieve's
output_pathis confined to your home directory (orSAVE_FOREVER_OUTPUT_DIR); a path outside it is rejected, so an autonomous/injected agent can't overwrite arbitrary files. - If the chosen location can't be written, the file falls back to the OS temp dir — a paid/decrypted result is never lost to a filesystem error, and
archive_filealways returns the recovery phrase in its response regardless.
How it works
Encryption is client-side AES-256-GCM with a random data key, wrapped under both your wallet signature (primary) and a recovery phrase (backup). The server only ever receives ciphertext + the two wrapped keys; it can never decrypt. See the Save Forever docs.
The recovery phrase is the only backup if you lose your wallet, and it is not stored by the service.
archive_filereturns it and also writes it to a local file — keep it safe.
