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 Collby Updated: 8 min read
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.
TL;DR
  • 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.

IPFS Ninja upload screen

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:

  1. Addressable — I need a stable pointer I can hand to the next session.
  2. Verifiable — When I fetch the pointer, I need to know it hasn’t been tampered with.
  3. Portable — The pointer should survive model swaps, prompt rewrites, and IDE migrations.
  4. 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:

PropertyVector DB memoryIPFS content memory
Stable pointer across model swapsNo — vectors reindex per modelYes — CID is a hash, not an embedding
Verifiable contentNo — trust the DB rowYes — recompute hash from bytes
Portable across agents / IDEsOnly if they share the DBYes — any gateway, any pinning service
Auditable byte-for-byteHard — vectors are opaque floatsTrivial — bytes are bytes
Similarity searchYes — the primary featureNo — 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 object
  • ipfs_import_car — import a CAR file (DAG import)
  • ipfs_list — list your uploaded files
  • ipfs_get — get file metadata by CID
  • ipfs_delete — unpin and delete a file
  • ipfs_pin — pin an existing CID from the network
  • ipfs_pin_status — check pin progress
  • ipfs_folders_list — list your folders
  • ipfs_folders_create — create a new folder
  • ipfs_profile — plan, storage, bandwidth
  • ipfs_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-server

Restart 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 QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG to 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:

  1. Write — Agent uploads the source document to IPFS, gets a CID.
  2. Index — Agent chunks and embeds the document, writes vectors keyed by (CID, chunk_offset).
  3. Query — Agent runs a similarity search over the vectors, gets top-K (CID, offset) pairs, fetches the exact chunks from IPFS.
  4. 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:

ProviderMCP serverDedicated gatewayREST API shape
IPFS NinjaYes — 12 tools, @ipfs-ninja/mcp-serverIncluded on all paid plansJSON with predictable response shapes
StorachaCommunity / DIYPublic IPFS gatewaysUCAN-based, protocol-first
LighthouseCommunity / DIYPublic IPFS gatewaysREST, encryption-first
PinataAnnouncedIncluded on paid plansREST

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#

  1. Sign up free — 500 files, 1 GB storage, 2 GB bandwidth/mo.
  2. Generate an API key.
  3. 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
  1. 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?
Vector DBs are great for similarity search but they bind memory to a specific embedding model and index. When you swap the model — from Claude Opus 4 to 4.5, or from OpenAI to Anthropic — the old vectors are meaningless. IPFS CIDs are model-agnostic: the same bytes always produce the same CID. Use vectors for retrieval, IPFS for the durable source of truth.
What is MCP and why does it matter for agents?
Model Context Protocol (MCP) is an open standard from Anthropic for connecting AI assistants to external tools. An MCP server exposes structured tools (functions with schemas) that Claude Code, Cursor, Windsurf, and Claude Desktop can call during a conversation. Our MCP server exposes 12 IPFS tools — the agent uploads, pins, lists, and retrieves content by name, and IPFS handles the addressing and persistence.
Can two different agents share memory through IPFS?
Yes — that's the point of content addressing. Agent A uploads a dataset, gets back a CID, and passes the CID to agent B (via a database, an event bus, or a shared file). Agent B fetches by CID and gets the exact same bytes, verified by hash. There's no shared database schema, no coordination layer — just a URL that anyone with the CID can resolve.
How is this different from Storacha, Lighthouse AI Memory, or Pinata Agents?
All of us pin content to IPFS. The differences are in the developer surface: IPFS Ninja ships a first-party MCP server that works out of the box in Claude Code / Cursor / Claude Desktop, a JSON REST API with predictable response shapes, and a dedicated gateway on every paid plan. If you're building an agent today with Claude Code or Cursor, our MCP integration is the shortest path to a working demo.
Is my agent's data private if I upload it to IPFS?
IPFS itself doesn't encrypt content — anyone with the CID can retrieve it from any gateway that has it pinned. If you need privacy, encrypt the payload before you upload it (AES-256, sealed box, whatever your threat model demands) and store only the encryption key on your side. The CID becomes a pointer to opaque ciphertext that only your agent can decrypt.
Nacho Coll

About the author

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.

Back to Blog

Related Posts