Skip to main content
Glama
smankoo

local-memory-mcp

by smankoo
README.md
# local-memory-mcp

A local-first long-term memory system for AI coding agents, exposed as an [MCP](https://modelcontextprotocol.io/) server. Built for [Kiro CLI](https://kiro.dev/cli/) but compatible with any MCP-capable client.

## Why

AI agents forget everything between sessions. This gives them persistent, searchable, semantically-aware memory — stored entirely on your machine.

## Architecture

```
┌─────────────────────────────────────────────────┐
│  MCP Server (stdio)                             │
│                                                 │
│  Tools: store_memory · recall · search_memories │
│         get_memory · forget · relate            │
│         query_graph · consolidate · memory_stats│
├─────────────────────────────────────────────────┤
│  Memory Engine                                  │
│  ┌───────────┬──────────┬───────────────────┐   │
│  │ Retrieval │ Embeddings│ Consolidation    │   │
│  │ (hybrid)  │ (local)   │ (decay + merge)  │   │
│  └───────────┴──────────┴───────────────────┘   │
├─────────────────────────────────────────────────┤
│  Storage Layer                                  │
│  ┌──────────┬───────────┬────────┬──────────┐   │
│  │ Memories │ Vectors   │ FTS5   │ Knowledge│   │
│  │ (SQLite) │(sqlite-vec)│(SQLite)│ Graph    │   │
│  └──────────┴───────────┴────────┴──────────┘   │
└─────────────────────────────────────────────────┘
```

**Hybrid retrieval** combines four signals into a single score:

| Signal | Weight | Source |
|--------|--------|--------|
| Vector similarity | 50% | sqlite-vec (L2 distance on 384-dim embeddings) |
| Full-text search | 25% | SQLite FTS5 |
| Recency | 15% | Exponential decay, 30-day half-life |
| Importance | 10% | User-assigned + access-frequency boosting |

**Embeddings** run fully locally via [Transformers.js](https://huggingface.co/docs/transformers.js) (ONNX runtime) using `all-MiniLM-L6-v2`. No API keys. No network calls after first model download.

**Knowledge graph** stores typed entities and weighted relations in SQLite with BFS traversal up to 3 hops.

**Consolidation** applies importance decay, merges near-duplicate memories, and prunes forgotten ones.

## Dual-scope storage

Every memory lives in one of two scopes:

- **Global** (`~/.local-memory/memory.db`) — your preferences, facts, cross-project knowledge
- **Project** (`.local-memory/memory.db` in repo root) — project-specific context, decisions, patterns

The agent can query either scope or both. Project scope auto-detects from `.git`, `package.json`, `Cargo.toml`, `pyproject.toml`, or `go.mod`.

## Tools

| Tool | Description |
|------|-------------|
| `store_memory` | Store a memory with type, scope, importance, and optional entity extraction |
| `recall` | Semantic recall — hybrid search combining all four signals |
| `search_memories` | Keyword-based full-text search |
| `get_memory` | Fetch a specific memory by ID |
| `forget` | Delete a memory and cascade to embeddings + graph |
| `relate` | Create/strengthen entity relationships in the knowledge graph |
| `query_graph` | Traverse the knowledge graph from an entity (BFS, 1-3 hops) |
| `consolidate` | Decay old memories, merge duplicates, prune weak ones |
| `memory_stats` | Counts for memories, entities, and relations per scope |

## Quickstart

### Install

```bash
git clone https://github.com/smankoo/local-memory-mcp.git
cd local-memory-mcp
npm install
npm run build
```

### Configure Kiro CLI

**Option A — Auto-configure:**

```bash
npx tsx scripts/install-kiro.ts          # global
npx tsx scripts/install-kiro.ts --project # project-level
```

**Option B — Manual:**

Add to `~/.kiro/settings/mcp.json`:

```json
{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": ["/absolute/path/to/local-memory-mcp/dist/index.js"],
      "env": {
        "MEMORY_DIR": "~/.local-memory"
      }
    }
  }
}
```

Then restart Kiro CLI and run `/mcp` to verify.

### Other MCP clients

Any client that speaks MCP over stdio works. The server binary is `dist/index.js`:

```bash
node /path/to/local-memory-mcp/dist/index.js
```

## Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `MEMORY_DIR` | `~/.local-memory` | Global data directory |
| `MEMORY_PROJECT` | auto-detected CWD | Project root override |
| `EMBEDDING_MODEL` | `Xenova/all-MiniLM-L6-v2` | HuggingFace model for embeddings |

## Configuration

Tuning knobs are in `src/utils/config.ts`:

| Parameter | Default | Description |
|-----------|---------|-------------|
| `deduplicationThreshold` | 0.92 | Cosine similarity above which a new memory updates the existing one |
| `consolidationThreshold` | 0.85 | Similarity above which two memories are merged during consolidation |
| `decayRate` | 0.995 | Daily importance multiplier (0.995^30 ≈ 0.86, so ~14% decay/month) |
| `minImportanceBeforePrune` | 0.05 | Memories below this with <2 accesses get pruned |

## Development

```bash
npm run dev          # watch mode
npm test             # run tests (downloads model on first run, ~60s)
npm run build        # production build
```

## Project structure

```
src/
├── index.ts                # Entry point — stdio transport
├── server.ts               # MCP tool definitions
├── engine/
│   ├── memory-engine.ts    # Orchestrator — store, recall, forget, consolidate
│   ├── retrieval.ts        # Hybrid scoring (vector + FTS + recency + importance)
│   ├── embeddings.ts       # Local embedding via Transformers.js
│   ├── consolidation.ts    # Decay, merge, prune lifecycle
│   └── graph.ts            # Entity relationship engine
├── storage/
│   ├── database.ts         # SQLite + sqlite-vec + FTS5 initialization
│   ├── schema.ts           # Drizzle ORM schema
│   ├── memory-store.ts     # CRUD for memories table
│   ├── vector-store.ts     # sqlite-vec operations
│   ├── fts-store.ts        # FTS5 search with query sanitization
│   └── graph-store.ts      # Entity + relation tables, BFS traversal
└── utils/
    ├── config.ts           # Environment + defaults
    ├── scoring.ts          # Recency decay, hybrid scoring, cosine similarity
    └── id.ts               # nanoid generation
```

## Tech stack

- **TypeScript** + **tsup** (ESM, Node 22)
- **better-sqlite3** + **Drizzle ORM** for structured storage
- **sqlite-vec** for vector similarity search
- **SQLite FTS5** for full-text search
- **@huggingface/transformers** for local embeddings (ONNX)
- **@modelcontextprotocol/sdk** for the MCP server
- **Vitest** for testing

## License

MIT