Long-term memory MCP server for LLMs — hybrid search in a single SQLite file
Project description
rekal
Long-term memory for LLMs. An MCP server backed by a single SQLite file.
pip install rekal
The problem
LLMs forget everything between sessions. You tell it you prefer Ruff, that you deploy with tags, that the auth service lives in services/auth. Next conversation, blank slate.
rekal fixes this. It stores memories in SQLite with hybrid search (keywords + vectors + recency) so your LLM can recall things you've told it before. One file, no cloud, no API keys.
Quick start
Add rekal to your MCP client config (Claude Desktop, Cursor, Claude Code, etc.):
{
"mcpServers": {
"rekal": {
"command": "rekal"
}
}
}
On first run, rekal creates ~/.rekal/memory.db. That single file holds everything. Copy it to back up, drop it to start fresh.
Requires Python 3.14+.
How it works
Your LLM stores things worth remembering:
User: "I prefer Ruff over Black for formatting"
LLM: → memory_store("User prefers Ruff over Black", type="preference")
Weeks later, different conversation:
User: "Set up linting for my new project"
LLM: → memory_search("formatting linting preferences")
← "User prefers Ruff over Black" (score: 0.92)
When facts change, old versions stay linked:
LLM: → memory_supersede(old_id="mem_abc", new_content="API moved from v2 to v3")
When things contradict each other:
LLM: → memory_conflicts(project="backend")
← "use PostgreSQL for everything" contradicts "migrate analytics to ClickHouse"
Search
Three signals, blended into one score:
score = 0.4 · BM25(keyword match)
+ 0.4 · cosine(semantic similarity)
+ 0.2 · exp(-t/half_life)
"deploy auth" and "shipping the login system to pre-prod" both find the same memory. Recent stuff ranks higher, but old memories still show up when relevant.
Embeddings run locally via fastembed. Nothing leaves your machine.
Claude Code skills
If you use Claude Code, rekal ships as a plugin with two skills:
| Skill | Trigger | What it does |
|---|---|---|
rekal-save |
Auto on session end, or /rekal-save |
Reviews the conversation, deduplicates against existing memories, stores what's worth keeping |
rekal-hygiene |
/rekal-hygiene |
Finds conflicts, duplicates, and stale data. Proposes fixes for your approval, never deletes on its own |
Install in Claude Code:
/plugin marketplace add janbjorge/rekal
/plugin install rekal-skills@rekal
Requires rekal to be running as an MCP server (see Quick start).
Tools
16 tools over MCP:
Core
| Tool | Description |
|---|---|
memory_store |
Store a memory with type, project, tags, and conversation scope |
memory_search |
Hybrid search: BM25 + vector + recency in one query |
memory_update |
Update content, tags, or type (re-embeds automatically) |
memory_delete |
Delete a memory by ID |
Smart write
| Tool | Description |
|---|---|
memory_supersede |
Replace a memory while keeping the old one as history |
memory_link |
Link memories: supersedes, contradicts, related_to |
memory_build_context |
Relevant memories + conflicts + timeline for a query, in one call |
Introspection
| Tool | Description |
|---|---|
memory_similar |
Find memories similar to a given one |
memory_topics |
Topic summary grouped by type |
memory_timeline |
Chronological view with optional date range filters |
memory_related |
All links to and from a memory |
memory_health |
Database stats: counts by type, project, date range |
memory_conflicts |
Find memories that contradict each other |
Conversations
| Tool | Description |
|---|---|
conversation_start |
Start a conversation, optionally linked to a previous one |
conversation_tree |
Get the full conversation DAG |
conversation_threads |
List recent conversations with memory counts |
conversation_stale |
Find inactive conversations |
Memory types
| Type | For | Example |
|---|---|---|
fact |
Things that are true | "The API rate limit is 1000 req/min" |
preference |
How you like things | "Prefers dataclasses over hand-written __init__" |
procedure |
Steps to do something | "Deploy: git tag vX.Y.Z && git push --tags" |
context |
Current state | "Currently rewriting the payment service" |
episode |
Things that happened | "Debugged the OOM, root cause was unbounded cache" |
Architecture
One SQLite file, four components:
rekal
│
SQLite ──┬── FTS5 index ──── keyword relevance (BM25)
├── sqlite-vec ──── semantic similarity (384d vectors)
├── recency ─────── exponential decay (30-day half-life)
└── memory links ── supersedes / contradicts / related_to
Conversations form a DAG (follow-ups, branches, merges), navigable like a git log.
CLI
rekal serve # Run as MCP server (default)
rekal health # Database health report
rekal export # Export all memories as JSON
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rekal-1.3.0.tar.gz.
File metadata
- Download URL: rekal-1.3.0.tar.gz
- Upload date:
- Size: 138.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
405aa5bdb9fc014a14488bbf9a9ecfe94d1cc74c958beeda48b202f0d74addac
|
|
| MD5 |
c158ba2436f33450db928e6241010a25
|
|
| BLAKE2b-256 |
6e2d3b5e3897869df91b5b97f2a58891fd939684ce12d79494c33ae0f825dec2
|
Provenance
The following attestation bundles were made for rekal-1.3.0.tar.gz:
Publisher:
release.yml on janbjorge/rekal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rekal-1.3.0.tar.gz -
Subject digest:
405aa5bdb9fc014a14488bbf9a9ecfe94d1cc74c958beeda48b202f0d74addac - Sigstore transparency entry: 1282991642
- Sigstore integration time:
-
Permalink:
janbjorge/rekal@a72774b65b813017e204c7d2a5467b22d4c3a18d -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/janbjorge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a72774b65b813017e204c7d2a5467b22d4c3a18d -
Trigger Event:
push
-
Statement type:
File details
Details for the file rekal-1.3.0-py3-none-any.whl.
File metadata
- Download URL: rekal-1.3.0-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d247305a8a81aa431e50b49a69b681f3d3f6d3633eaf9f3bc218095539a3f1b1
|
|
| MD5 |
d085088a2d15a8824a870cc12ca95159
|
|
| BLAKE2b-256 |
ef4bd083f557fe78f25578e9f6cae75ed9b71cb68e4ee72f65067a06f6fd9e6f
|
Provenance
The following attestation bundles were made for rekal-1.3.0-py3-none-any.whl:
Publisher:
release.yml on janbjorge/rekal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rekal-1.3.0-py3-none-any.whl -
Subject digest:
d247305a8a81aa431e50b49a69b681f3d3f6d3633eaf9f3bc218095539a3f1b1 - Sigstore transparency entry: 1282991648
- Sigstore integration time:
-
Permalink:
janbjorge/rekal@a72774b65b813017e204c7d2a5467b22d4c3a18d -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/janbjorge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a72774b65b813017e204c7d2a5467b22d4c3a18d -
Trigger Event:
push
-
Statement type: