Skip to main content
Glama

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.

Related MCP server: Facthouse

Install

npm install
npm run build

Requires Node.js >= 22.5 (uses node:sqlite).

Run

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:

{
  "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

Related MCP Connectors

Related MCP Servers