AI Memory MCP
by pateljeel123
README.md
# AI Memory MCP
A persistent, searchable memory layer for AI assistants, exposed as an MCP
(Model Context Protocol) server. Works with Claude, Cursor, Windsurf, VS
Code, Continue, or any other MCP-compatible client. Implements the MVP
scope from the AI Memory MCP PRD: CRUD, namespaces, hybrid ranked search,
relationships, chat-context assembly, import/export, and optional
LLM-powered auto-extraction.
## Why this design
- **Zero required setup.** Storage uses Node's built-in `node:sqlite`
(experimental but stable enough for this), so there's no native module to
compile and no external database to run. One file, `memory.db`, holds
everything.
- **Provider-agnostic embeddings.** Ships with a dependency-free local
hashing embedder so semantic search works out of the box with no API
key. Swap in a real embedding provider (OpenAI-compatible endpoint) via
env vars when you want production-quality semantic recall — see below.
- **Auto-extraction is optional.** Set `ANTHROPIC_API_KEY` to enable the
`memory_extract` tool, which asks Claude to pull memory-worthy facts out
of raw conversation text. Without a key, everything else still works;
you just call `memory_add` explicitly instead.
## Install
```bash
npm install
npm run build
```
Requires Node.js >= 22.5 (uses `node:sqlite`).
## Run
```bash
npm start
```
This starts the server on stdio, which is how MCP clients (Claude Desktop,
Cursor, etc.) talk to it. You won't see interactive output — clients spawn
this process directly.
### Example: Claude Desktop config
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"ai-memory": {
"command": "node",
"args": ["--experimental-sqlite", "/absolute/path/to/ai-memory-mcp/dist/index.js"],
"env": {
"MEMORY_DB_PATH": "/absolute/path/to/ai-memory-mcp/memory.db",
"DEFAULT_USER_ID": "your-name"
}
}
}
}
```
## Configuration (environment variables)
| Variable | Default | Purpose |
|---|---|---|
| `MEMORY_DB_PATH` | `./memory.db` | Path to the SQLite database file |
| `DEFAULT_USER_ID` | `default-user` | User id used when a tool call omits `user_id` |
| `EMBEDDING_PROVIDER` | *(unset → local hash)* | `openai` \| `custom` \| unset |
| `EMBEDDING_API_URL` | provider default | Endpoint for `openai`/`custom` |
| `OPENAI_API_KEY` | — | Used when `EMBEDDING_PROVIDER=openai` |
| `EMBEDDING_API_KEY` | — | Used when `EMBEDDING_PROVIDER=custom` |
| `EMBEDDING_MODEL` | `text-embedding-3-small` | Remote embedding model name |
| `EMBEDDING_DIM` | `256` (local) / `1536` (openai) | Vector dimensionality |
| `ANTHROPIC_API_KEY` | — | Enables `memory_extract` auto-extraction |
**Note on the local embedding fallback:** it's a deterministic
hashing-trick bag-of-words vector — good enough to demo hybrid ranking and
run fully offline, but it won't catch deep paraphrases the way a real
embedding model will (e.g. it may not recognize "I prefer TypeScript" and
"I love typed JS" as near-duplicates). For real semantic quality in
production, point `EMBEDDING_PROVIDER=openai` at a real embeddings
endpoint.
## Tools exposed
| Tool | Maps to PRD section 14 |
|---|---|
| `memory_add` | `memory.add` — stores a memory, auto-dedupes near-identical content |
| `memory_search` | `memory.search` — hybrid ranked search |
| `memory_chat_context` | `memory.chat_context` — token/char-budgeted context for the current prompt |
| `memory_update` | `memory.update` |
| `memory_delete` | `memory.delete` |
| `memory_list` | `memory.list` |
| `memory_related` | `memory.related` — relationship graph traversal |
| `memory_pin` / `memory_unpin` | `memory.pin` / `memory.unpin` |
| `memory_stats` | `memory.stats` |
| `memory_export` | `memory.export` — JSON or Markdown |
| `memory_import` | `memory.import` — JSON or Markdown |
| `memory_extract` | Section 9 automatic extraction, requires `ANTHROPIC_API_KEY` |
Resources: `memory://stats`, `memory://recent`, `memory://important`.
## Ranking formula (PRD section 16)
```
final = 0.45 * semantic + 0.25 * importance + 0.15 * recency + 0.10 * frequency + 0.05 * pin
```
- `recency` decays exponentially with a ~30 day half-life.
- `frequency` is a log-scaled function of access count (capped so heavy
repeat access doesn't dominate).
- `pin` is a flat boost for pinned memories.
Tune the weights in `src/memoryEngine.ts` (`WEIGHTS`) once you have real
usage data — the PRD flags these defaults as a starting point, not a final
answer.
## Deduplication
On `memory_add`, the new memory's embedding is compared against existing
memories in the same namespace. Above a 0.93 cosine-similarity threshold,
the call updates the existing memory (merging tags/entities, raising
importance) instead of inserting a duplicate. Threshold and dedup scope
live in `src/memoryEngine.ts`.
## What's implemented vs. deferred from the PRD
**Implemented (MVP, section 28):** persistent storage, hybrid search,
importance/recency/frequency/pin ranking, CRUD, namespaces, relationships,
`memory.chat_context`, JSON/Markdown import-export, provider-agnostic
embeddings.
**Deferred (sections 24–25, "future/nice-to-have"):** contradiction
detection beyond simple dedup, memory aging/compression/reflection,
multimodal memories (voice/image/PDF), third-party syncs (GitHub, Notion,
Slack, Calendar, etc.), pgvector/Postgres backend, encryption-at-rest,
multi-tenant auth (JWT/OAuth) — the current server assumes a single
trusted local client per the typical MCP desktop-app deployment model.
## Extending to Postgres + pgvector
The `MemoryDB` class in `src/db.ts` is the only place that talks to
storage. To move to Postgres/pgvector for multi-user or team deployments,
reimplement that class against `pg` with a `vector` column and an ANN
index, keeping the same method signatures — nothing else in the codebase
needs to change.
## Project layout
```
src/
types.ts shared types (MemoryRecord, SearchResult, etc.)
db.ts SQLite storage layer (node:sqlite)
embeddings.ts provider-agnostic embedding layer + local fallback
extraction.ts optional Anthropic-powered fact extraction
memoryEngine.ts ranking, search, dedup, chat_context, import/export
server.ts MCP tool + resource registration
index.ts stdio entrypoint
```
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues