IPFS storage for AI agents: content-addressed memory that survives model swaps
Vector DBs bind agent memory to a specific model and index. IPFS gives agents deterministic pointers (CIDs) that survive model, prompt, and tool churn — and our MCP server puts them one config line away from Claude Code, Cursor, and Claude Desktop.
Nacho founded IPFS.NINJA to make content-addressed storage feel as simple as an S3 PUT — a single API call, a permanent CID, no wallets or peer discovery to reason about.

- AI-agent memory built on vector DBs locks you to a specific embedding model and index — swap the model and the vectors are meaningless.
- IPFS CIDs are deterministic content pointers: the same bytes always produce the same CID, regardless of which agent, prompt, or LLM produced them.
- Our MCP server (`@ipfs-ninja/mcp-server`) plugs IPFS Ninja into Claude Code, Cursor, Windsurf, and Claude Desktop as 12 native tools — upload, pin, list, retrieve, and manage files from a natural-language prompt.
- Combine vector search (recency, similarity) with IPFS (durable, portable, auditable source of truth) — don't replace one with the other.
Every AI agent has a memory problem. Not the model context window — that’s a different problem — but the layer underneath it: where does an agent write things it wants to remember, and how does it find them again when the model, the prompt, or the surrounding toolchain changes?
Most teams reach for a vector database. It’s a reasonable first move — semantic search feels magical the first time it works. But vector memory has a load-bearing assumption that everyone forgets: the vectors are bound to a specific embedding model. Swap the model and every vector you’ve written is a random number.
This post is about a different foundation: content-addressed storage on IPFS. Not as a replacement for vector search, but as the durable, portable, auditable layer underneath it. And about how our MCP server puts that layer one config line away from Claude Code, Cursor, Windsurf, and Claude Desktop.

The agent-memory problem, stated plainly#
An AI agent — Claude Code refactoring a repo, a Cursor agent scaffolding a feature, a Windsurf agent running a multi-step data pipeline — accumulates state across a session:
- Notes it wrote to itself.
- Files it fetched from the web.
- Datasets it computed intermediate results from.
- Tool outputs it wants to reference later.
When the session ends, that state has to live somewhere. And when a different session picks up — maybe next week, maybe with a newer model, maybe in a different IDE — it has to find the same state again.
The requirements are unglamorous:
- Addressable — I need a stable pointer I can hand to the next session.
- Verifiable — When I fetch the pointer, I need to know it hasn’t been tampered with.
- Portable — The pointer should survive model swaps, prompt rewrites, and IDE migrations.
- Auditable — I should be able to look at what the agent remembered, byte for byte.
Vector DBs give you (1), sort of. They don’t give you (2), (3), or (4). Content-addressed storage gives you all four for free.
Why content addressing matches agent memory#
An IPFS Content Identifier (CID) is a cryptographic hash of the exact bytes of a file. Two properties fall out of this:
- The same bytes always produce the same CID. Agent A on Claude Opus 4.5 uploads a JSON blob and gets
bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi. Agent B on Sonnet 5, running six months later, computes the same hash locally and gets the same CID. No coordination required. - The CID is a proof. When you fetch content by CID, the gateway can’t lie to you. You (or your client) can recompute the hash from the bytes and confirm the CID matches. Tampering is impossible without invalidating the pointer.
Compare that to vector memory:
| Property | Vector DB memory | IPFS content memory |
|---|---|---|
| Stable pointer across model swaps | No — vectors reindex per model | Yes — CID is a hash, not an embedding |
| Verifiable content | No — trust the DB row | Yes — recompute hash from bytes |
| Portable across agents / IDEs | Only if they share the DB | Yes — any gateway, any pinning service |
| Auditable byte-for-byte | Hard — vectors are opaque floats | Trivial — bytes are bytes |
| Similarity search | Yes — the primary feature | No — needs an index on top |
The point isn’t that vector DBs are bad. Similarity search is genuinely useful. The point is that vector DBs are the retrieval layer, not the storage layer. Store the source of truth on IPFS; index it with vectors on top; when you swap the model, rebuild the index from the CIDs.
How agents talk to IPFS: MCP#
The mechanical question is: how does an agent — which is fundamentally an LLM with a scripted tool loop — actually call an IPFS API?
The answer in 2026 is Model Context Protocol (MCP), an open standard published by Anthropic in late 2024 and now supported natively by Claude Code, Cursor, Windsurf, and Claude Desktop. MCP defines a JSON-RPC schema for exposing tools to an LLM: each tool has a name, an input schema, and an output shape. The client (Claude Code, etc.) discovers the tools at startup and lets the model call them during a conversation.
We ship a first-party MCP server: @ipfs-ninja/mcp-server. It exposes 12 tools that map one-to-one to our REST API:
ipfs_upload— upload arbitrary content (base64 or text)ipfs_upload_json— upload a JSON objectipfs_import_car— import a CAR file (DAG import)ipfs_list— list your uploaded filesipfs_get— get file metadata by CIDipfs_delete— unpin and delete a fileipfs_pin— pin an existing CID from the networkipfs_pin_status— check pin progressipfs_folders_list— list your foldersipfs_folders_create— create a new folderipfs_profile— plan, storage, bandwidthipfs_analytics— daily bandwidth and file stats
From the agent’s point of view, calling ipfs_upload looks exactly like calling any other tool — the same shape as read_file, bash, or web_search. The MCP transport handles authentication (a bearer API key held server-side in your config), retries, and error surfacing.
One line of config — Claude Code#
Sign up at ipfs.ninja (free plan is fine for a demo), grab an API key from the dashboard, and add the MCP server:
claude mcp add ipfs-ninja \
--transport stdio \
-e IPFS_NINJA_API_KEY=bws_your_full_api_key_here \
-- npx -y @ipfs-ninja/mcp-serverRestart Claude Code, type /mcp, and you’ll see ipfs-ninja connected with 12 tools. That’s it. You can now say things like:
Upload this JSON as permanent metadata and give me the CID.
Pin the readme at
QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdGto my account.
How much storage am I using?
Cursor, Windsurf, and Claude Desktop all speak MCP the same way — see the MCP server docs for their exact config.
A real example flow: dataset handoff between two agents#
Here’s a shape you’ll see in practice. Agent A is a research agent — it scrapes a set of pages, cleans them, and emits a normalised JSONL corpus. Agent B is a synthesis agent — it reads the corpus and produces a report.
Agent A (in Claude Code):
You: Scrape the top 20 pages for "IPFS agent memory 2026", normalise them
into JSONL with fields {url, title, published, body}, and upload
the corpus to IPFS. Store the CID in `research/index.json` with
a timestamp and topic.
Claude: [scrapes, normalises, calls ipfs_upload with the JSONL blob]
→ CID: bafybeidzcsx4hslfdsojnzs43wovabahvxikfl56b6ax4dgmvljkc4jfvi
→ Size: 1.2 MB
→ Gateway: https://ipfs.ninja/ipfs/bafybeidzcsx4hslfdsojnzs43wovabahvxikfl56b6ax4dgmvljkc4jfvi
[updates research/index.json with { topic: "ipfs-agent-memory",
cid: "bafybeidzcsx4h...", uploaded: "2026-07-11T..." }]Agent B (next week, potentially on a newer model, in a different IDE):
You: Read research/index.json, fetch the latest corpus for
"ipfs-agent-memory", and produce a synthesis report.
Claude: [reads research/index.json, finds CID bafybeidzcsx4h...]
[calls ipfs_get to confirm the file exists and check size]
[fetches https://ipfs.ninja/ipfs/bafybeidzcsx4h... via curl]
[synthesises the report from the JSONL]
→ Report ready. Sources verified against CID.Notice what the handoff protocol is: a CID in a JSON file. Not a database row. Not an S3 key with a mutable pointer. Not a vector index. A cryptographic pointer to immutable bytes. Agent B gets exactly the corpus Agent A produced — verifiable by hash — and doesn’t need to know which model, which IDE, or which embedding scheme Agent A used.
When to still use a vector DB#
To be clear: this isn’t a case for ripping out your vector database. Vectors are the right primitive for “give me the 20 most similar chunks to this query.” Content addressing is the right primitive for “give me the exact bytes that were pinned under this pointer.”
Use both:
- Write — Agent uploads the source document to IPFS, gets a CID.
- Index — Agent chunks and embeds the document, writes vectors keyed by
(CID, chunk_offset). - Query — Agent runs a similarity search over the vectors, gets top-K
(CID, offset)pairs, fetches the exact chunks from IPFS. - Rebuild — When the embedding model changes, re-run step 2 from the CIDs. The vectors change; the source of truth doesn’t.
This is the same pattern as git + a code-search index: git stores content-addressed blobs, the search index is disposable and rebuildable.
How this compares to Storacha, Lighthouse, and Filecoin memory#
The AI-agent-storage space in 2026 has a lot of movement. Everyone pinning content to IPFS or Filecoin — Storacha, Lighthouse, Pinata, 4EVERLAND — is chasing the same rising cluster. What matters for an agent developer is the developer surface:
| Provider | MCP server | Dedicated gateway | REST API shape |
|---|---|---|---|
| IPFS Ninja | Yes — 12 tools, @ipfs-ninja/mcp-server | Included on all paid plans | JSON with predictable response shapes |
| Storacha | Community / DIY | Public IPFS gateways | UCAN-based, protocol-first |
| Lighthouse | Community / DIY | Public IPFS gateways | REST, encryption-first |
| Pinata | Announced | Included on paid plans | REST |
If you’re building an agent today with Claude Code, Cursor, or Claude Desktop, the fastest path to a working demo is our MCP server + a free account. If you’re building against a UCAN-based protocol layer or need Filecoin proofs, Storacha’s protocol-first stack is a better fit. Content addressing is the shared substrate; pick the operator whose surface fits your workflow.
Try it#
- Sign up free — 500 files, 1 GB storage, 2 GB bandwidth/mo.
- Generate an API key.
- Add the MCP server to Claude Code:
claude mcp add ipfs-ninja \
--transport stdio \
-e IPFS_NINJA_API_KEY=bws_... \
-- npx -y @ipfs-ninja/mcp-server- Ask Claude to upload something.
Full setup for Cursor / Windsurf / Claude Desktop is in the MCP server docs. If you want the step-by-step, see our 5-minute Claude Code + MCP tutorial.
Ready to give your agent durable memory? Create a free account — no credit card required.
Frequently asked questions
Why not just use a vector database for agent memory?
What is MCP and why does it matter for agents?
How is this different from Storacha, Lighthouse AI Memory, or Pinata Agents?
Is my agent's data private if I upload it to IPFS?
About this article
This article was AI-assisted, human-reviewed, and product-verified against the live IPFS.NINJA platform before publishing. Learn how we use AI in our content .

About the author
Nacho Coll
Founder & Engineer at IPFS.NINJA
Nacho founded IPFS.NINJA to make content-addressed storage feel as simple as an S3 PUT — a single API call, a permanent CID, no wallets or peer discovery to reason about. Writes about IPFS internals, decentralized storage patterns, and the pinning-service landscape from the operator side of the wire.

