Skip to main content
Glama

ctrl-memory

Lightweight, local-first MCP memory server for LLM agents.

Store, search, and retrieve agent memories with zero external dependencies. Plug it into Hermes, Claude Code, Cursor, or any MCP-compatible client.

pip install ctrl-memory
ctrl-memory-mcp

✨ Features

  • Zero-dependency core — pure Python, no databases, no external services

  • Two backends — JSON files (MVP, zero deps) or SQLite (production, WAL mode)

  • Semantic search — optional sentence-transformers for cosine similarity ranking

  • Hybrid retrieval — keyword recall + vector re-ranking for best precision/recall

  • Fuzzy matching — Damerau-Levenshtein typo tolerance built in

  • Scope filtering — tag-based domain isolation

  • Supersession awareness — automatically filters outdated/obsolete facts

  • Hermes plugin — auto-prefetch context, auto-capture conversation turns

  • MCP stdio server — plug into any MCP-compatible client

  • User isolation — each user's memory is fully separated

  • Cross-session persistence — memories survive between conversations


Related MCP server: tartarus-mcp

🚀 Quick start

curl -fsSL https://raw.githubusercontent.com/ctrlProgrammer/ctrl-memory-system/main/install.sh | bash

This creates an isolated virtual environment in ~/.local/share/ctrl-memory/, installs ctrl-memory with semantic search, and makes the ctrl-memory-mcp command available globally. No pip install --user or sudo needed.

After install, open a new terminal (or exec $SHELL) and run:

ctrl-memory-mcp

Manual install with pip

# Core (zero deps)
pip install ctrl-memory

# With semantic search
pip install "ctrl-memory[embeddings]"

⚠️ If your system restricts global pip installs (PEP 668), use the one-liner above or install inside a virtual environment:

python3 -m venv .venv
source .venv/bin/activate
pip install "ctrl-memory[embeddings]"

pipx (alternative)

pipx install "ctrl-memory[embeddings]"

Run the MCP server

ctrl-memory-mcp

The server listens on stdin/stdout (MCP stdio transport). It starts when a client connects and exits when the client disconnects — no background daemon.

Check if it's working

In one terminal, start the server:

ctrl-memory-mcp

In another terminal, run:

# 1. Initialize the session
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}' | ctrl-memory-mcp

# 2. Add a fact
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"add_memory","arguments":{"user_id":"alice","content":"Alice prefers Fastify over Express"}}}' | ctrl-memory-mcp

# 3. Search
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search_memory","arguments":{"user_id":"alice","query":"web framework"}}}' | ctrl-memory-mcp

💡 For Hermes users: the plugin activates automatically when you start a new conversation. No need to run ctrl-memory-mcp separately. Memory is stored per-user across sessions.


🔄 Updating

# If you used the one-liner installer — just re-run it (upgrades in-place):
curl -fsSL https://raw.githubusercontent.com/ctrlProgrammer/ctrl-memory-system/main/install.sh | bash

# If you used pip:
pip install --upgrade "ctrl-memory[embeddings]"

# If you used pipx:
pipx upgrade ctrl-memory

📦 Backends

JSON backend (default)

  • Zero dependencies

  • One file per user: ~/.ctrl-memory/<user_id>.json

  • Auto-increment IDs, append-only writes

  • Best for: MVP, personal use, <1000 facts

SQLite backend

  • Single .db file with WAL mode

  • Indexed queries, ACID transactions

  • Embedding storage for semantic search

  • Best for: production, multi-user, >1000 facts

ctrl-memory-mcp --backend sqlite

When sentence-transformers is installed, ctrl-memory automatically enables:

  • Auto-embedding — facts are vectorized at write time (384-dim all-MiniLM-L6-v2)

  • Hybrid search — keyword candidates → cosine similarity re-ranking → sorted by relevance

  • Score filtering — configurable min_score threshold to filter weak matches

pip install "ctrl-memory[embeddings]"

No flags needed — detection is automatic.


🔌 Hermes Agent plugin

ctrl-memory ships with a native Hermes Agent provider.

Install

# Copy the plugin
cp -r hermes_provider ~/.hermes/hermes-agent/plugins/memory/ctrl-memory/

Configure

Add to ~/.hermes/config.yaml:

memory:
  provider: ctrl-memory
  config:
    backend: sqlite       # or json (default)
    db_path: ~/.hermes/memory.db

The plugin provides:

  • Automatic prefetch — relevant context injected before every LLM turn

  • Turn capture — facts extracted from conversations and stored

  • 4 toolsadd_memory, search_memory, delete_memory, memory_status


🔧 MCP tools

Tool

Description

add_memory

Store a new fact with optional metadata tags

search_memory

Hybrid keyword + semantic search

get_fact

Retrieve a specific fact by ID

list_facts

List all facts for a user with pagination

update_fact

Edit an existing fact (re-embeds if semantic enabled)

delete_fact

Remove a fact (cleans up embedding)

count_facts

Get total fact count for a user

search_memory_semantic

Pure cosine similarity search (uses embeddings)


🏗️ Architecture

┌─────────────────────────────────────┐
│          MCP Client                  │
│  (Hermes, Claude Code, Cursor...)   │
└──────────────┬──────────────────────┘
               │ stdio JSON-RPC
┌──────────────▼──────────────────────┐
│        mcp_server.py                │
│     MCP stdio transport layer       │
└──────────────┬──────────────────────┘
               │
┌──────────────▼──────────────────────┐
│       memory_backend.py             │
│  ┌─────────┐  ┌──────────┐         │
│  │ JSON    │  │ SQLite   │         │
│  │ Store   │  │ Store    │         │
│  └─────────┘  └────┬─────┘         │
│                    │                │
│  ┌─────────────────▼──────────┐     │
│  │    EmbeddingEngine          │     │
│  │  (optional, auto-detect)   │     │
│  └────────────────────────────┘     │
└─────────────────────────────────────┘

Search flow

Query
  │
  ▼
1. Keyword search (token-OR with stop-word filter)
  │
  ├── No results? → Fuzzy fallback (Damerau-Levenshtein)
  │
  ▼
2. Cosine similarity re-ranking (if embeddings available)
  │
  ▼
3. Scope filtering (if tags match)
  │
  ▼
4. Supersession filtering (remove obsolete facts)
  │
  ▼
5. Sort by score, return top N

📊 Benchmark results

Tested against PrecisionMemBench — 77 retrieval scenarios across alias resolution, fuzzy matching, scope isolation, noise resistance, supersession chains, and budget constraints.

Score: 54 / 77 ✅ (70% passing)

Phase

Passing

Δ

Base keyword search

9 / 77

Hybrid keyword + cosine

42 / 77

+33

+ Damerau-Levenshtein fuzzy

43 / 77

+1

+ Scope filtering

49 / 77

+6

+ Supersession filtering

54 / 77

+5

What passes (54 tests)

Category

Tests

Alias resolution

k8s → Kubernetes, GHA → GitHub Actions, ReactJS → React, POV → point of view, DLQ → dead letter queue, base class → composition-inheritance, exceptions → error handling, 2-word shingles

Exact match

repository-layer, canonical name, long query (400+ chars)

Scope filtering

Redis-in-writing returns character not datastore, code-scope doesn't leak writing, cross-scope blocked, user-edited respects scope, scope bleed protection

Supersession

SQLAlchemy superseded by MongoDB hidden, TSLint→ESLint→Biome chain resolves to terminal, resolved_at beliefs excluded, pinned+resolved excluded from questions

Fuzzy matching

All-caps case-insensitive (REACTJS), typo prefix guard, scope-aware fuzzy filtering

Messy queries

Filler-heavy extraction, compound surfaces 2 beliefs, negation still surfaces topic, all-caps case insensitive

Budget/limits

Ceiling eviction, zero graceful, one pinned wins, recency tiebreak

Edge cases

Cold start, empty query, whitespace query, short query passthrough, short query score clears, empty alias content path

User isolation

Other-user beliefs never leak

Universal scope

Persona prelude, explicit query with no relevant, zero-reinforcement fresh belief surfaces

What fails (23 tests) — root causes

Cause

Tests

Why

Token bleeding

8

Generic query tokens match too many facts (e.g. "kube" finds multiple)

Relation expansion

4

"auth depends on redis" — not yet implemented

Cap stress

3

6+ entities in single query needs NLP extraction

Ranking weights

2

canonical_name should outrank content match

Multi-scope Redis

2

Redis in both code+writing scopes needs per-scope dedup

Fuzzy edge cases

2

k9s vs k8s prefix guard, single-edit with token bleed

Other

2

why_it_matters not indexed, type isolation routing

Comparison with other providers

Provider

Passing

Precision

Dependencies

tenure (reference)

77 / 77

1.00

MongoDB Atlas Search (BM25, shingles, fuzzy)

ctrl-memory

54 / 77

~0.70

Zero external deps

okf

~30 / 77

~0.47

PostgreSQL

supermemory

~21 / 77

~0.22

Supabase + API

yourmemory

~21 / 77

~0.17

MongoDB

mem0

~9 / 77

~0.06

Qdrant + API

Second place among all tested providers. ctrl-memory achieves this with zero external dependencies — no databases, no APIs, no cloud services.


🧪 Development

# Clone
git clone https://github.com/ctrl-alt-dev/ctrl-memory
cd ctrl-memory

# Setup
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[embeddings]"

# Test
python3 -m unittest discover tests -v

# Run benchmark
cd /tmp
git clone https://github.com/tenurehq/precisionMemBench
cd precisionMemBench
MEMORY_PROVIDER=ctrl-memory CTRL_MEMORY_URL=http://localhost:8000 \
  RESEED=true npx ava src/retrieval.external.eval.test.ts --timeout 10m

Test suite

File

Tests

What it covers

test_memory_backend.py

23

JSON store CRUD, search, user isolation

test_sqlite_store.py

25

SQLite store CRUD, search, embeddings

test_mcp_server.py

24

MCP protocol, JSON-RPC, tool dispatch

test_embeddings.py

24

Embedding engine, cosine similarity

test_hermes_provider.py

24

Plugin lifecycle, tools, prefetch

116 tests total (105 run, 11 skip without sentence-transformers).


📄 License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ctrlProgrammer/ctrl-memory-system'

If you have feedback or need assistance with the MCP directory API, please join our Discord server