Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Persistent memory MCP server that stores and retrieves memories in Markdown files, enabling shared context across multiple AI agents with hybrid search and deduplication.

README.md

mem-persistence

🧠 Persistent memory MCP server for AI agents — one memory, every agent, your files.

mem-persistence lets Claude Desktop, Claude Code, Cursor, Zed, and any MCP-compatible client share the same persistent memory, backed by plain Markdown files you own and can edit by hand.

Why?

AI agents have amnesia. Each tool keeps its own silo — Claude Code forgets what OpenClaw knows, Cursor can't recall what you told Claude yesterday. Your context is scattered across sessions that evaporate.

mem-persistence fixes this:

  • Markdown is the source of truth — not a database, not a binary blob. Files you can read, edit, and version with git.
  • Hybrid search — token matching + semantic embeddings for accurate recall.
  • Embedding providers — Ollama (local & private, recommended), Gemini, OpenAI, or none (token-only). Cached to disk.
  • Deduplication — prevents writing the same fact twice (token + entity overlap detection).
  • Works offline — no cloud dependency. Embeddings are optional.

MCP Tools

| Tool | Description | |---|---| | memory_search(query, maxResults?) | Hybrid search across all .md files | | memory_write(content, file?, section?) | Write with automatic deduplication | | memory_read(path, from?, lines?) | Read a specific file or section | | memory_checkpoint(summary) | Save a session checkpoint to a daily note | | memory_entities(query?) | Query the knowledge graph (if entities.md exists) | | memory_status() | Index stats: files, chunks, last sync | | fact_save(entity, attribute, value, confidence?, source?) | Save an exact (entity, attribute, value) fact with a verified→high_probability→false confidence ladder | | fact_get(entity, attribute) | Exact key-value lookup | | fact_query(entity?, attribute?, confidence?) | List facts by filter | | fact_demote(entity, attribute, source?) | Mark a fact false without a replacement |

Facts are stored in data/facts.db (built-in node:sqlite), separate from the markdown corpus — exact key-value recall for names, settings, and IDs that semantic search handles badly.

---

Quick Start

1. Install and build

git clone https://github.com/emiliotorrens/mem-persistence.git
cd mem-persistence
npm install
npm run build

2. Start the server

node dist/index.js --workspace /path/to/your/workspace --port 3456

3. Connect a client

Pick the setup that matches your client — see Client Setup below.

4. Add agent instructions

Copy AGENT_INSTRUCTIONS.md into your agent's instruction file:

| Editor | Where to paste | |---|---| | Claude Desktop | Settings → Personal Preferences | | Claude Code | CLAUDE.md in project root | | Cursor | .cursorrules in project root | | Windsurf | .windsurfrules in project root |

---

Client Setup

There are two MCP transports. Which one you need depends on the client:

| Transport | Clients | Where server runs | Remote access | |---|---|---|---| | HTTP | Claude Code, Cursor, Zed | Anywhere (local or remote) | ✅ via Tailscale/VPN | | stdio | Claude Desktop | Same machine as Desktop | ❌ (see proxy workaround) |

HTTP clients (Claude Code, Cursor, Zed)

Point to the running server URL:

{
  "mcpServers": {
    "memory": {
      "url": "http://127.0.0.1:3456/mem-persistence/mcp"
    }
  }
}

For remote access over Tailscale, replace 127.0.0.1 with the server's Tailscale hostname:

{
  "mcpServers": {
    "memory": {
      "url": "http://my-machine.tail1234.ts.net:3456/mem-persistence/mcp"
    }
  }
}

Claude Desktop (stdio, same machine)

Claude Desktop only supports stdio — it spawns mem-persistence as a child process.

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": [
        "/path/to/mem-persistence/dist/index.js",
        "--workspace", "/path/to/your/workspace"
      ],
      "env": {
        "MEM_PERSISTENCE_EMBEDDINGS": "ollama",
        "MEM_PERSISTENCE_EMBEDDINGS_MODEL": "embeddinggemma"
      }
    }
  }
}

See Embeddings for the other providers. If you omit env entirely, the server falls back to token-only search (no semantic matching).

WSL users (Windows): replace "command": "node" with "command": "wsl" and add "node" as the first element of args. ⚠️ Claude Desktop's env block is set on the Windows process and is not inherited by the WSL child. Pass the variables inside the command instead: ``json { "mcpServers": { "memory": { "command": "wsl", "args": [ "-e", "env", "MEM_PERSISTENCE_EMBEDDINGS=ollama", "MEM_PERSISTENCE_EMBEDDINGS_MODEL=embeddinggemma", "node", "/path/to/mem-persistence/dist/index.js", "--workspace", "/path/to/your/workspace" ] } } } ``

⚠️ Do not pass --port in stdio mode. It causes an EADDRINUSE conflict if an HTTP instance is already running.

💡 Already running an HTTP instance? Prefer the proxy setup over a second stdio process — even on the same machine. One server means one embedding config and one cache instead of two.

Remote Claude Desktop via proxy

If Claude Desktop runs on a different machine (e.g., a laptop) where mem-persistence isn't installed, use the bundled mcp-proxy.js to bridge stdio to the remote HTTP server.

Requirements on the client machine: Node.js + Tailscale. That's it — no cloning, no npm install.

  1. Copy mcp-proxy.js to the laptop (one file, zero dependencies).
  2. Add to Claude Desktop config:
{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": ["/path/to/mcp-proxy.js"],
      "env": {
        "MCP_REMOTE_URL": "http://my-machine.tail1234.ts.net:3456/mem-persistence/mcp"
      }
    }
  }
}

Desktop thinks it's talking to a local stdio server; the proxy forwards everything over HTTP.

Set MCP_DEBUG=1 to log proxy traffic to stderr for troubleshooting.

---

Running as a Service (PM2)

For production use, run the server as a persistent background service with PM2:

# 1. Install pm2
npm install -g pm2

# 2. Copy and edit the config
cp ecosystem.config.cjs.example ecosystem.config.cjs
# → Set workspace path and optional API keys

# 3. Start and persist
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup    # autostart on reboot (follow the printed instructions)

Health check: curl http://127.0.0.1:3456/health

---

Network Binding

By default, the server listens on 127.0.0.1 only. Use --bind to control which interfaces it binds to:

# Localhost + Tailscale (recommended for remote access)
node dist/index.js --workspace /path --port 3456 --bind 127.0.0.1,tailscale

# Localhost + explicit VPN IP
node dist/index.js --workspace /path --port 3456 --bind 127.0.0.1,10.0.0.5

# All interfaces (⚠️ only behind a firewall)
node dist/index.js --workspace /path --port 3456 --bind all

| --bind value | Resolves to | |---|---| | localhost | 127.0.0.1 | | tailscale | Auto-detected via tailscale ip -4 (100.x.x.x) | | all / 0.0.0.0 | All network interfaces | | Any IP | Used as-is |

In ecosystem.config.cjs:

args: '--workspace /path --port 3456 --bind 127.0.0.1,tailscale',

Or via environment variable: MEM_PERSISTENCE_BIND=127.0.0.1,tailscale

⚠️ Security: mem-persistence has no built-in authentication. Never expose the port to the public internet. Use --bind 127.0.0.1,tailscale to limit access to localhost + your private network.

---

Workspace

The --workspace flag points to the directory containing your memory files. mem-persistence indexes all .md files recursively.

Any directory with .md files works. Search quality improves with a layered layout:

| Layer | Path | Purpose | |---|---|---| | L1 | MEMORY.md | Long-term curated memory — highest search priority | | L2 | memory/.md | Daily notes, recent context | | L3 | reference/.md | Detailed data, historical records |

For automatic setup of this structure (with crons, dedup, and knowledge graph), see layered-memstack.

You can also set the workspace via environment variable: MEM_PERSISTENCE_WORKSPACE=/path/to/workspace

---

Embeddings

By default, search uses token matching only (Jaccard + containment + entity overlap). No API calls, works offline.

Enabling embeddings adds semantic understanding:

| Query | Token-only | With embeddings | |---|---|---| | "where does Emilio work" | ❌ no keyword overlap | ✅ understands meaning | | "what trips are coming up?" | ❌ misses if phrased differently | ✅ matches semantically |

Configure via environment variables. Three providers are supported — local (Ollama) is recommended: embeddings never leave your machine and there are no API quotas.

Option A — Ollama (local, private) — recommended

Run Ollama and pull a small embedding model:

ollama pull embeddinggemma                                  # 621 MB · 768 dims · multilingual
MEM_PERSISTENCE_EMBEDDINGS=ollama
MEM_PERSISTENCE_EMBEDDINGS_MODEL=embeddinggemma             # optional (default)
MEM_PERSISTENCE_EMBEDDINGS_BASE_URL=http://127.0.0.1:11434  # optional (default)

Option B — Cloud (Gemini / OpenAI)

Zero local footprint, but every chunk is sent to the provider's API and is subject to quotas. Get a free Gemini API key → aistudio.google.com.

MEM_PERSISTENCE_EMBEDDINGS=gemini    # "gemini" or "openai"
GOOGLE_API_KEY=your-key              # Gemini — free
OPENAI_API_KEY=your-key              # OpenAI — $0.02/M tokens

Details:

  • Hybrid scoring: 0.4 × token + 0.6 × vector
  • Disk cache: .mem-persistence/embeddings/ — keyed by model, no repeated calls
  • Silent fallback: if the provider is unavailable, falls back to token-only automatically

---

Deduplication

Before writing, mem-persistence checks if similar content already exists:

Input:  "GitHub configured with gh auth login, user emiliotorrens"
Match:  "gh auth login hecho — cuenta emiliotorrens, protocolo HTTPS"
Result: DUPLICATE (score: 0.90) — not written

Uses token similarity (Jaccard + containment) and entity overlap (IDs, dates, versions, URLs).

Adjust the threshold: MEM_PERSISTENCE_DEDUP_THRESHOLD=0.65 (default — lower = stricter).

---

OpenClaw Integration

If you use OpenClaw, mem-persistence coexists with OpenClaw's native memory:

  • External clients (Claude Desktop, Code, Cursor) → connect via mem-persistence (stdio or HTTP)
  • OpenClaw agent → uses its native memory-core plugin with hybrid search + embeddings

Both systems index the same Markdown files. mem-persistence is the MCP bridge for external clients; OpenClaw handles its own recall, wiki compilation, and dreaming.

---

Roadmap

  • [x] Deduplication engine
  • [x] Hybrid search (token + vector + MMR + temporal decay)
  • [x] MCP server — stdio and HTTP transports, 6 tools, TypeScript + ESM
  • [x] Embedding providers: Gemini (free) and OpenAI, with disk cache
  • [x] Request/response logging (.mem-persistence/logs/)
  • [x] HTTP mode — Tailscale-friendly, pm2-ready
  • [x] stdio→HTTP proxy for remote Claude Desktop
  • [ ] CLI (mem-persistence search "query")
  • [ ] Local embeddings via transformers.js (offline, no API key)
  • [ ] npm publish

---

Related

  • layered-memstack — OpenClaw skill that sets up a 3-layer memory system with automated maintenance. Uses mem-persistence as the MCP bridge for external clients.

Credits

  • OpenClaw — the agent framework where this was born and battle-tested
  • MCP — the protocol that makes cross-agent memory possible

License

MIT

---

Built with 🐾 by Emilio Torrens and Claw.

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Vector & Memory servers.