A local-first MCP server that gives any MCP-compatible LLM client persistent, semantically searchable memory. No cloud services — just a Go binary, a local Ollama instance for embeddings, and a chromem-go vector store on disk.
Built primarily for OpenCode but works with any MCP client that supports stdio transport (Claude Desktop, Cursor, etc.) or Streamable HTTP transport (Hermes Agent, etc.).
Client (stdio | streamable HTTP)
│ JSON-RPC 2.0
▼
mcp-memory (Go binary)
├── Ollama → nomic-embed-text embeddings (768-dim)
└── chromem-go → ~/.local/share/mcp-memory/db/ (gzip'd vector store, no server)
When you call store_memory, the content is embedded via Ollama and persisted to a local chromem-go collection alongside its metadata. When you call search_memories, your query is embedded the same way and matched against stored vectors using cosine similarity.
All data stays on your machine.
| Tool | Description |
|---|---|
store_memory |
Embed and persist a memory. Returns its UUID. |
search_memories |
Semantic similarity search. Returns ranked results with scores. |
browse_recent |
List recent memories, newest first. Filterable by type and time window. |
recall_session |
Retrieve all memories from a named session, in chronological order. |
delete_memory |
Remove a memory by UUID. |
get_stats |
Counts by type, oldest/newest timestamps, unique session count. |
Each stored memory has a memory_type field:
| Type | Use for |
|---|---|
conversation |
A turn or exchange in an LLM conversation |
fact |
A distilled assertion — "user prefers dark mode", "project X uses Rust" |
code |
A code snippet worth keeping |
decision |
An architectural or design decision and its rationale |
note |
Anything else (default) |
- A running Ollama instance with
nomic-embed-textpulled - Go 1.23+ (only for source builds)
ollama pull nomic-embed-textnix build git+https://git.4ray.co/jean/mcp-memory.git
# binary at ./result/bin/mcp-memory
# or run directly without installing
nix run git+https://git.4ray.co/jean/mcp-memory.gitgit clone https://git.4ray.co/jean/mcp-memory.git
cd mcp-memory
go build -o ~/.local/bin/mcp-memory .All configuration is via environment variables or matching CLI flags. Every option has a default so zero-config local usage works out of the box.
| Variable / Flag | Default | Description |
|---|---|---|
OLLAMA_URL / --ollama-url |
http://localhost:11434 |
Ollama base URL (no trailing slash) |
EMBED_MODEL / --embed-model |
nomic-embed-text |
Ollama model used for embeddings |
EMBED_DIMS / --embed-dims |
768 |
Embedding vector dimensions — must match the model |
MEMORY_DB_PATH / --db-path |
~/.local/share/mcp-memory/db |
Persistent store directory (XDG-compliant) |
MCP_MEMORY_SOURCE / --source |
opencode |
Label attached to every stored memory identifying the client |
MCP_TRANSPORT / --transport |
stdio |
Transport: stdio or http (Streamable HTTP on /mcp) |
MCP_HTTP_BIND / --http-bind |
127.0.0.1:8645 |
Bind address for HTTP transport |
Add to ~/.config/opencode/opencode.jsonc:
Run mcp-memory as a daemon and point Hermes at it:
MCP_TRANSPORT=http MCP_HTTP_BIND=127.0.0.1:8645 mcp-memoryIn ~/.hermes/config.yaml:
mcp_servers:
memory:
url: http://127.0.0.1:8645/mcp
enabled: trueIn claude_desktop_config.json:
{
"mcpServers": {
"memory": {
"command": "/home/you/.local/bin/mcp-memory",
"env": {
"OLLAMA_URL": "http://localhost:11434",
"MEMORY_DB_PATH": "/home/you/.local/share/mcp-memory/db"
}
}
}
}# Dev shell with go + gopls + gotools
nix develop
# Build
go build .
# Run (stdio)
OLLAMA_URL=http://localhost:11434 go run .
# Run (HTTP)
MCP_TRANSPORT=http MCP_HTTP_BIND=127.0.0.1:8645 go run .
# Tidy modules
go mod tidy.
├── main.go — entry point: parse config, init store, branch on transport
├── config.go — Config struct, env vars + flags
├── embedder.go — OllamaEmbedder: HTTP client for /api/embeddings
├── store.go — chromem-go wrapper: store, search, browse, recall, delete, stats
├── server.go — MCP server: registers all six tools
└── types.go — MemoryType, MemoryEntry, parseMemoryType, docToEntry
| Layer | Module |
|---|---|
| MCP protocol | modelcontextprotocol/go-sdk — official |
| Embeddings | direct net/http calls to Ollama's /api/embeddings |
| Vector storage | philippgille/chromem-go — pure Go, no CGO |
The default model is nomic-embed-text (137 MB, 768-dim, runs fast on CPU or GPU). To use a different model, set EMBED_MODEL and EMBED_DIMS — the embedder errors early if the returned vector size doesn't match.
Other good options available via Ollama:
| Model | Dims | Notes |
|---|---|---|
nomic-embed-text |
768 | Default. Fast, solid English quality. |
qwen3-embedding:0.6b |
1024 | Better quality, multilingual, 32K context. |
mxbai-embed-large |
1024 | Strong English quality, 512-token context limit. |
Note: If you switch models, existing vectors in the DB were embedded with the old model and similarity scores will be meaningless. Either wipe
MEMORY_DB_PATHor use a separate path per model.
chromem-go stores data as gzip-compressed gob files under the configured MEMORY_DB_PATH. The directory is safe to back up and copy between machines.
To wipe all memories:
rm -rf ~/.local/share/mcp-memory/db/The directory and collection are recreated automatically on next startup.
The on-disk layout is incompatible — chromem-go uses gzip'd gobs, LanceDB used Arrow columnar files. There is no automatic migration path. Either:
- Start fresh (recommended for personal corpora — embeddings are cheap to regenerate from source content).
- Keep the old binary (
v0.1.0tag) running pointed at the existing LanceDB directory while the new binary runs against a fresh path.
mcp-memory is licensed under the MIT License. See LICENSE for details.
{ "mcp": { "memory": { "type": "local", "command": ["/home/you/.local/bin/mcp-memory"], "enabled": true, "environment": { "OLLAMA_URL": "http://localhost:11434", "EMBED_MODEL": "nomic-embed-text", "EMBED_DIMS": "768", "MEMORY_DB_PATH": "/home/you/.local/share/mcp-memory/db", "MCP_MEMORY_SOURCE": "opencode", }, }, }, }