Skip to main content
Glama
README.md
# memory-mcp

A unified, local memory for Claude — an MCP server that stores memories as
**1024-dimensional embeddings** in a single SQLite file (`memory.db`) and serves
them back over the Model Context Protocol.

- **Runtime:** TypeScript, stdio transport
- **Store:** SQLite + [`sqlite-vec`](https://github.com/asg017/sqlite-vec)
- **Embedder:** pluggable — local **Ollama** (default) or remote **Voyage AI**
- **Vectors:** `float[1024]`, cosine distance

## Data model (two tables, one id)

One memory is stored as two rows that share the same id:

| `memories` (normal table) | `vec_memories` (vec0 virtual table) |
| --- | --- |
| `id, text, tags, source, parent_id, content_hash, created_at, updated_at` | `rowid, embedding float[1024]` |

`sqlite-vec`'s `vec0` table only holds the vector, so the readable content lives
in `memories` and the two are joined on `memories.id = vec_memories.rowid`.
`content_hash` (sha256 of the text) makes exact duplicates a no-op.

## Setup

```bash
cd ~/memory-mcp
npm install
npm run build
```

### Local embeddings (default, nothing leaves the machine)

```bash
# install & run Ollama, then pull a 1024-d model:
ollama pull bge-large
ollama serve            # if not already running
```

### Remote embeddings (Voyage)

```bash
export EMBEDDER=voyage
export VOYAGE_API_KEY=...   # voyage-3 = 1024-d
```

Copy `.env.example` to `.env` to see all options.

## Wire it into Claude

Add to `claude_desktop_config.json` (Claude Desktop) or `.mcp.json` (Claude Code):

```json
{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": ["/Users/tylertabarovsky/memory-mcp/dist/server.js"],
      "env": { "EMBEDDER": "ollama" }
    }
  }
}
```

## Tools

| Tool | Args | Does |
| --- | --- | --- |
| `memory_write` | `text, tags?, source?` | chunk → embed → store |
| `memory_search` | `query, k?` | embed query → cosine kNN → ranked hits |
| `memory_list` | `limit?, tag?` | recent memories, optional tag filter |
| `memory_delete` | `id` | remove content + vector |

## Capture model

This scaffold uses the **explicit** model: Claude calls `memory_write` when it
decides something is worth keeping. Simplest and least noisy. A passive/auto
capture layer can be added later on top of the same tools.