recall-mcp
# π§ Recall MCP β Long-term Memory for AI Agents
> **Your agent finally remembers what it did yesterday.** Cross-session, persistent, semantic memory for any MCP-compatible agent (Claude Desktop, Cursor, Cline, Continue, β¦).
[](https://modelcontextprotocol.io)
[](LICENSE)
[](https://www.python.org)
[](#zero-dependencies)
[](https://github.com/eddyflores100-lang/recall-mcp/stargazers)
---
## π― The Problem (worth 100,000+ GitHub stars)
Every time you start a new chat with Claude, Cursor, or any AI agent, **it starts from zero**. It doesn't remember:
- The bug you fixed yesterday
- The architecture decisions from last week
- Your codebase conventions (tabs vs spaces, framework version, test runner)
- Your preferences ("always use TypeScript", "never commit directly to main")
- The project's gotchas ("the auth middleware is broken, bypass it for now")
This means:
- π **You repeat yourself** β explain the same context every session
- π **Slower iteration** β agent re-discovers what it already knew
- π **Worse quality** β no accumulated knowledge
- πΈ **Wasted tokens** β re-reading the same files, re-asking the same questions
## β¨ The Solution
Recall MCP gives your agent **persistent, searchable memory across sessions**.
```python
# Yesterday, in chat session A:
agent.call("remember", content="User prefers tabs over spaces. Project uses Next.js 14 with App Router.")
agent.call("remember", content="Auth middleware has a known bug with session expiry; bypass for now.")
# Today, in chat session B (fresh context):
agent.call("recall", query="code style preferences")
# β [{"content": "User prefers tabs over spaces. Project uses Next.js 14 with App Router.",
# "score": 0.95, "tags": ["coding-style"], "project": "webapp", ...}]
agent.call("recall", query="known bugs auth")
# β [{"content": "Auth middleware has a known bug with session expiry; bypass for now.",
# "score": 0.87, ...}]
```
### Why it's better than context-pruning approaches
| Approach | When it works | When it fails |
|----------|----------------|----------------|
| **Context pruning** (e.g. the other skill I shipped) | Compresses tool output *within a session* | Useless across sessions β the agent still forgets everything when you start a new chat |
| **Recall MCP** (this project) | Works *across* sessions β yesterday's context is searchable today | Doesn't help if your conversation is one-shot |
They're complementary: use a pruner to fit more useful context in the current session, and use Recall so the next session doesn't have to start from scratch.
## π Quick Start
### 1. Install
**Option A β pip (PyPI, recommended):**
```bash
pip install recall-mcp
# After install, the `recall-mcp` command is available:
recall-mcp # starts the MCP server on stdio
```
**Option B β uvx (no install, run directly):**
```bash
uvx recall-mcp
```
**Option C β single-file (zero install):**
```bash
curl -sSL https://github.com/eddyflores100-lang/recall-mcp/raw/main/mcp_recall.py \
-o ~/.local/bin/recall-mcp
chmod +x ~/.local/bin/recall-mcp
```
No `pip install` step, no virtualenv, no API keys β just Python 3.10+ with stdlib.
### 2. Configure with your agent
> **If you installed via pip/uvx:** use `"command": "recall-mcp"` with no args.
> **If you used the single-file download:** use `"command": "python3"` with `"args": ["/path/to/mcp_recall.py"]`.
**Claude Desktop** β edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"recall": {
"command": "recall-mcp"
}
}
}
```
**Cursor** β `.cursor/mcp.json`:
```json
{
"mcpServers": {
"recall": {
"command": "recall-mcp"
}
}
}
```
**Cline / Continue / any MCP client** β same pattern: set `command` to `recall-mcp` (post-install) or `python3` with the script path (single-file mode).
### 3. Start using
Restart your agent and you'll see 8 new tools available. Try:
> *"Remember that I prefer functional React components over class components."*
Then start a brand new chat:
> *"Recall what I told you about React conventions."*
Your agent will pull the memory and continue where you left off.
## π οΈ MCP Tools (8 total)
| Tool | What it does |
|------|--------------|
| `remember` | Store a memory with optional tags / project / importance (0..1). Auto-deduplicates by content hash. |
| `recall` | Semantic-ish search via FTS5 BM25 + recency/importance/access-count boosting. |
| `forget` | Delete a memory by `id` or by FTS content match (deletes all matches). |
| `list_memories` | List with filters: `project`, `tag`, `limit`, `order` (recent / oldest / accessed / important). |
| `summarize_session` | Pass a list of chat messages β automatically extracts memorable facts/preferences/decisions and stores them. |
| `get_stats` | Total count, per-project, per-source, per-tag breakdown, oldest, newest, most-accessed, avg importance, DB size. |
| `export_memories` | Dump memories as JSON (optionally per-project) β perfect for backups or transferring between machines. |
| `import_memories` | Load JSON back in. `on_duplicate` policy: `skip` / `bump` (increment access) / `replace` (overwrite metadata). |
### Tool call examples
```jsonc
// remember
{
"content": "PostgreSQL connection string format: postgres://user:pass@host:5432/db",
"tags": ["database", "postgres"],
"project": "backend",
"importance": 0.8
}
// recall
{
"query": "how to connect to postgres",
"limit": 5,
"project": "backend",
"min_importance": 0.3
}
// summarize_session (great for end-of-session snapshots)
{
"messages": [
{"role": "user", "content": "I always use pnpm, never npm."},
{"role": "assistant", "content": "Noted. I'll use pnpm throughout."},
{"role": "user", "content": "We decided to deploy on Vercel."}
],
"project": "webapp"
}
```
## ποΈ Architecture
```
ββββββββββββββββ stdio (JSON-RPC) ββββββββββββββββββββ
β MCP client β ββββββββββββββββββββββββββΊ β mcp_recall.py β
β (Claude / β β β
β Cursor / β β ββββββββββββββ β
β Cline β¦) β β β MemoryStoreβ β
ββββββββββββββββ β β - rememberβ β
β β - recall β β
β β - forget β β
β β - stats β β
β β ... β β
β ββββββββ¬ββββββ β
β β β
β βΌ β
β ββββββββββββββ β
β β SQLite β β
β β + FTS5 β β
β β (local file)β β
β ββββββββββββββ β
ββββββββββββββββββββ
Default path:
~/.recall/memory.db
```
**Ranking formula** (for `recall` results):
```
score = bm25_rank Γ 1.0
+ recency_decay Γ 0.5 (full weight 90d, then linear fade to 0.25)
+ importance Γ 0.5 (user-set 0..1)
+ min(access_count Γ 0.05, 0.5)
```
This means: a memory that matches the query, was recently stored, marked as important, and accessed often will rank highest. A 6-month-old low-importance memory won't completely vanish, but it won't crowd out fresher results either.
## π Privacy & Security
- **100% local** β every byte lives in `~/.recall/memory.db` on your machine.
- **Zero telemetry** β no external API calls, no analytics, no phone-home.
- **Auto-redacts secrets** before storage. Detected patterns include:
- GitHub tokens (`ghp_β¦`, `gho_β¦`, `ghs_β¦`, fine-grained)
- OpenAI keys (`sk-β¦`), Anthropic keys (`sk-ant-β¦`), Gemini (`AIzaβ¦`)
- AWS access keys (`AKIAβ¦`)
- JWTs (`eyJβ¦`)
- Stripe keys, Slack tokens, Bearer tokens, private keys
- `password=β¦` assignments
- Connection strings with embedded credentials (`postgres://user:pass@β¦`)
- All replaced with `[REDACTED]` before being written to disk.
- **Per-project isolation** β memories from project A don't bleed into project B's `recall` unless you ask for them.
- **Export anytime** β `export_memories` gives you the full database as JSON. Your data is yours.
## π Comparison
| Feature | Recall MCP | mem0 | LangChain Memory | Zep |
|---------|-----------|------|------------------|-----|
| Local-first (no cloud) | β
| β | β
| β |
| Zero external dependencies | β
| β | β | β |
| MCP-native | β
| β | β | β |
| Cross-session | β
| β
| β (per-conversation) | β
|
| Auto-summarize sessions | β
| β | β | β
|
| Smart decay (LRU + recency) | β
| β | β | β |
| Secret redaction built-in | β
| β | β | β |
| Export / import | β
| partial | β | β |
| Free (no paid plan) | β
| $ | β
| $ |
| Setup time | 30 sec | 10 min | 5 min | 10 min |
## βοΈ Configuration (env vars)
| Var | Default | Description |
|-----|---------|-------------|
| `RECALL_MCP_DB` | `~/.recall/memory.db` | Path to SQLite DB file |
| `RECALL_MAX_LENGTH` | `50000` | Max chars per memory (truncates with notice) |
| `RECALL_DECAY_DAYS` | `90` | Days at full weight before decay starts |
| `RECALL_MAX_RESULTS` | `50` | Hard cap on `recall` and `list_memories` limits |
| `RECALL_LOG_LEVEL` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` (stderr only) |
## π§ͺ Testing
```bash
# Option A β full pytest suite (43 tests across 4 files)
git clone https://github.com/eddyflores100-lang/recall-mcp.git
cd recall-mcp
pip install -e ".[dev]"
python -m pytest tests/ -v
# Expected: 43 passed
# Option B β single-file smoke test (no pytest needed, 14 tests)
python test_recall.py
# Expected: === 14 passed, 0 failed ===
```
**CI:** GitHub Actions runs the full suite on Python 3.10β3.13 across Ubuntu, macOS, and Windows on every push and PR.
The test suite covers:
- **Protocol** (9 tests): initialize, ping, notifications/initialized, tools/list, invalid method, invalid tool, malformed JSON, resources/list, prompts/list
- **Memory CRUD** (13 tests): remember, duplicate detection, empty/long content, importance clamping, recall with filters, forget by id/query, access count bumping
- **Secrets** (11 tests): GitHub classic + fine-grained tokens, OpenAI, Anthropic, AWS, JWT, Stripe, connection strings, password assignments, private keys, on-disk verification
- **Session & Export** (10 tests): summarize_session extraction + capping, get_stats, export/import round-trip, invalid input handling, list ordering, tag filters
## πΊοΈ Roadmap
- [ ] Optional vector embeddings (with `OPENAI_API_KEY` or local sentence-transformers) for true semantic search beyond FTS5
- [ ] Multi-agent memory sharing (memory namespaces)
- [ ] Web UI for browsing / searching / editing memories
- [ ] Backup to S3 / Dropbox / gists
- [ ] MCP resources endpoint (expose memories as browsable resources)
- [ ] Auto-tagging (extract dates, URLs, file paths from content)
- [ ] CLI tool (`recall search "query"`, `recall add "text"`)
- [ ] Plugin SDK for custom extractors in `summarize_session`
## π€ Why I built this
I ship MCP servers for a living (see also: [`context-pruner-mcp`](https://github.com/eddyflores100-lang/context-pruner-mcp)). After using agents for months, the single biggest quality boost came not from better models or bigger context windows β it came from giving the agent a way to **not forget**. Context pruning squeezes more juice out of the current session; long-term memory means the next session starts ahead instead of from zero.
If this saves you 10 minutes of re-explaining per session, that's roughly 40 hours a year for a daily user. Open source it so everyone gets those hours back.
## π License
MIT β see [LICENSE](LICENSE).
## β Star History
If this saved you time, please β the repo β it helps others discover it.
---
**Author:** Eddy Flores ([`eddyflores100-lang`](https://github.com/eddyflores100-lang))
**Issues / feature requests:** [GitHub Issues](https://github.com/eddyflores100-lang/recall-mcp/issues)
TDQS
Scored across 8 tools
Each tool has a distinct purpose: remember stores, recall searches, forget deletes, list_memories enumerates, summarize_session derives memories from conversation, get_stats aggregates statistics, and export/import handle data transfer. No two tools overlap in their core function, making misselection unlikely.
Tool names follow a consistent imperative verb pattern: either bare verbs (remember, recall, forget) or verb_noun pairs (list_memories, summarize_session, get_stats, export_memories, import_memories). The convention is uniform and predictable, with no mixed casing or inconsistent verb styles.
Eight tools is a well-scoped set for a memory management server. Each tool addresses a core need (store, search, delete, list, auto-summarize, stats, export, import) without redundancy or bloat, fitting comfortably in the ideal 3β15 range.
The tool surface covers the full memory lifecycle: creating (remember, summarize_session, import_memories), reading (recall, list_memories, get_stats, export_memories), updating (import_memories with replace/bump), and deleting (forget). No critical operations are missing for managing persisted memories.