The open, self-hostable memory layer for AI agents. MCP-native, local-first, research-grade.
Project description
Memry
The open, self-hostable memory layer for AI agents - memry.tech
pip install memry
memry mcp # your agent now has long-term memory
Memry gives any MCP-capable agent - Claude Code, Claude Desktop, Cursor, Windsurf, Codex - durable long-term memory. It distills conversations into discrete facts, reconciles each new fact against what it already knows, and serves the result back as token-budgeted context. All state is a single SQLite file on your machine: no vector database, no queue, no cloud account, and it works with zero API keys.
Why Memry
It runs anywhere, with nothing. The default install needs no services and no keys:
storage is one SQLite file, retrieval falls back to FTS5 BM25 plus deterministic hash
embeddings, and writes are stored verbatim. Set ANTHROPIC_API_KEY or OPENAI_API_KEY
and the same pipeline upgrades itself to LLM extraction and real embeddings. Local-first
is the default, not a demo mode.
It remembers the way you would want it to. New facts are reconciled against existing
ones: duplicates are skipped, refinements update in place, and contradictions supersede
the old memory instead of deleting it. Memories are bi-temporal (valid_from /
invalid_at / superseded_by), so "moved to Amsterdam" does not erase "lived in
Berlin" - it dates it. Importance decays with a half-life, and a sweep retires stale
trivia, again without destroying anything.
Nothing is a black box. Raw episodes are stored immutably before anything is derived from them, every memory links back to its source episodes, every mutation is an inspectable event, and every search hit carries its score signals (BM25, vector, recency, importance). When a memory looks wrong, you can trace where it came from, or re-run a better extraction pipeline over the original episodes.
Entities are disambiguated, not name-matched. Mentions become first-class entities, and a shared name is never enough to merge two of them: unclear cases stay separate ("three Jonases") with a merge proposal you confirm or reject once the evidence is in.
It scales when needed and stays simple when not. Optional extras add a usearch HNSW
index for larger stores (memry[ann]) and a PostgreSQL + pgvector backend for
multi-writer deployments (memry[postgres]). Per-tenant API keys with strict isolation
(MEMRY_TENANTS) let one server serve several teams. The default remains a zero-ops
single file.
You can measure it. A built-in eval harness scores retrieval (recall@k, MRR, latency percentiles) deterministically and offline, and the pluggable backend interface includes a Mem0 adapter so you can benchmark against it under identical conditions.
Quickstart
As an MCP server (any agent)
// Claude Desktop / Cursor / Windsurf config
{
"mcpServers": {
"memry": {
"command": "memry",
"args": ["mcp"],
"env": { "ANTHROPIC_API_KEY": "sk-ant-..." } // optional but recommended
}
}
}
# Claude Code
claude mcp add memry -- memry mcp
The server exposes save_memories, search_memories, get_memory_context,
list_memories, update_memory, delete_memory, memory_history, and memory_stats.
As a Python library
from memry import MemoryStore
store = MemoryStore()
# write: extraction + reconciliation (or infer=False to store verbatim)
store.add(
[{"role": "user", "content": "I'm Ada, a data engineer in Berlin. I prefer uv over pip."}],
user_id="ada",
)
# read: hybrid search with explainable scores
for hit in store.search("what tooling does the user prefer?", user_id="ada"):
print(hit.score, hit.memory.content, hit.signals)
# or a ready-to-inject, token-budgeted context block
ctx = store.reconstruct_context("help me set up a new project", user_id="ada", token_budget=1200)
print(ctx.text)
As a self-hosted server (REST + dashboard + MCP)
memry serve --host 0.0.0.0 --port 8787
# dashboard: http://localhost:8787/
# REST API: http://localhost:8787/api/v1/...
# MCP (HTTP): http://localhost:8787/mcp
With Docker: docker compose up -d (see docker-compose.yml).
Or on a fresh Ubuntu/Debian VPS, one command installs Docker, Memry, and Caddy with automatic HTTPS (full guide):
curl -fsSL https://raw.githubusercontent.com/cosmin-novac/memry/main/deploy/install.sh \
| MEMRY_DOMAIN=memory.example.com bash
Set MEMRY_API_KEY to require Authorization: Bearer <key> on the API. More in
docs/self-hosting.md. To plug a hosted Memry into
claude.ai as a custom connector, see
docs/connect-claude-ai.md.
From the CLI
memry add "I moved to Amsterdam and joined ASML" -u ada
memry search "where does ada work" -u ada
memry context "plan a commute" -u ada
memry history <memory_id> # full audit trail
memry sweep # decay: soft-forget stale memories
memry eval --dataset evals/datasets/synthetic_v1.jsonl
How it works
flowchart LR
A[conversation] --> E["episodes (immutable log)"]
A --> X[extraction]
X --> R{reconcile}
R -->|new| ADD[add]
R -->|refines| UPD[update in place]
R -->|contradicts| SUP[supersede old]
R -->|duplicate| SKIP[skip]
ADD --> M[(memories)]
UPD --> M
SUP --> M
Q[agent query] --> H[hybrid retrieval]
M --> H
H --> C[token-budgeted context]
- Episodes first. Every message is stored verbatim before anything is derived from it. Memories are an index; episodes are the source of truth.
- Extraction. An LLM distills discrete, self-contained facts with a type (semantic / episodic / procedural), importance, categories, and entities. Without an LLM key, messages are stored verbatim and everything still works.
- Reconciliation. Each fact is compared to its most similar existing memories: duplicates are skipped, refinements rewrite in place, contradictions invalidate the old memory and link it to its successor.
- Retrieval. BM25 and cosine similarity fused with reciprocal-rank fusion, then boosted by recency and importance. Keyword-only when no embedder is configured.
- Forgetting. Effective importance decays over time;
memry sweepinvalidates memories that fall below threshold. Category filters (memry search -c diet) narrow any query.
Configuration
Everything works with defaults. Override via env vars, ~/.memry/config.json, or Config(...):
| Env var | Default | Notes |
|---|---|---|
MEMRY_DB_PATH |
~/.memry/memry.db |
single SQLite file |
MEMRY_BACKEND |
local |
local | mem0 (needs memry[mem0]) |
MEMRY_DEFAULT_USER |
default |
user scope when the agent doesn't pass one |
MEMRY_LLM_PROVIDER |
auto | anthropic | openai | ollama | none - auto-detected from ANTHROPIC_API_KEY / OPENAI_API_KEY |
MEMRY_LLM_MODEL |
per provider | claude-opus-4-8 / gpt-5-mini / llama3.1 (use claude-haiku-4-5 for cheaper extraction) |
MEMRY_EMBEDDING_PROVIDER |
auto | openai | ollama | voyage | hash | none |
MEMRY_API_KEY |
- | bearer token for the REST/MCP HTTP server |
Anthropic extraction requires the optional SDK: pip install "memry[anthropic]".
Evaluation
memry eval --dataset evals/datasets/synthetic_v1.jsonl -k 5
The harness ingests each case through the full write path, then scores retrieval (recall@k, MRR, latency p50/p95). It is deterministic and offline, so it runs in CI. LoCoMo and LongMemEval can be formatted into the same JSONL schema to compare providers, configs, and backends (including the Mem0 adapter) under identical conditions. The landscape survey behind the design is in docs/research/competitive-analysis.md.
Project layout
src/memry/
models.py # Episode / Memory / MemoryEvent (bi-temporal, provenance)
config.py # env + file config, provider auto-detection
store.py # MemoryStore - the public API
retrieval.py # hybrid search: RRF + recency + importance
backends/ # storage interface, local SQLite engine, Mem0 adapter
intelligence/ # extraction, reconciliation, decay, context building
providers/ # LLMs (Anthropic/OpenAI/Ollama) & embeddings (+hash fallback)
mcp_server.py # MCP tools (stdio + streamable HTTP)
rest.py # REST API + dashboard + /mcp mount
evals/ # retrieval eval harness
Development
pip install -e ".[dev]"
pytest
License
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 memry-0.2.4.tar.gz.
File metadata
- Download URL: memry-0.2.4.tar.gz
- Upload date:
- Size: 61.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af7fe756de940bc7a6f78e02bd1e902ad651c5ae982cc1114d06bad45f7453ad
|
|
| MD5 |
f05de580af2d74279bc3fd40b253d3db
|
|
| BLAKE2b-256 |
3c4cc23cd378651b6fcfaf6e6fb70924ad6e7a031d3376a7c39e52ff256f18be
|
Provenance
The following attestation bundles were made for memry-0.2.4.tar.gz:
Publisher:
publish.yml on cosmin-novac/memry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
memry-0.2.4.tar.gz -
Subject digest:
af7fe756de940bc7a6f78e02bd1e902ad651c5ae982cc1114d06bad45f7453ad - Sigstore transparency entry: 2211923829
- Sigstore integration time:
-
Permalink:
cosmin-novac/memry@2a7343844e795339aa56bad7c9d22010afe4c045 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/cosmin-novac
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2a7343844e795339aa56bad7c9d22010afe4c045 -
Trigger Event:
push
-
Statement type:
File details
Details for the file memry-0.2.4-py3-none-any.whl.
File metadata
- Download URL: memry-0.2.4-py3-none-any.whl
- Upload date:
- Size: 73.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f0f5763d90397a1aa15d4ce795107becb22f481d4985c996f24d7507f1c7188
|
|
| MD5 |
39db3c6d144773ab4b0817767d137067
|
|
| BLAKE2b-256 |
5cb40ee23f08b5506dc3cfb367ba3839f24fb49504887a6bd08463d86eb763ae
|
Provenance
The following attestation bundles were made for memry-0.2.4-py3-none-any.whl:
Publisher:
publish.yml on cosmin-novac/memry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
memry-0.2.4-py3-none-any.whl -
Subject digest:
5f0f5763d90397a1aa15d4ce795107becb22f481d4985c996f24d7507f1c7188 - Sigstore transparency entry: 2211923862
- Sigstore integration time:
-
Permalink:
cosmin-novac/memry@2a7343844e795339aa56bad7c9d22010afe4c045 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/cosmin-novac
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2a7343844e795339aa56bad7c9d22010afe4c045 -
Trigger Event:
push
-
Statement type: