35 MCP Tools for Persistent AI Memory
Overview
Section titled “Overview”toon-memory provides 35 MCP tools and 4 MCP resources for managing persistent memory:
| Tool | Description |
|---|---|
memory_remember |
Save a decision, pattern, bug, knowledge, or warning (negative “do NOT do this” memory, recalled with a boost) (optional TTL, auto-tag inference, links, auto quality score, merge-dedup, confidence, optional importance: critical/high/medium/low) |
memory_recall |
Search memory (use BEFORE reading files, filters expired TTL). mode: "graph" expands a relationship-aware subgraph for higher precision. Ranking uses RRF fusion (BM25×3 + graph centrality, adaptive k); pass rrf: false for the legacy linear score. sessionBias boosts entries from the current git branch. pathScope scopes results to a file path (supports globMatch). budget: "tiny" (top 3), "normal" (top 10), or "deep" (top 20). as_of re-includes entries superseded after a point-in-time date. explain: true appends a per-entry reason line (why it was retrieved). budget_tokens caps the output by estimated token count (0 = no limit). mode: "index" lists one line per entry (key, id, category, date, relevance %) with no content; ids bulk-fetches entries by id/key, order preserved |
memory_forget |
Lifecycle ops by key or id: action: "soft" (default) marks obsolete, "hard" permanently removes, "restore" brings back to active, "supersede" retires it with a superseded_by link to new_key |
memory_stats |
View memory state (including TTL stats, quality distribution, cold memories below quality/access thresholds, and hit-rate/duplicate/dead metrics: % recalled at least once, % exact-content duplicates, % obsolete entries) |
memory_summary |
Save/retrieve file summaries |
memory_archive |
Archive old entries (>30 days) and expired TTL entries |
memory_diff |
Show changes since a date (24h, 7d, or exact date) |
memory_suggest |
Find related entries for a given context |
memory_captured |
List activity auto-captured by hooks (opt-in) or clear the log |
memory_checkpoint |
Session checkpoint: creates a snapshot of current memory state with 7d TTL. Useful for rollback reference during long sessions |
memory_consolidate |
Cleanup ops, deterministic (no LLM): mode: "identical" (default) de-duplicates entries with identical content, "similar" merges near-duplicates (Jaccard >50%), "low-quality" batch-compresses low-quality entries (minQuality, dryRun), "versions" detects entries describing the same subject at different library versions and retires the older ones in favor of the newest |
memory_encrypt |
Enable AES-256-GCM encryption |
memory_decrypt |
Disable encryption |
memory_backup |
Create timestamped backup of memory file (auto-prunes to 10 most recent) |
memory_secret |
Encrypted secrets vault (secrets.toon, AES-256-GCM): store/get/list/forget. Keeps data.toon readable while sensitive values stay encrypted at rest. Requires TOON_MEMORY_KEY |
memory_export_global |
Write current project memory to the global file (~/.toon-memory/memory/global.toon). One-shot share of cross-project conventions |
memory_import_global |
Merge cross-project conventions from the global file into this project (one-shot, deterministic, offline). merge: false replaces instead |
memory_export_gist |
Export memory to a private GitHub Gist for cloud sync. Requires GITHUB_TOKEN env var |
memory_import_gist |
Import memory from a GitHub Gist. Merges entries (keeps newer dates, combines tags) |
memory_merge_sessions |
Merge observations from multiple sessions/branches into a consolidated view. Deduplicates and suggests entries to promote |
memory_compress |
LLM-powered compression: select entries to compress into one concise entry (two-step: the tool provides context, you provide the summary) |
memory_sessions |
Show active agent sessions, branches, and soft file conflicts for parallel-session coordination |
context_brief |
One-call context briefing: memory + sessions + health in compact markdown. Use instead of 5-6 separate memory_* calls. Zero LLM |
context_generate |
Full project briefing: combines project structure, git state, memory entries, and active sessions in one call. Replaces 5-6 manual tool calls |
context_diff |
Incremental briefing: git commits + modified files + new/updated memory + active sessions since last session |
context_focus |
Hyper-focused briefing: only relevant memory + related source files + callers + test files for a query |
context_health |
Memory health audit: orphan links, duplicates, broken file refs, expired TTL, stale sessions, score 0–100 |
context_export |
Export memory as markdown: injectable context for system prompts (full or compact) |
memory_smart_recall |
Unified search: BM25 + graph + quality + freshness + decay + session bias in one call |
memory_visualize |
Open interactive graph viewer inline in MCP Apps–compatible hosts. Force-directed graph, stats, timeline, detail panel |
memory_pin |
Pin an entry (with priority 1-5): pinned entries always appear at the top of recall results sorted by priority, even without a keyword match |
memory_unpin |
Unpin an entry: remove the priority flag |
memory_search |
Unified search with filters: same as memory_recall plus category, tags, from_date, to_date filters. Tag filter uses AND logic — all specified tags must match. sessionBias boosts entries from the current git branch |
memory_tag |
Batch tag operations: add, remove, or set tags on one or more entries by key or id |
memory_reflect |
Memory reflection: deterministically ranks entries by staleness, quality, and over-connection to surface what needs attention or cleanup. Zero LLM |
memory_promote |
Auto-promote drafts: promote low-confidence entries to active status deterministically (default threshold 0.65, Jaccard dedup > 0.5, dryRun by default) |
Typed graph edges
Section titled “Typed graph edges”Since v3.7.0 every edge in the memory graph carries a type, written as type:key:
| Edge type | Meaning | Example |
|---|---|---|
relates |
Generic relatedness — explicit links you declare when saving |
relates:engine-arch |
superseded_by |
Entry replaced by a newer one (written on the old entry) | superseded_by:new-key |
supersedes |
Entry that replaces an older one (mirrored on the new entry) | supersedes:old-key |
Explicit links become relates:key edges, memory_forget(key, action: "supersede") adds the superseded_by/supersedes pair, and recall’s graph expansion can traverse them — so you can tell how entries relate, not just that they do.
MCP Resources
Section titled “MCP Resources”Memory is also exposed as MCP resources for direct context reading:
| Resource | URI | Description |
|---|---|---|
| Memory Entries | toon://memory/entries |
Full memory dump |
| Memory Stats | toon://memory/stats |
Category counts and TTL info |
| Memory Summaries | toon://memory/summaries |
Auto-generated system primer: knowledge map, recent memories, and key decisions |
| Memory Graph Viewer | ui://viewer |
Interactive D3.js force-directed graph rendered inline in any MCP Apps–compatible host |
Resources let agents read memory as context without tool invocations — useful for system prompts or session startup. The system primer provides instant context about your project’s knowledge state.
Examples
Section titled “Examples”Remember a decision
Section titled “Remember a decision”memory_remember({ category: "decision", key: "use-zod", content: "Use Zod for validation", file: "src/types.ts", tags: "validation;types"})// 🧠 Guardado: decision/use-zod (a1b2c3d4)// 🎯 Quality: 0.80 | Confidence: 1.00// 🔗 Entradas relacionadas:// [pattern] zod-schemas — Shared Zod schemas for API validationEntries are auto-scored for quality (0-1) based on tags, links, content detail, and specificity. You-asserted memories get confidence 1.0; inferred/gathered memories get 0.65-0.75.
Remember with TTL
Section titled “Remember with TTL”memory_remember({ category: "knowledge", key: "sprint-deadline", content: "Sprint ends July 18, feature freeze is July 16", ttl: "7d"})// 🧠 Guardado: knowledge/sprint-deadline (x1y2z3w4)// 🎯 Quality: 0.55 | Confidence: 1.00// ⏰ TTL: 2026-07-19Use ttl for temporary context like deadlines or sprint info. Supports relative (7d, 30d) or exact dates (2026-12-31). Expired entries are auto-filtered from search.
Auto-inferred tags
Section titled “Auto-inferred tags”memory_remember({ category: "bug", key: "redis-connection-timeout", content: "Redis connection timeout in production, increased pool size" // tags left empty — auto-inferred from content})// 🧠 Guardado: bug/redis-connection-timeout (a1b2c3d4)// 🏷️ Tags inferidos: redisWhen tags is empty, the system infers them from content using a vocabulary of 20+ categories: redis, auth, api, db, security, test, deploy, config, performance, refactor, error, logging, types, async, state, ui, storage, email, payment, webhook. On top of that, toon-memory init writes a project vocabulary derived from your dependencies (package.json, Cargo.toml, requirements.txt, pyproject.toml, go.mod), so an entry mentioning a dependency like redis also gets auto-tagged redis. More tags = higher quality score.
Search memory
Section titled “Search memory”memory_recall({ query: "redis" })// [bug] redis-pool-fix (i9j0k1l2)// Added max_connections=20// File: redis.ts | Tags: redis;fix | Date: 2026-07-10 | Quality: 0.82Results are quality-weighted — entries with more detail, tags, and links surface first.
Explain WHY a result was returned
Section titled “Explain WHY a result was returned”memory_recall({ query: "redis", explain: true })// [decision] redis-cache-config (a1b2c3d4)// Redis cache layer for session storage// File: src/cache.ts | Tags: redis;cache | Date: 2026-07-10// ↳ 92% relevance · used 14× · used today · importance HIGHThe ↳ reason line is deterministic (relevance %, access count, last-used, importance) — no LLM involved. Use explain: true when you want to know why the agent was shown those entries. Entries saved with an explicit importance level also report it (e.g. · explicit critical).
Cap output with budget_tokens
Section titled “Cap output with budget_tokens”memory_recall({ query: "redis", budget_tokens: 300 })// Entries accumulate greedily; the tail that would exceed the estimate is dropped.// budget_tokens: 0 (default) = no limit.Tip: Combine
budget_tokenswithbudget: "deep"for a context window that stays inside a hard token ceiling regardless of memory size.
Browse the memory index (progressive disclosure)
Section titled “Browse the memory index (progressive disclosure)”memory_recall({ mode: "index" }) // or { query, mode: "index" } for a filtered view// 📇 Memory index (15 entries)://// [1] use-zod (a1b2c3d4) · decision · 2026-07-10 · 100%// [2] redis-cache-config (e5f6g7h8) · decision · 2026-07-09 · 82%// ...mode: "index" shows one line per entry — key, id, category, date, relevance % — with no content, so a large memory costs almost nothing to browse. Pick the ids you need, then bulk-fetch the full entries:
memory_recall({ ids: "a1b2c3d4,e5f6g7h8" })// Fetched 2 entries:// [decision] use-zod (a1b2c3d4)// Use Zod for validation// File: src/types.ts | Tags: validation;types | Date: 2026-07-10ids accepts entry ids or keys, comma/space/;-separated, and preserves your order (unknown entries are skipped). Three layers: browse the index → fetch by ids → search with mode: "flat" for the full ranked result.
Rejected decisions
Section titled “Rejected decisions”Record options you decided against so the agent never re-proposes them. A lightweight convention — a decision entry tagged rejected, no extra schema:
memory_remember({ category: "decision", key: "rejected-graphql", content: "Rejected GraphQL: REST + generated types wins on codegen and schema drift risk.", tags: "rejected;api;graphql"})Tag the entry with rejected and use a rejected-<topic> key so the keyword is easy to recall. Link it to the winning alternative if useful (links: "rest-api"). The next memory_recall for that idea surfaces the rejection with its reason — your “no” becomes part of the project memory instead of being re-debated every session.
Search with date filter
Section titled “Search with date filter”memory_recall({ query: "redis", from_date: "2026-07-01", to_date: "2026-07-31"})Show changes since last session
Section titled “Show changes since last session”memory_diff({ since: "24h" })// 📋 Cambios desde 2026-07-11://// ➕ Nuevas (2):// [decision] use-zod (a1b2c3d4)// Use Zod for validation// [bug] redis-timeout (e5f6g7h8)// Redis connection timeout fixSupports since as relative (24h, 7d) or exact date. Filter by type: all, created, or updated.
Find related entries
Section titled “Find related entries”memory_suggest({ context: "redis cache configuration" })// 🔍 Sugerencias para "redis cache configuration"://// [decision] redis-cache-config (a1b2c3d4)// Redis cache layer for session storage// File: src/cache.ts | Tags: redis;cache | Date: 2026-07-10Archive old entries
Section titled “Archive old entries”memory_archive()// 📦 Archivadas 5 entradas antiguas// 📋 Quedan 42 entradas activasEnable encryption
Section titled “Enable encryption”memory_encrypt()// 🔐 Encriptación habilitada// ⚠️ Guarda esta clave (no se puede recuperar):// a1b2c3d4...List active sessions and conflicts
Section titled “List active sessions and conflicts”memory_sessions({ conflictsOnly: false })// 🧭 Sesiones activas (2) — ventana 10 min://// • opencode @ feature/foo// id: sess-B// Archivos:// • src/shared.ts// • claude @ feature/foo (tú)// id: sess-A//// 🔥 Conflictos suaves (1):// ⚠️ src/shared.ts ↔ opencode@feature/foo, claude@feature/fooUse memory_sessions({ conflictsOnly: true }) if you only care about clashes. See Coordinación multi-sesión below.
Coordinación multi-sesión
Section titled “Coordinación multi-sesión”When you run several AI agent sessions in parallel (e.g. three OpenCode sessions on the same repo at once), they can clobber each other’s work. memory_sessions is a file-based coordination tool — no server, no network, no LLM calls — that lets every session see what its siblings are doing.
How it works
Section titled “How it works”- On startup, a
SessionStarthook writes a heartbeat file for the session at.toon-memory/memory/sessions/<id>.json. Each process writes only its own file, so there is no lock contention. - The heartbeat records the agent name, the git branch, the files touched, and a last-seen timestamp.
- Reading across all those files gives every session a shared, eventually-consistent view of who else is active.
- A session is “active” while its last heartbeat is within the TTL window (10 min). Dead sessions (process PID no longer alive and a stale heartbeat) are pruned lazily.
- Soft conflicts are files touched by 2+ active sessions — surfaced by
memory_sessionsso you can avoid stepping on sibling work.
Recommended habit for parallel sessions
Section titled “Recommended habit for parallel sessions”- At session start, the
SessionStarthook prints other active sessions, their branches, and any soft conflicts. - Before editing shared files, run
memory_sessions()to confirm no sibling is touching them. - When you finish, your heartbeat is marked ended and the files are released.
Memory Graph (recall basado en grafo)
Section titled “Memory Graph (recall basado en grafo)”For larger memories, a flat keyword search can return too much or miss relationships. toon-memory can treat memory as a lightweight knowledge graph so recall returns the right entries with fewer tokens. Combined with quality scoring, the most useful entries surface first.
It is fully deterministic and offline — no embeddings, no vector DB, no LLM, no server. Edges come from:
- Explicit
links— keys you declare when saving an entry. - Implicit
[[key]]refs — any[[some-key]]mention inside the content.
Remember with links
Section titled “Remember with links”memory_remember({ category: "decision", key: "risk-engine-priority", content: "The engine prioritizes risk over speed (see [[risk-spec]]).", file: "spec.md:10", tags: "risk;spec", links: "engine-arch" // explicit edge to another entry})// 🧠 Guardado: decision/risk-engine-priority (a1b2c3d4)Recall with graph mode
Section titled “Recall with graph mode”memory_recall({ mode: "graph" }) finds keyword matches (seeds) and expands the ego-subgraph up to hops (1 or 2). Relevance propagates from seeds to neighbors, so a related spec or decision surfaces even without the query word. The result is capped (limit, default 6) for a smaller, more precise context.
memory_recall({ query: "riesgo", mode: "graph", hops: 2 })// [decision] risk-engine-priority (a1b2c3d4)// The engine prioritizes risk over speed (see [[risk-spec]]).// File: spec.md:10 | Tags: risk;spec | Date: 2026-07-01// links: engine-arch//// [knowledge] risk-spec (a2b3c4d5)// Risk specification for the engine.// links: risk-engine-priority;engine-arch//// [pattern] engine-arch (e6f7g8h9)// Engine architecture.// links: risk-specUse
mode: "graph"when a decision ripples across several entries (architecture, specs, related bugs). For isolated facts, the defaultflatmode is enough. The graph is built on read, so there is no extra index file to maintain.
Token-efficient recall (compact: true)
Section titled “Token-efficient recall (compact: true)”When every token counts, pass compact: true to get a denser output:
memory_recall({ query: "riesgo", mode: "graph", hops: 2, compact: true })// [1] decision/risk-engine-priority// The engine prioritizes risk over speed (see [[risk-spec]]).// tags: risk;spec · edges: ->2, ->3//// [2] knowledge/risk-spec// Risk specification for the engine.// tags: risk · edges: ->1//// [3] pattern/engine-arch// Engine architecture.// tags: engine · edges: ->1What compact changes:
- Each entry gets a stable numeric index (
[1],[2], …) in score order. id,date, andfileare dropped — onlytagsis kept.- In
graphmode, edges render as->2(numeric, not key names). - Neighbors reached via the graph (non-seeds) are truncated to a short snippet with an ellipsis, while directly-matched seeds keep their full content.
- The stored
.toonfile is never mutated —compactonly reshapes the response.
How recall ranks results
Section titled “How recall ranks results”Recall is deterministic and offline (no embeddings, no LLM). Since v3.7.0 the default ranking is RRF (Reciprocal Rank Fusion):
- BM25 relevance — probabilistic term-frequency score over
id+category+key+content+file+tags, fused three times (the only real retriever on a small memory graph). - Graph centrality — degree-normalized (0..1), fused once: a hub connected to many entries ranks near the top even without the query word.
- Adaptive
k—k = clamp(3..60, round(sqrt(n))), wherenis the candidate count. The textbookk=60flattens rank differences on small graphs, so it scales withsqrt(n). - Per-hop decay — nodes
dhops from a seed are multiplied by0.5^d, keeping distant context below nearby context. - Session bias — entries whose file appears in the current session get a 1.15× boost.
- Language family — entries written in the same script as the query (latin/CJK/cyrillic/…) get a +0.1 boost via
languageFamily(). - Folder match — entries whose
path_scopefolder matches the current file get a +0.05 boost. - Explicit importance —
memory_remember({ importance })lets you setcritical(+0.3),high(+0.15),medium(0), orlow(−0.1);criticaldecisions surface beforelownotes, and the level shows up inexplainreasons andbudget: "deep"output. Empty = auto (recency + frequency). - Priority — pinned entries sort first regardless of score.
Pass rrf: false to fall back to the legacy linear weighted score (BM25 + 0.4·centrality + 0.25·importance + seed bonus). In graph mode, recall seeds on keyword matches, expands the ego-subgraph up to hops, and returns the top limit (default 6) by combined score. memory_smart_recall combines all these signals in one call.
Smart recall (memory_smart_recall)
Section titled “Smart recall (memory_smart_recall)”A unified search that combines BM25, graph, quality, freshness, and decay in one call:
memory_smart_recall({ intent: "redis cache configuration", hops: 2 })// Combines BM25 relevance + graph centrality + quality score + freshness decay// Returns top results ranked by combined scoreThis is the recommended way to recall memory — it handles everything in a single call instead of requiring you to orchestrate multiple tools.
Quality scoring
Section titled “Quality scoring”Every entry is automatically scored for quality (0-1) based on:
- Tag coverage (0.3 weight) — more tags = higher score
- Link richness (0.2 weight) — more links = more connected
- Content detail (0.2 weight) — longer, more detailed content scores higher
- Recency (0.15 weight) — recent entries score slightly higher
- Specificity (0.15 weight) — entries with file references and specific keys score higher
High-quality entries surface first in recall results, ensuring the most useful context is always prominent.
Merge-deduplication
Section titled “Merge-deduplication”When you save an entry with an existing key, the system merges attributes:
- Tags: union of both tag sets
- Links: union of both link sets
- Quality: max of both scores
- Confidence: max of both scores
- Content: kept as-is (no overwriting)
- Date: updated to now
- Importance: the higher explicit level wins (critical > high > medium > low)
This means re-saving an entry enriches it rather than replacing it.
Auto-tag from project dependencies
Section titled “Auto-tag from project dependencies”On toon-memory init, the CLI scans your dependency manifests and writes a vocab table into .toon-memory/memory/config.json:
{ "vocab": { "react": ["react"], "zod": ["zod"], "redis": ["redis"] }}memory_remember matches new entries against this vocabulary on top of the built-in one. Re-run toon-memory init after adding major dependencies to refresh it. The vocab key is merged (never clobbered) with the encrypted/capture flags in config.json. More tags = higher quality score.
Categories
Section titled “Categories”Entries are organized by category:
| Category | Use Case |
|---|---|
decision |
Design decisions (“Why X over Y?”) |
pattern |
Project patterns (“Uses Zod for validation”) |
bug |
Bug fixes (“Redis pool exhaustion”) |
knowledge |
General knowledge (“Broker uses RESP”) |
warning |
“Do NOT do this” — anti-patterns, landmines, mistakes to avoid (recalled with a +0.2 boost) |