Skip to main content
Glama
README.md
# 🧠 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, …).

[![MCP Compatible](https://img.shields.io/badge/MCP-2024--11--05-blue)](https://modelcontextprotocol.io)
[![License: MIT](https://img.shields.io/badge/License-MIT-green)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/Python-3.10+-blue)](https://www.python.org)
[![Zero Dependencies](https://img.shields.io/badge/dependencies-0-success)](#zero-dependencies)
[![Stars](https://img.shields.io/github/stars/eddyflores100-lang/recall-mcp)](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

A3.7/5.0

Scored across 8 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues