🐌

Your AI agent forgets everything.
This server fixes that.

An MCP server that gives Claude Code, Claude Desktop, VS Code β€” any MCP client β€” universal long-term memory: typed records searched by meaning, experience that transfers between projects, and a knowledge graph. All on your machine.

Get started in 3 steps Source on GitHub
local-first no API keys multilingual semantic search SQLite β†’ PostgreSQL .NET 10

What changes once it is connected

The agent stops living inside a single chat. Decisions, lessons and preferences survive /clear, survive the week-end, and β€” most importantly β€” survive the jump to your next project.

🧠

Memory across sessions

Clear the chat, come back tomorrow β€” the agent recalls what was decided and why, from a database, not from scrollback.

πŸ”

Experience transfer

Start a new project and the server answers "where have I seen this before?" β€” similar past projects arrive with their lessons, so old mistakes are not repeated.

πŸ”Ž

Search by meaning

A multilingual embedding model (e5) runs in-process. A question in Russian finds a lesson written in English. No keywords, no exact phrasing.

🧹

Self-cleaning

Near-duplicates are refused, short-lived events expire, stale records get nominated for review. Durable knowledge is never deleted without your confirmation.

πŸ•ΈοΈ

Knowledge graph

Directed, typed links between projects β€” uses, depends_on, implements… Symmetric "related" is never stored: vector similarity derives it on the fly.

πŸ”’

Yours, locally

One SQLite file in your home directory by default. No accounts, no cloud, no telemetry. When you outgrow one machine β€” the same server speaks PostgreSQL.

Quick start

1

Install

Needs the .NET 10 SDK. This puts the snail-mcp-memory command on your PATH (~/.dotnet/tools β€” the .NET installer takes care of it):

shell β€” dotnet tool
dotnet tool install --global Snail.MCP.Memory --prerelease

Alternative, no install: the SDK ships the dnx runner β€” dnx Snail.MCP.Memory --yes --prerelease fetches the package from NuGet on first use, caches it and runs it.

2

Connect it to your client

For Claude Code, one command; other clients are a few lines of JSON β€” see Clients.

shell
claude mcp add mem0 --scope user -- snail-mcp-memory
3

Use it

In your next session, just say:

init memory for this project β€” we are building a REST API in Go with PostgreSQL

The agent registers the project, and if memory already knows similar work, the reply carries a briefing: which past projects look alike and which of their lessons apply here. From then on the agent saves decisions as you work and recalls them when they matter.

First run: the embedding model (~123 MB) is downloaded once into ~/.snail-mcp-memory/models/. Until it arrives β€” or on machines where it never can β€” everything still works, with text search instead of semantic search.

Connecting to a client

The server speaks stdio: every client config boils down to "run snail-mcp-memory" (or dnx Snail.MCP.Memory --yes --prerelease to skip installation). The examples register it as mem0 β€” the slash commands in the repo pre-approve tools under that name. Zero configuration required β€” settings only change the defaults.

Claude Code β€” .mcp.json

.mcp.json
{
  "mcpServers": {
    "mem0": {
      "command": "snail-mcp-memory"
    }
  }
}

Running through dnx instead: "command": "dnx", "args": ["Snail.MCP.Memory", "--yes", "--prerelease"].

Claude Desktop

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Β· Windows: %APPDATA%\Claude\claude_desktop_config.json β€” same JSON as above. If the command is not found, use the full path /Users/<you>/.dotnet/tools/snail-mcp-memory.

VS Code β€” .vscode/mcp.json

.vscode/mcp.json
{
  "servers": {
    "mem0": {
      "type": "stdio",
      "command": "snail-mcp-memory"
    }
  }
}

Configuration

Every setting is an optional environment variable. This example lists all of them with their defaults β€” copy it and keep only the lines you change:

.mcp.json β€” every setting, default values
{
  "mcpServers": {
    "mem0": {
      "command": "snail-mcp-memory",
      "env": {
        "SNAIL_MCP_MEMORY_PROVIDER": "Sqlite",
        "SNAIL_MCP_MEMORY_DIRECTORY": "~/.snail-mcp-memory",
        "SNAIL_MCP_MEMORY_CONNECTION_STRING": "",
        "SNAIL_MCP_MEMORY_WORKSPACE": "",
        "SNAIL_MCP_MEMORY_EMBEDDING_ENABLED": "true",
        "SNAIL_MCP_MEMORY_EMBEDDING_MODEL_PATH": "~/.snail-mcp-memory/models/model.onnx",
        "SNAIL_MCP_MEMORY_EMBEDDING_TOKENIZER_PATH": "~/.snail-mcp-memory/models/sentencepiece.bpe.model",
        "SNAIL_MCP_MEMORY_EMBEDDING_MODEL_URL": "https://huggingface.co/Xenova/multilingual-e5-small/resolve/main/onnx/model_quantized.onnx",
        "SNAIL_MCP_MEMORY_EMBEDDING_TOKENIZER_URL": "https://huggingface.co/intfloat/multilingual-e5-small/resolve/main/sentencepiece.bpe.model",
        "SNAIL_MCP_MEMORY_EMBEDDING_DIMENSIONS": "384",
        "SNAIL_MCP_MEMORY_DUPLICATE_THRESHOLD": "0.95",
        "SNAIL_MCP_MEMORY_SIMILARITY_FLOOR": "0.75",
        "SNAIL_MCP_MEMORY_IDLE_TIMEOUT_MINUTES": "60"
      }
    }
  }
}

The same keys β€” bare names, without the prefix β€” can live in a JSON file instead: ~/.snail-mcp-memory.json (also read: the path in SNAIL_MCP_MEMORY_CONFIG, ./.snail-mcp-memory.json, ./snail-mcp-memory.json, ~/.config/snail-mcp-memory/config.json). Environment variables win over the file.

SettingDefaultMeaning
PROVIDERSqliteSqlite β€” single local file with sqlite-vec; Postgres β€” server database with pgvector
DIRECTORY~/.snail-mcp-memorywhere the database and the models live; understands a leading ~
CONNECTION_STRINGβ€”SQLite: a file path or Data Source=… (default {Directory}/memory.db). PostgreSQL: the full connection string, required
WORKSPACE(empty)partition of a shared database: writes are tagged with it, reads see only it; empty β€” the whole base
EMBEDDING_ENABLEDtruefalse turns semantic search off; recall falls back to text matching
EMBEDDING_MODEL_PATH{Directory}/models/…where the ONNX model lives; downloaded on first use
EMBEDDING_TOKENIZER_PATH{Directory}/models/…where the SentencePiece tokenizer lives; downloaded on first use
EMBEDDING_MODEL_URL / …_TOKENIZER_URLe5-smalldownload sources for a missing model (default: multilingual-e5-small, int8)
EMBEDDING_DIMENSIONS384vector length of the configured model β€” change only together with the model
DUPLICATE_THRESHOLD0.95similarity above which remember refuses a near-duplicate and offers supersession
SIMILARITY_FLOOR0.75similarity below which a search hit is dropped; raise to ~0.8 if recall feels noisy
IDLE_TIMEOUT_MINUTES60minutes without a tool call before an orphaned server process shuts itself down

PostgreSQL

For a shared or backed-up memory, point the server at PostgreSQL with the pgvector extension (the pgvector/pgvector Docker images ship it). Nothing else changes β€” same tools, same behavior:

env
"SNAIL_MCP_MEMORY_PROVIDER": "Postgres",
"SNAIL_MCP_MEMORY_CONNECTION_STRING": "Host=db.example.com;Database=memory;Username=snail;Password=…"

What the agent can do with it

You normally never call these yourself β€” the agent does, guided by instructions the server ships inside the protocol itself. Knowing them helps you phrase requests.

Every record carries a kind; the vocabulary is open, the core carries semantics:

factdecisionlesson preferencereferencetask event Β· expires in 90 daysnote
ToolWhat it does
init_project_memoryregisters a project and returns the experience briefing; description finds similar past projects, seedFrom preloads named donors
rememberstores one typed record; refuses a near-duplicate (supersede with replaceId, keep both with force)
recallsemantic search; empty project β€” the whole memory (that is how experience crosses projects), empty query β€” an overview of the newest records
forgetdeletes records by id, several ids comma-separated
review_memorynominates stale records for deletion; the deletion itself stays a confirmed forget
list_projectsthe projects that have memory, optionally narrowed by a name prefix
rename_projectrenames a project everywhere: registry, records, edges
link_projectsa directed, typed edge: uses, depends_on, design_of, part_of, implements, documents
unlink_projectsremoves the edges of a project pair
get_graphthe edges around a project, depth 1–5, without loading records

Integration: copy two things from the repo

The protocol carries the tool descriptions β€” enough for basic use. The full integration is two files you copy yourself from the git repository into your agent's setup; nothing is installed automatically:

1. Slash commands. .claude/commands/ holds mem0-init, mem0-recall, mem0-remember, mem0-link, mem0-graph, mem0-list β€” manual one-shot shortcuts with the mem0 tools pre-approved, so they run without permission prompts:

shell
cp .claude/commands/mem0-*.md ~/.claude/commands/

Registered the server under another name? Adjust the mcp__mem0__ prefix inside the files.

2. Memory rules. server-instructions.md at the repo root is the full instruction set β€” the kind vocabulary, when to save unprompted, when to search before proposing, how to self-heal wrong records. Paste its content into your agent's instruction file β€” ~/.claude/CLAUDE.md for Claude Code, or the system prompt of a custom agent. The agent works without it, but with it the memory maintains itself.

Sharing one database

πŸ‘€

Several projects, one person

Nothing to configure. Projects live side by side in one database β€” that is exactly what makes cross-project experience transfer work.

πŸ‘₯

Several people, one database

Give each their own WORKSPACE. Writes are tagged with it, reads never leave it β€” teammates do not see each other's memory. An empty workspace reads the whole base.

Good to know

🌍 Languagerecord content is stored in the language of your conversation; the model is multilingual, so search works across languages
✈️ Offlineafter the one-time model download the server needs no network at all
⏳ Lifecycleevent records expire after 90 days; durable kinds are only deleted by an explicit, confirmed forget
🧯 Housekeepingan orphaned server process shuts itself down after an hour of silence (IDLE_TIMEOUT_MINUTES)
πŸ—„οΈ Your dataone SQLite file at ~/.snail-mcp-memory/memory.db, inspectable with any SQLite browser