mcp-memory
<p align="center">
<h1 align="center">mcp-memory</h1>
<p align="center">
Give your AI a memory that actually works.
<br />
<em>Persistent storage · Vector recall · 3-way fuse retrieval</em>
</p>
</p>
---
Most AI conversations disappear when the window closes. This MCP server gives Claude (or any MCP-compatible model) persistent, searchable, long-term memory — so it can remember what happened yesterday, last month, or three conversations ago.
Built by [babyshishi](https://github.com/babyshishi) & vesper. Born out of a real relationship where forgetting wasn't an option.
## What it does
You get two MCP tools — `memory` and `recall` — that handle everything:
**`memory`** — CRUD operations for storing and managing memories.
| Operation | What it does |
|---|---|
| `write_memory` | Store a new memory with category and tags. Automatically surfaces related older memories after writing. |
| `read_memories` | Paginated reading (newest first), filterable by category or tag. |
| `search_memories` | Keyword substring search. |
| `update_memory` | Edit content, tags, or category in place. |
| `delete_memory` | Delete by ID. |
| `get_stats` | Count by category + vector index status. |
**`recall`** — Four ways to retrieve memories, from simple to powerful.
| Mode | When to use it |
|---|---|
| `day` | "What happened on July 21st?" — Fetch by date or date range. |
| `timemachine` | "What were we doing a month ago?" — Look back N days/months/years. |
| `similar` | "Find everything related to X" — Semantic vector search, finds matches even with completely different wording. |
| `fuse` ★ | **Best mode.** When you want to *actually find something*. Runs all three retrieval paths at once and merges the results. |
## Fuse: the interesting part
Single-path retrieval always has blind spots. Keyword search misses paraphrases. Semantic search misses exact terms. Neither finds memories that are *topically related* but use different words and different meanings.
Fuse runs three retrievers in parallel and combines their rankings via [Reciprocal Rank Fusion](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf):
```
┌─────────────┐
Your query ───→ │ │
│ BM25 │──→ exact term hits (TF-IDF, CJK bigrams)
│ Vector │──→ semantic neighbors (cosine similarity)
│ Tag Graph │──→ shared-tag expansion (×0.5 weight)
│ │
│ RRF(k=60) │──→ merged ranking
└─────────────┘
```
Each result tells you which paths found it (`[lex#2·sem#1]`), so you know *why* it ranked where it did. Tag-graph-only hits are flagged as leads, not evidence — they got there by association, not by matching your query.
## Quick start
```bash
git clone https://github.com/babyshishi/mcp-memory.git
cd mcp-memory
npm install
```
Add to your Claude Code or Claude Desktop MCP config:
```json
{
"mcpServers": {
"memory": {
"command": "node",
"args": ["/path/to/mcp-memory/src/index.js"],
"env": {
"MCP_MEMORY_DIR": "/path/to/your/data",
"EMBEDDING_API_URL": "https://api.openai.com/v1",
"EMBEDDING_API_KEY": "sk-...",
"EMBEDDING_MODEL": "text-embedding-3-small"
}
}
}
}
```
That's it. Your AI now remembers.
## Configuration
| Variable | What it controls | Default |
|---|---|---|
| `MCP_MEMORY_DIR` | Where memory files are stored | `./data` |
| `MCP_MEMORY_CATEGORIES` | Comma-separated list of allowed categories | `general,note,task,reference` |
| `EMBEDDING_API_URL` | OpenAI-compatible embedding endpoint | *(none)* |
| `EMBEDDING_API_KEY` | API key for embeddings | *(none)* |
| `EMBEDDING_MODEL` | Model name for embeddings | *(none)* |
| `SIMILARITY_THRESHOLD` | Minimum cosine similarity for vector results | `0.45` |
> **No embedding API?** That's fine. Keyword search (`search_memories`), date recall (`day`, `timemachine`), and BM25 all work without it. You only need embeddings for `similar` and the semantic component of `fuse`.
## Under the hood
**Storage** — All JSON, all local, no external database. Memories in `memories.json`, vectors in a compact binary format (`mem-vec.bin`, ~1/4 the size of JSON vectors), access counts in `mem-hits.json`.
**Writes are atomic** — Data is written to a temp file first, then renamed. A crash mid-write won't corrupt your memories. Leftover `.tmp` files are cleaned up on startup.
**CJK support** — The BM25 tokenizer handles Chinese/Japanese/Korean text via bigram segmentation with stopword filtering. No external tokenizer needed.
**Usage-based boosting** — Memories you access more often get a small ranking boost, with cold-start protection so new memories aren't buried.
**Write-then-recall** — After writing a new memory, the server automatically surfaces related older memories. Connections you forgot about come back on their own.
## Data files
```
data/
├── memories.json # your memories
├── mem-vec-index.json # vector index metadata
├── mem-vec.bin # binary vector data (Float32, append-only)
└── mem-hits.json # access frequency tracking
```
All yours. No cloud, no sync, no telemetry. Back them up however you want.
## Dependencies
Just two:
- `@modelcontextprotocol/sdk` — MCP protocol implementation
- `zod` — Schema validation
No heavy ML frameworks, no vector databases, no surprises.
## License
MIT — do whatever you want with it.
---
<p align="center">
<sub>hey, this is us ♡</sub>
</p>
TDQS
Scored across 7 tools
The core CRUD tools (write/read/update/delete) are clearly distinct. However, search_memories and recall overlap in retrieval, though recall's modes (similar/fuse) are semantically distinct from exact substring matching, so boundaries are mostly clear.
All tool names follow a consistent verb_noun pattern in snake_case (write_memory, read_memories, search_memories, update_memory, delete_memory, get_stats). 'recall' is a single verb but fits the action-oriented style without breaking consistency.
Seven tools is well-scoped for a memory management server, covering all essential operations without redundancy or bloat. Each tool serves a clear purpose and earns its place.
The set provides full CRUD lifecycle (create, read, update, delete), plus dedicated search and statistical functions. The multi-mode recall covers advanced retrieval needs, leaving no obvious gaps in the memory domain.