th-memory-mcp
This server is a local, private long-term memory system for AI assistants (MCP over stdio), letting the AI store, retrieve, and manage user preferences, lessons, interactions, and memory graphs across sessions.
Store memories:
remembersaves/updates preferences (category+key upsert, confidence increases on re-save);save_lessonrecords corrections as situation/mistake/correction.Retrieve memories:
recallsearches preferences/lessons via full-text + recent interactions;get_contextassembles a token-budgeted context with hybrid retrieval and optional graph expansion;get_profilereturns distilled profile sections, top preferences, and recent lessons.Search history:
search_historyfinds past user prompts by keyword with timestamped snippets;get_recent_interactionslists raw captured interactions filtered by kind (prompt/tool_call/error).Manage/delete:
forgetdeletes a memory row by id (with optional type to avoid cross-table id clashes);update_memoryedits fields in place or creates a superseding memory when content changes.Graph & relationships:
link_memorycreates typed relations (supports/contradicts/supersedes/derived_from/related_to/caused_by/depends_on);merge_memorymerges duplicates into a canonical memory with provenance.Consolidation & extraction:
consolidateclusters similar memories and optionally creates derived memories;extract_memoriesscans recent interactions for memory-intent phrases and proposes/creates memory candidates deterministically.Import/export & stats:
export_memorywrites JSON backups underdata/exports/;import_memoryvalidates and dry-runs imports before applying;memory_statsreports counts, DB size, timestamps, and profile sections.Scope & lifecycle awareness: supports USER/SESSION/PROJECT/GLOBAL scoping, lifecycle states (active/stale/superseded/archived), temporal validity, conflict/dedup resolution, and secret filtering for privacy.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@th-memory-mcpremember that I prefer pnpm over npm"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
th-memory-mcp
Status: v2.3.0 — a temporal, conflict-aware, hybrid-retrieval memory engine. 16 MCP tools, 25 passing test suites. Non-destructive schema migration from v1 (all v1 data preserved). New in v2.2: lifecycle states, temporal validity, conflict/dedup resolution with USER/SESSION/PROJECT/GLOBAL scope, hybrid FTS+vector retrieval (RRF), memory graph, get_context assembly, periodic consolidation, and link_memory / merge_memory / update_memory / import_memory / extract_memories. New in v2.2.3: scope-enforced retrieval, graph scope isolation, export/import round-trip, hardened import path (realpath), strict import validation, N+1 query elimination, cold/ablation benchmark, and MEMORY_RETRIEVAL_MODE switch. New in v2.2.7: synced secret filter between Claude hook and capture-core (6-pattern redact instead of line-drop), fixed err() to return isError:true per MCP spec, fixed backup rotation (backup only when migrations pending + prune to 5 files), and added hook error logging for SessionEnd distill. New in v2.2.8: fixed scope contamination 0.75→0 (critical) and conflict false 0→1 (GLOBAL leak), fixed graph hop1 0.52→1.0 via includeGraph, and rescaled benchmark profiles to 5K/20K/100K/500K/1M (pre-commit now quick 5K + normal 20K only). New in v2.2.9: extended export to entities/users/relations, forget now removes associated links, fail-closed migration with shared ISO helper, eliminated FTS N+1, included smoke in test script, and synced viewer to rescaled profiles 5K/20K/100K/500K/1M. New in v2.3.0: CLI th-memory + highlight underline.
Requirements
Node.js >= 20 — the server uses Node-only APIs (the
better-sqlite3native build andimport.meta.urlresolution) and the MCP SDK requires a modern runtime. CI tests on Node 20.x and 22.x.npm — to install dependencies and run the build/test scripts (
npm install,npm run build,npm test).OpenCode — the host that loads this MCP server and the auto-capture plugin. Any build supporting MCP over stdio + plugins works; the plugin runs on OpenCode's bundled Bun runtime.
OS: Windows / macOS / Linux — the server is cross-platform (Node). The auto-capture plugin runs wherever OpenCode's Bun runtime runs. Windows note:
MEMORY_DB_PATHis easiest to set withsetx; on macOS/Linux useexportin your shell profile.
No external services, accounts, or API keys are required — everything lives in a single local SQLite file.
Related MCP server: MCP Vector Memory
Quick Start
Fastest path: after cloning, run npm run quickstart — it builds, wires opencode.json, deploys the plugin, and sets MEMORY_DB_PATH for you in one command. The steps below show exactly what it does (use them if you prefer manual control).
Install via npm (alternative): install the server globally with npm install -g th-memory-mcp (or run it on demand with npx th-memory-mcp), then point the mcp command in opencode.json to th-memory-mcp instead of the built dist/index.js. The auto-capture plugin still comes from this repo (copy src/plugin/learning-capture.ts as described in step 4 below).
Note: no longer published to GitHub Packages — install from npmjs with
npm i -g th-memory-mcp.
# 1. Clone and build
git clone https://github.com/worakorn-prince/th-memory-mcp.git
cd th-memory-mcp
npm install
npm run build
# 2. Share one DB between the server and the plugin
# Windows (PowerShell):
setx MEMORY_DB_PATH "$PWD/data/memory.db"
# macOS / Linux (add to your shell profile, e.g. ~/.zshrc):
# export MEMORY_DB_PATH="$PWD/data/memory.db"Merge this into your
~/.config/opencode/opencode.json(replace<REPO>with the absolute clone path):
{
"instructions": ["<REPO>/AGENTS.memory.example.md"],
"mcp": {
"memory": {
"type": "local",
"command": ["node", "<REPO>/dist/index.js"],
"enabled": true,
"environment": { "MEMORY_DB_PATH": "<REPO>/data/memory.db" }
}
}
}(Optional) Auto-capture: copy
src/plugin/learning-capture.ts→~/.config/opencode/plugins/Restart OpenCode
Try it: "Remember that I prefer pnpm" → new session → "What package manager do I prefer?"
Architecture
OpenCode ──┬─ Plugin learning-capture (Bun) ── auto-captures prompts/tool/error into DB
│ └─ injects profile back into context on compaction
└─ MCP th-memory-mcp (Node.js stdio) ── 16 tools read/write the same SQLite DB
▲
Global instructions (memory-protocol.md) teach the AI to use the toolsSee ARCHITECTURE_v2.md for the full architecture spec.
Why th-memory-mcp?
LLMs don't remember you between sessions — every new chat starts blank. th-memory-mcp gives your AI a private, local long-term memory:
Context-based learning, not fine-tuning — it captures your preferences, corrections, and habits, then recalls them into context next time. Same mechanism as the memory features of leading AI products, without sending any data off your machine.
100% local & private — a single SQLite file, no cloud, no external API. Secrets are filtered before anything is stored.
Low overhead — each tool call is capped (latency < 10 ms, bounded output size) and the AI only queries memory when it's actually useful, so it never bloats your context.
Resilient — every tool degrades gracefully; if the DB is unavailable the AI keeps working instead of crashing.
Open & extensible — MIT licensed, 16 documented tools, a rule-based distill, and an auto-capture plugin you can adapt.
Works with other harnesses
th-memory-mcp is a standard MCP server, so the 9 tools run anywhere MCP-over-stdio is supported. Full auto-capture (background prompt/tool/error capture + profile injection) needs a hook runtime — OpenCode has it built in; Claude Code gets it via our hooks bridge; Codex and Cursor use the tools manually (no hook runtime yet).
Feature | OpenCode | Claude Code | Qwen Code | Codex | Cursor |
16 MCP tools | ✅ | ✅ | ✅ | ✅ | ✅ |
Auto-capture (background) | ✅ plugin | ✅ hooks | ⚠️ adapter | ❌ manual | ❌ Rules |
Profile injection | ✅ compaction | ✅ UserPromptSubmit | ❌ | ❌ | ❌ |
Lexical fuzzy matching | ✅ (v2.0) | ✅ (v2.0) | ✅ (v2.0) | ✅ (v2.0) | ✅ (v2.0) |
Claude Code: see CLAUDE_CODE_HOOKS.md — drop-in hooks replicate the OpenCode plugin (capture + profile injection on
UserPromptSubmit/PreCompact, rule-based distill onSessionEnd).Qwen Code: see QWEN_SETUP.md — MCP works fully; hooks use the Gemini-CLI schema so auto-capture needs a small adapter.
Codex: see CODEX_SETUP.md
Cursor: see CURSOR_SETUP.md
All harnesses share one SQLite file via MEMORY_DB_PATH, so memory captured
anywhere is readable everywhere.
Highlights
Structured memory — preferences with confidence scoring plus dedicated
lessonrecords (situation → mistake → correction) for capturing corrections, not just flat facts.Lifecycle & temporal — every memory has a lifecycle state (active/stale/superseded/archived), confidence/importance/salience scoring, per-type decay, and validity intervals so the AI can reason about point-in-time truth and supersession chains.
Conflict-aware — duplicate detection, contradiction detection, and update/supersession resolution preserve both sides of ambiguous evidence instead of silently overwriting.
Hybrid retrieval —
get_contextblends FTS5 keyword search with a dependency-free lexical fuzzy matching (hashed n-gram similarity, 512-dim FNV-1a) (RRF fusion + scoring), then assembles a token-budgeted context with optional memory-graph expansion.Consolidation — periodic clustering of similar memories into derived memories with full provenance (
derived_fromlinks).First-class Thai / i18n — Thai-aware tokenization in distill; the AI accepts Thai and English interchangeably.
Private by default — a single local SQLite file, no cloud, no API keys, with secret lines (
api_key=,password:,token) filtered before storage.Cross-harness — runs on OpenCode, Claude Code, Codex, and Cursor sharing one DB; auto-capture + profile injection via OpenCode plugin or Claude hooks.
Lightweight & resilient — Node +
better-sqlite3, no extra native extensions; every tool degrades gracefully so the AI keeps working if the DB is unavailable.
Scripts
Command | Description |
| compile TypeScript → |
| run the MCP server (stdio) from |
| rule-based distill: interactions → profile sections + prune old data (env |
| full suite: capture, distill, lifecycle, temporal, conflict, retrieval, graph, context, consolidation, benchmark, security, tools_v21, smoke, e2e_transport, retrieval_benchmark, recall_regression, scope, profile, entity_extraction, conflict_benchmark, security_regression, export_import_roundtrip |
| test capture-core (filter secrets, dedupe, truncate, insert SQL) |
| test distill-core (Thai tokenize, stats, profile sections, prune) |
| test lifecycle engine (states, decay, supersession) |
| test temporal model (validity, historical retrieval) |
| test conflict & dedup resolution |
| test hybrid FTS+vector+RRF retrieval |
| test memory graph (entities, relations, traversal) |
| test context assembly + token budgeting |
| test clustering + derived memories |
| latency benchmark over 300 memories |
| injection / safety checks |
| end-to-end smoke test over JSON-RPC (16 tools) |
Tools (16)
Tool | Description |
| upsert preference (category+key) — re-saving the same key increases confidence by 0.1 (cap 1.0) |
| search preferences + lessons (FTS5) + recent matching interactions. Use before starting a new task |
| user profile overview: profile sections + top preferences + 5 most recent lessons |
| record a lesson learned from a correction (situation / mistake / correction) |
| search past user prompts by keyword (200-char snippets per row) |
| delete one memory row (preference/lesson/interaction) by id (+type prevents cross-table id clash) |
| memory statistics: counts by kind, DB size, oldest/newest interaction, profile sections |
| list recent raw interactions (filter by kind) — feedstock for Smart Distill |
| export memory to JSON under |
| assemble relevant memories for the current task via hybrid retrieval (+ optional graph expansion) with token budgeting |
| cluster similar memories via embedding similarity; optionally create derived/consolidated memories linked via |
| create a typed relationship between two memories in the graph (supports/contradicts/supersedes/derived_from/related_to/caused_by/depends_on) |
| merge a duplicate/near-duplicate into a canonical memory (source becomes superseded, provenance in |
| update mutable fields in place, or create a superseding memory when |
| import memories from JSON (validates type, dedupes against existing, never overwrites blindly); dry-run by default, |
| scan recent captured interactions for memory-intent phrases and propose memory candidates (deterministic, no LLM); dry-run by default, |
CLI (th-memory)
Two binaries ship in package.json (bin):
Binary | Entry | Purpose |
|
| MCP server (stdio) — the 16 tools above |
|
| local memory CLI (zero-dep, shares the same DB via |
Usage: th-memory [--db <path>] [--json] [--plain] <command> [options] — per-command help via th-memory <command> --help.
Global flags (every command):
Flag | Effect |
| use this SQLite file (sets |
| print JSON |
| disable colors |
| show help (global or per-command) |
| print version |
Commands:
Command | Usage |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Highlight behavior (highlight command and recall --highlight): matches are wrapped with an underline (ESC[4m…ESC[24m) when stdout is a TTY with colors enabled; when piped, with --json, or with --plain/--no-color, matches are wrapped with [mem]…[/mem] markers instead.
Examples:
th-memory remember --category coding_pref --key package_manager --value pnpm
th-memory recall pnpm --limit 5
th-memory recall pnpm --highlight
echo "I prefer pnpm for installs" | th-memory highlight -q pnpmNote: --value - reads the value from stdin (e.g. echo -n "pnpm" | th-memory remember --category coding_pref --key package_manager --value -).
Install with OpenCode
Merge the
mcpsection fromopencode.example.jsoninto youropencode.json(global or project-level)Important: set
MEMORY_DB_PATHto the SAME database file for both the server and the plugin (the example uses<ABSOLUTE_PATH>/th-memory-mcp/data/memory.db), otherwise the auto-capture plugin writes to a different DB than the one the AI readsHow to set it (pick one):
define it in the mcp
environment(see example) — covers the MCP server onlyor set it as a system/user-level environment variable (e.g.
setx MEMORY_DB_PATH "D:/path/to/memory.db"on Windows) — covers both server and plugin, since the plugin runs in the same process as OpenCode
Attach the global memory rules — add to
opencode.json:"instructions": ["C:/Users/<user>/.config/opencode/memory-protocol.md"](example rule content is in
AGENTS.memory.example.md— can be attached at project level instead)(Optional) Deploy the auto-capture plugin: copy
src/plugin/learning-capture.ts→~/.config/opencode/plugins/learning-capture.tsRestart OpenCode (config loads at startup only)
Test: "Remember that I prefer pnpm" → open a new session and ask back
Daily usage
The AI accepts both Thai and English interchangeably — you can switch languages at any time without warning.
Example command | Tool / effect |
"Remember that..." |
|
"Summarize memory" / "distill memory" | Smart Distill — AI reads |
"How is my memory?" / "memory status" |
|
"Export memory" / "backup memory" |
|
"Search history..." |
|
"Forget..." |
|
Long-term care: run npm run distill occasionally to summarize stats and prune interactions older than 30 days.
data/ structure
data/
├── memory.db # SQLite (WAL mode) — main DB (+ .db-wal, .db-shm)
└── exports/ # JSON files from export_memory (writeable only in this dir)DB path can be overridden via the
MEMORY_DB_PATHenv vareverything in
data/is git-ignored
Benchmark — internal self-reported (not third-party)
⚠️ Internal self-reported benchmark — not third-party benchmark
internal small-N: 180 records/30 topics (B.retrieval: 30 topics × 5 relevant + 30 distractors = 180; full run also uses small-N storage/temporal/context subsets)
single-machine self-run: single developer machine, single OS/Node/better-sqlite3 build — not cross-machine, not independently verified
not third-party benchmark: self-reported, not independently verified; do not compare as if from an external evaluator
Dataset and harness are in
repro/(commitable) andbenchmark/(full framework, seeTH_MEMORY_MCP_BENCHMARK_SPEC.mdandbenchmark/README.md).
Two modes
Mode | Command | Data | Suites | Use case |
Normal |
| 180 records / 30 topics | retrieval | quick check (<5s) |
Heavy |
| 600 records / 100 topics + 2k scale | all (storage/retrieval/temporal/context/performance/scalability/cold/ablation) | stress / regression |
Reproduce:
npm run build
# Normal — quick
npm run benchmark
npm run benchmark -- --k 10
npm run benchmark -- --out repro/results
# Heavy — full framework, more data
npm run benchmark:heavy
# or custom:
node benchmark/run.mjs --suite all --topics 100 --distractors 100 --scale 2000 --out benchmark/resultsViewer — compare last 3 versions (table + charts)
npm run benchmark:viewer
# or: npx serve . -l 3000
# open http://localhost:3000/benchmark/viewer/ or http://localhost:3000/result/viewer.htmlThe viewer loads benchmark/results/history.jsonl, groups by version, takes the latest run of the 3 most recent versions (e.g. 2.2.6 / 2.2.7 / 2.2.8) and shows a highlighted table (1 row per version) + bar charts for Recall@5 / MRR / NDCG@5 and Latency p95. Results are also saved per version in result/v*_benchmark_result.md and benchmark/results/versions/<ver>/.
Last internal run (v2.2.8, warm, normal profile, a2dcbce — not third-party): Recall@5=0.9060, Precision@5=0.9060, MRR=1, NDCG@5=0.9347 over 100 topics/600 records. See result/v2.2.8_benchmark_result.md and repro/README.md for details and caveats (internal, single-machine self-run).
Known Limitations
No encryption at rest (plaintext-at-rest) —
data/memory.db(WAL mode,better-sqlite3) is a plain, unencrypted SQLite file.100% local & privatemeans no cloud or network exfiltration — it does not mean encrypted at rest. Anyone with filesystem access (shared machine, backup, malware, stolen device) can read preferences/lessons/interactions in plaintext. For sensitive data, use OS-level full-disk encryption (BitLocker / FileVault / LUKS) or an opt-in SQLCipher build (requires native rebuild and key management). No SQLCipher/in-code encryption is applied by default andsrc/db/index.tsdocuments this explicitly.Single-user local process — no auth layer (Batch B-3) —
userId/sessionId/projectIdare caller-supplied strings with no authentication or authorization check inside the server. Scope isolation (retrieval,get_context, graph traversal/expansion,consolidate,link_memory,merge_memory) is enforced only against the values the caller sends, so a caller can read or write any scope by passing a different id. This is suitable for a single-user local process (one operator, localdata/memory.db). Do not share one server/DB across mutually-untrusted users without an auth layer in front that authenticates each caller and forces the correctuserId(and allowedprojectId/sessionId). No new auth system is built into the server by design — that layer belongs in front of it.
License
MIT © 2026 worakorn-prince
This project is licensed under the MIT License — see the LICENSE file for the full text.
Available Tools
16 toolsconsolidateConsolidate memoriesB
Cluster similar memories via embedding similarity and optionally create derived/consolidated memories linked via 'derived_from'. Use during periodic consolidation.
| Name | Required | Description | Default |
|---|---|---|---|
| derive | No | Create a derived memory for each cluster | |
| userId | No | Scope to a user (USER scope) | |
| projectId | No | Scope to a project | |
| sessionId | No | Scope to a session (SESSION scope) | |
| threshold | No | Cosine similarity threshold for clustering (default 0.7) | |
| minClusterSize | No | Minimum members to report a cluster (default 2) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the clustering mechanism and optional derived creation, but does not state whether original memories are modified, whether the operation is reversible, what side effects occur (e.g., deleting clusters), or any permission requirements. The lack of such context leaves the agent guessing about the tool's impact.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no redundancy. The core purpose is front-loaded, and the usage hint is appended. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool performs clustering and optional derived memory creation, but the description lacks details on return values (no output schema), impact on existing memories, threshold behavior, and what 'consolidation' entails. An agent would need more context to call this correctly and understand its effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all six parameters are already documented in the schema. The description adds a small amount of context about 'derived_from' linking but does not clarify parameter interactions or defaults beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action (cluster similar memories via embedding similarity) and a resource (memories), with an optional derived-memory creation linked via 'derived_from'. This clearly distinguishes it from sibling memory tools like merge_memory or link_memory by focusing on clustering and derived creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a timing hint ('Use during periodic consolidation') but does not specify when to avoid this tool or how it compares to alternatives like merge_memory or link_memory. The guidance is minimal and lacks exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_memoryExport memory to JSONA
Export preferences, lessons, profile (and optionally raw interactions) to a JSON file under data/exports/. Only writes inside that directory. Returns the file path, size in bytes and a JSON preview.
| Name | Required | Description | Default |
|---|---|---|---|
| filename | No | Output file name inside data/exports/ (only A-Z a-z 0-9 . _ - allowed, must end with .json). Defaults to memory-export-YYYYMMDD-HHmmss.json | |
| includeInteractions | No | Include raw interaction rows in the export (file gets bigger) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of exposing behavior. It discloses an important safety constraint ('Only writes inside that directory') and states what the tool returns (file path, size, JSON preview). It does not mention overwrite behavior or permissions, but it covers the most material side effect for an export tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The first sentence front-loads the core action and target location; the second adds the safety guard and return-value summary. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description compensates by naming return values (file path, size, JSON preview). Combined with full parameter documentation in the schema and the directory-restriction detail, the agent has enough context to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents both filename and includeInteractions. The description adds only the phrase 'optionally raw interactions,' which restates the includeInteractions parameter rather than adding new meaning. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific action ('Export'), a concrete resource (preferences, lessons, profile, optionally raw interactions), and a target destination (JSON file under data/exports/). This clearly distinguishes it from sibling tools like import_memory or recall, making its purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage — you would call this when you want a JSON export of memory data — but it does not explicitly state when to prefer this tool over alternatives like import_memory or get_recent_interactions. It gives clear context but no exclusions or alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_memoriesExtract memories from interactionsA
Scan recent captured interactions for memory-intent phrases and propose memory candidates (deterministic, no LLM). Dry-run by default; pass apply=true to create them (source=captured).
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Interaction kind to scan (default prompt) | |
| apply | No | Create the proposed memories (default false = propose only) | |
| limit | No | Max recent interactions to scan (default 50) | |
| userId | No | Scope extracted memories to a user (USER scope) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full burden and does it well: it explicitly discloses deterministic behavior, no LLM involvement, dry-run default, and the mutation path when apply=true. This gives an agent a reliable model of side effects before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two focused sentences front-load the core purpose and then give the key behavioral switch. Every clause earns its place; no filler or redundant restating of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The definition is sufficient for correct invocation: purpose, defaults, mutation flag, and provenance are all covered, and the schema documents parameters. It would be slightly stronger if it described the shape of the returned memory candidates, since there is no output schema, but this is a minor gap for a proposal tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all four parameters. The description mainly restates the apply default and adds source=captured context, which is useful but does not add substantive meaning beyond the schema's own descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Scan recent captured interactions ... propose memory candidates'. It also differentiates from memory-write/recall siblings by emphasizing this is a deterministic scanning/proposal step, not direct storage or retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly signals the intended workflow: run in dry-run to propose candidates, pass apply=true to persist with source=captured. It does not name sibling alternatives or exclusion conditions, but the use case is clear from the context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forgetForget a memory entryA
Delete one memory row (preference, lesson or interaction) by id and sync the search index. Pass type when you know it (ids from remember are preference ids, from save_lesson are lesson ids).
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Which table the id belongs to. Recommended whenever known, because numeric ids can coincide across tables. | |
| target_id | Yes | Row id to delete (id returned by remember/save_lesson) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full behavioral burden. It usefully discloses that the operation destroys a row and has a side effect ('sync the search index'), but says nothing about irreversibility, required permissions, or behavior when the id does not exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with zero filler, and the core delete semantics and side effect are front-loaded before the optional-parameter advice.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter delete tool with no output schema, the description covers purpose, the key side effect, and parameter sourcing. It could add error/not-found behavior, but nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and already explains why type matters across tables, but the description adds genuinely new mapping information: 'ids from remember are preference ids, from save_lesson are lesson ids'. That source-to-type mapping is not derivable from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete one memory row ... by id') and names the entity types it can target, which clearly separates it from read-side siblings like recall and update_memory. It stops short of naming which sibling to use when the goal is modification instead of deletion, so it does not reach full sibling routing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives conditional guidance for the optional parameter ('Pass type when you know it') and explains where the ids come from. It never states when to prefer forget over update_memory or merge_memory, so the when-to-use-this-tool question is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_contextGet assembled contextA
Assemble relevant memories for the current task via hybrid retrieval (+ optional memory-graph expansion), with token budgeting. Use to load memory into context before a task.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of seed memories (default 10) | |
| query | No | Optional focus query to seed hybrid retrieval | |
| userId | No | Scope context to a user (USER scope) | |
| maxTokens | No | Token budget for assembled context (default 2000) | |
| projectId | No | Scope context to a project | |
| sessionId | No | ||
| includeGraph | No | Expand seeds with memory-graph neighbors | |
| includeHistory | No | Include superseded/archived memories |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses the use of hybrid retrieval, optional graph expansion, and token budgeting, but does not clarify read-only behavior, return format, or what happens when the token budget is exceeded.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two dense sentences with no filler: the core mechanism is front-loaded, followed by a usage cue. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 8 parameters, no annotations, and no output schema, the description gives a good high-level purpose but omits important operational details: what the assembled context looks like, how scoping params (userId/projectId/sessionId) interact, and how it differs from recall/search_history. The schema covers param semantics but not these behaviors.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 88%, so the schema already documents most parameters. The description adds little beyond alluding to query via 'hybrid retrieval' and maxTokens via 'token budgeting'; it does not explain parameter interactions or the effect of includeGraph/includeHistory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (assemble), resource (relevant memories), and method (hybrid retrieval with optional memory-graph expansion and token budgeting). It clearly identifies the tool's purpose beyond the title, though it does not explicitly distinguish it from sibling retrieval tools like recall or search_history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit usage cue: 'Use to load memory into context before a task.' This gives clear when-to-use guidance. However, it does not mention alternatives or state when not to use this tool, leaving some sibling ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_profileGet user profileA
Get the distilled user profile: profile sections, top preferences by confidence (max 15), and the 5 most recent lessons.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral transparency burden. It usefully discloses output composition and limits (max 15 preferences, 5 most recent lessons) and frames the result as 'distilled', indicating it is not the full raw profile. It does not explicitly state side-effect freedom, but 'Get' and the summary-style output strongly imply a read operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that leads with the verb and resource, then packs the distinguishing output details efficiently. There is no filler or unnecessary repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, the description adequately covers the tool's input and expected return shape. Terms like 'profile sections' and 'lessons' could be slightly more explicit, but the core information an agent needs to call and understand the result is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline of 4 applies. There is no parameter meaning for the description to add beyond what an empty schema already communicates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get the distilled user profile'. It goes beyond a generic getter by enumerating the exact components returned (profile sections, top preferences by confidence capped at 15, and the 5 most recent lessons), which helps distinguish it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to choose get_profile over related siblings like get_context, get_recent_interactions, or memory_stats. The intended use is only implied by the name and output description, with no exclusions or alternatives mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_interactionsRecent interactionsA
List recently captured raw interactions (newest first) as [id] ts [kind] content lines. Optionally filter by kind. Use for auditing history or before distilling memory.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Filter by kind (prompt / tool_call / error) | |
| limit | No | Max rows (default 20, max 100) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses key behavioral traits: newest-first ordering, raw interaction scope, and the line format [id] ts [kind] content. It does not mention edge cases like empty results or pagination, but these are minor for a read-only list tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no redundancy. The action, output format, filtering option, and use case are each covered efficiently, and the most important scoping information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a lightweight read-only tool with optional params and no output schema, the description adequately explains the return format, ordering, and purpose. The limit parameter is fully covered by the schema, leaving no critical gap, though the description could briefly note that results are capped.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides 100% coverage for both parameters, including enums, defaults, and limits. The description adds only the notion of optional kind filtering, which is already present in the schema, so no significant extra meaning is provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states the specific verb 'List', the resource 'recently captured raw interactions', ordering ('newest first'), and the exact output line format. This distinguishes it clearly from memory-management siblings like remember, recall, and consolidate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Use for auditing history or before distilling memory' gives clear context for when the tool is appropriate. It does not name alternative tools or state explicit exclusions, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
import_memoryImport memoriesA
Import memories from a JSON array or a .json file inside data/exports/. Validates type, dedupes against existing memories, and never overwrites active memory blindly. Dry-run by default; pass apply=true to insert.
| Name | Required | Description | Default |
|---|---|---|---|
| file | No | Path to a .json export file (must be inside data/exports/) | |
| json | No | Inline JSON: an array of memory objects, or { memories: [...] } | |
| apply | No | Actually insert memories (default false = dry run, just report) | |
| userId | No | Scope imported memories to a user (USER scope) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden. It discloses several important behaviors: validation, deduplication, refusal to blindly overwrite active memory, and dry-run-by-default safety. It does not describe return format or failure modes, but the core safety-relevant traits are clearly conveyed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The most important scoping information (source format) appears first, followed by safety guarantees and the activation flag. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations and no output schema, the description covers source, validation, dedupe, overwrite policy, and dry-run default. It omits specifics about the returned report and error handling, but the essential context for safe invocation is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds little beyond the schema: it restates the file-location constraint and the dry-run/apply behavior already present in the parameter descriptions. It does not add new semantic detail for userId or JSON structure beyond what the schema gives.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Import memories from a JSON array or a .json file inside data/exports/.' It clearly distinguishes the tool from siblings like export_memory and merge_memory by framing it as the import path for external memory data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives operational guidance ('Dry-run by default; pass apply=true to insert') but does not explicitly say when to choose this tool over alternatives such as merge_memory or update_memory. Context implies import is for bulk ingestion, but no exclusions or alternative routing are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
link_memoryLink two memoriesB
Create a typed relationship between two memories in the graph (supports/contradicts/supersedes/derived_from/related_to/caused_by/depends_on).
| Name | Required | Description | Default |
|---|---|---|---|
| relation | Yes | Link relation (supports/contradicts/supersedes/derived_from/related_to/caused_by/depends_on) | |
| sourceId | Yes | Source memory id | |
| targetId | Yes | Target memory id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description bears the full burden of disclosure, but it only says 'create a typed relationship.' It does not reveal side effects, whether existing links are overwritten, directionality of source/target, validation behavior, or whether memories must already exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one compact sentence with the action front-loaded and the relationship types listed inline. There is no fluff or redundant commentary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter tool with a fully documented schema, the description is minimally viable, but it leaves gaps: no return behavior, no effect on existing links, and no semantics for the relation types. Given the lack of annotations and output schema, more context would be helpful.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds little beyond the schema: 'between two memories' reinforces the meaning of sourceId/targetId, and the relation list mirrors the enum exactly. No additional semantic detail is provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action – 'Create a typed relationship between two memories in the graph' – and enumerates the valid relationship types. This clearly distinguishes it from sibling tools like update_memory, merge_memory, or consolidate by focusing on inter-memory graph links.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to use link_memory versus alternatives such as consolidate, merge_memory, or update_memory. The description only states what it does, without exclusions, prerequisites, or an explicit 'when to use' cue.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statsMemory statisticsA
Summarize memory usage: interaction counts by kind, preference/lesson totals, DB file size, oldest/newest interaction timestamps, and profile sections.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the transparency burden. The verb 'Summarize' clearly implies a non-mutating read-style operation, but the description does not explicitly state that it makes no changes, nor does it describe any other behavioral details like cost or freshness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that leads with the core action and then enumerates the exact delivered statistics. Every word adds useful information, with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description serves as the sole source of return-value expectations, and it enumerates counts, totals, file size, timestamps, and profile sections. Some terms like 'profile sections' remain somewhat vague, but for a simple zero-parameter stats tool this is reasonably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics to clarify. The schema coverage is trivially 100%, and the description reasonably focuses on the output content instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Summarize') and identifies a clear resource (memory usage) with a detailed list of metrics included in the output. It is distinct from sibling tools in content, though it does not explicitly contrast with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for retrieving high-level memory statistics and summaries rather than detailed records or management actions. However, it provides no explicit when-to-use or when-not-to-use guidance, nor does it name alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
merge_memoryMerge memoriesA
Merge a duplicate/near-duplicate memory into a canonical one. The source becomes superseded and provenance is recorded in metadata.merged_from.
| Name | Required | Description | Default |
|---|---|---|---|
| sourceId | Yes | Memory to merge away (becomes superseded) | |
| targetId | Yes | Canonical memory to keep (becomes active) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden. It clearly discloses the key side effect: the source becomes superseded and provenance is recorded in metadata.merged_from. It does not mention reversibility or permissions, but the most important behavioral outcome for an agent to know is explicitly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single well-formed sentence with no fluff. It front-loads the main action and then states the two important behavioral results (source supercoded, provenance recorded). Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter merge tool with no annotations and no output schema, the description gives enough to call it correctly: what it does, which parameter plays which role, and the expected side effects. It could add nuances like whether the operation is reversible, but nothing essential is missing for a typical invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both sourceId and targetId clearly. The description adds context about the canonical relationship but does not add detailed parameter-level semantics beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Merge'), a clear resource ('memory'), and a precise scope ('duplicate/near-duplicate memory into a canonical one'). It distinguishes itself from sibling tools like forget, update_memory, and consolidate by clarifying that this operation is about canonicalization of near-duplicates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: when a memory is a duplicate or near-duplicate of another canonical memory. It does not explicitly name alternatives or give when-not conditions, so it falls just short of a 5, but the trigger condition is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recallRecall memoryA
Search preferences + lessons via full-text index, plus recent matching interactions. Use before starting a new task.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max preference/lesson matches (default 8) | |
| topic | Yes | Topic to recall from memory |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral disclosure burden. It does disclose that the tool searches a full-text index and returns recent matching interactions, but it does not state whether the operation is read-only, how results are ranked, or whether recent interactions are subject to the limit parameter. This is adequate for a search tool but leaves some behavioral details implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The core search scope is front-loaded, and the usage guidance is immediately actionable. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with no output schema, the description covers the key elements: what is searched, the retrieval scope, and when to use it. It does not describe the exact return structure, but it gives enough context for an agent to invoke recall correctly before starting a task.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both 'topic' and 'limit'. The description adds minimal semantic value beyond the schema, only clarifying that the search targets preferences and lessons. Baseline 3 is appropriate given full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and resource ('preferences + lessons via full-text index, plus recent matching interactions'), which clearly identifies what the tool does. It is specific enough to distinguish recall from siblings like search_history or get_recent_interactions, even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use the tool: 'Use before starting a new task.' It does not mention alternatives or exclusions, but the timing guidance is clear and actionable for an agent deciding whether to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rememberRemember preferenceA
Save or update a user preference (category+key upsert). Re-saving the same key increases confidence by 0.1 (cap 1.0). Returns the row id for forget().
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Short stable key, e.g. package_manager | |
| value | Yes | The preference value | |
| category | Yes | Preference category |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral burden. It discloses the upsert semantics, the confidence increment on re-saving the same key, the 1.0 cap, and the return value (row id) needed by forget(). This is unusually transparent for a write operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight, front-loaded sentences with no filler. Every sentence adds distinct value: what the tool does, how repeat calls behave, and what the caller receives.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 3-parameter tool with no output schema, the description covers the action, the uniqueness semantics, the confidence side effect, and the return contract. Nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful extra semantics by explaining that category+key together form the identity for the upsert and that re-saving the same key affects confidence, which is not captured in the schema property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear action: 'Save or update a user preference' and specifies the uniqueness mechanism as 'category+key upsert'. This differentiates it from generic memory tools like update_memory and the recall/search siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use case is implied: call this when you need to persist or update a user preference. However, it does not explicitly state when to prefer this over siblings like update_memory, save_lesson, or link_memory, nor does it describe exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_lessonSave lessonA
Record a lesson learned from a correction: what situation, what mistake, what is the correct way. Call immediately after the user corrects your work.
| Name | Required | Description | Default |
|---|---|---|---|
| mistake | Yes | What was done wrong | |
| situation | Yes | The original situation/context | |
| correction | Yes | The correct approach |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it does supply useful behavioral context: the operation is a write ('Record') and carries a timing constraint (only after a correction). It does not disclose persistence semantics — whether the lesson is stored permanently, surfaced by recall or search_history, or deduplicated on repeated saves — which an agent would need to anticipate downstream effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, both purposeful: the first defines what the record captures, the second states when to invoke the tool. No wasted words, and the most operationally important guidance ('immediately after the user corrects your work') is prominent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with three simple string params, full schema documentation, and no output schema, the description covers the essentials: what to record and when to call it. The only gap is explicit boundary-setting against the closely related write-siblings (remember, extract_memories, update_memory), which is implied by the correction-specific language but never stated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters, setting the baseline at 3. The prose ('what situation, what mistake, what is the correct way') merely restates the parameter meanings rather than adding format, examples, or edge-case nuance, so the description adds marginal value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Record a lesson learned from a correction') and enumerates the three captured elements ('what situation, what mistake, what is the correct way'), which map directly to the required schema parameters. This correction-specific framing clearly distinguishes it from generic memory siblings like remember and recall.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Call immediately after the user corrects your work' provides an explicit, unambiguous trigger for invocation. However, it does not name alternatives (e.g., extract_memories or remember) or state when not to use this tool, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_historySearch prompt historyA
Search past user prompts (kind='prompt') by keyword. Returns timestamped snippets truncated to 200 chars each.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max results (default 10) | |
| query | Yes | Text to search in past prompts |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the filtered scope (kind='promp'), that results are timestamped, and that snippets are truncated to 200 characters. This exceeds a bare 'Search history' statement, though it stops short of noting ordering, case sensitivity, or lack of side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The entire description is two efficient clauses that each add value: the first states the action and scope, and the second clarifies the return format. It is front-loaded and contains no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only two parameters, full schema coverage, and no output schema, the description is complete enough for correct invocation. It explains what comes back (timestamped snippets truncated to 200 chars), and the schema covers input constraints. Missing details like ordering are minor for this simple search use case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds the notion of keyword search but does not elaborate on the limit parameter or its interaction with results; the schema already documents query and limit adequately.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Search'), identifies the exact resource ('past user prompts'), and adds a distinguishing technical detail (kind='prompt'). It also describes the result shape (timestamped snippets truncated to 200 chars), making it easy to tell apart from broader memory-retrieval siblings like recall or get_recent_interactions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The scope is clear—use this to search past user prompts by keyword—but it is stated as a capability rather than explicit routing guidance. No when-not conditions or alternative tools are named, so an agent must infer when this should be chosen over sibling retrieval tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_memoryUpdate a memoryA
Update mutable fields (summary/importance/confidence/valid_from/valid_until/metadata) in place. If content changes, a superseding memory is created by default (set supersede=false to edit in place).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Memory id to update | |
| content | No | New content. When provided, a superseding memory is created (supersede=true) unless supersede=false. | |
| summary | No | New summary | |
| metadata | No | New metadata object (replaces) | |
| supersede | No | If content changes, create a superseding memory instead of editing in place (default true) | |
| validFrom | No | ISO timestamp or null to clear | |
| confidence | No | ||
| importance | No | ||
| validUntil | No | ISO timestamp or null to clear |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose the single most important non-obvious trait: changing content creates a superseding memory by default rather than mutating the row. It still omits permissions requirements, reversibility, and what happens to the prior memory (invalidation vs retention), so it is strong but not complete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with zero filler; the in-place scope comes first and the default-fork side effect second, so the most consequential behavior is front-loaded. Nothing repeats the title or wastes tokens.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter mutation tool with no annotations and no output schema, the description covers field mutability and the supersede default but says nothing about the response (does the returned id change when a superseding memory is created?) or about failure modes such as an unknown id. Adequate, but gaps remain for an agent to call it confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 78%, so most parameters are already documented in the schema, including the supersede flag and the content/supersede interaction. The description restates the field set (with snake_case names that differ from the schema's camelCase) and adds no format or constraint detail beyond the schema, so it sits at the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (update) and resource (memory), and enumerates the mutable fields plus the in-place vs supersede distinction. This separates it from write siblings like remember and merge_memory, but it never names an alternative explicitly, so an agent must infer routing from the field list alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'Update mutable fields ... in place' and by the supersede=false escape hatch, which tells the agent how to force an edit rather than a fork. However, there is no explicit when-to-use vs remember/merge_memory/consolidate guidance and no stated preconditions (e.g. that the id must exist and be live).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v2.3.0- Changed
consolidate2 fields changed- added
Input schema / properties / sessionIdAdded value: +{ + "description": "Scope to a session (SESSION scope)", + "type": [ + "string", + "null" + ] +} - added
Input schema / properties / userIdAdded value: +{ + "description": "Scope to a user (USER scope)", + "type": [ + "string", + "null" + ] +}
2 tool updates
v2.2.9- Changed
forget1 field changed- changed
Input schema / properties / type / enumPrevious value: -[ - "preference", - "lesson", - "interaction" -]New value: +[ + "memory", + "preference", + "lesson", + "interaction" +]
- Changed
update_memory3 fields changed- added
Input schema / properties / validFromAdded value: +{ + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO timestamp or null to clear" +} - added
Input schema / properties / validUntil / anyOfAdded value: +[ + { + "$ref": "#/properties/validFrom/anyOf/0" + }, + { + "type": "null" + } +] - removed
Input schema / properties / validUntil / typeRemoved value: -[ - "string", - "null" -]
16 tool updates
v2.2.1- First observed
consolidate - First observed
export_memory - First observed
extract_memories - First observed
forget - First observed
get_context - First observed
get_profile - First observed
get_recent_interactions - First observed
import_memory - First observed
link_memory - First observed
memory_stats - First observed
merge_memory - First observed
recall - First observed
remember - First observed
save_lesson - First observed
search_history - First observed
update_memory
TDQS
Scored across 16 tools
Most tools clearly target distinct operations, but recall and get_context both serve task-time memory retrieval and could be confused by an agent. Search-related tools are otherwise differentiated by scope, and descriptions provide enough clarity.
Names mix single-word verbs like remember and forget, get_ prefixed accessors, verb_noun operations like merge_memory, and the noun-only memory_stats. The inconsistent style is noticeable, though all names are snake_case and readable.
With 16 tools, this sits at the borderline heavy end for a memory server. The breadth is somewhat justified by coverage of CRUD, graph links, consolidation, import/export, and stats, but a few tools could potentially be combined.
The tool set covers the full memory lifecycle: capture/extract, save, retrieve, update, merge, delete, graph linking, consolidation, profile generation, export/import, and statistics. There are no obvious critical dead ends for the stated memory-management purpose.
Maintenance
Related MCP Connectors
Persistent memory for Claude Code and Cursor. Stop re-explaining your project every session.
Persistent cross-session memory shared by Codex, Claude Code, ChatGPT, and other AI agents.
Shared memory for coding agents. Stop re-explaining your codebase every session.
- memoryOAuthcom.leapmemory
Long-term memory for AI assistants. Isolated per-user storage, recall across conversations.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceProvides persistent local memory functionality for AI assistants, enabling them to store, retrieve, and search contextual information across conversations with SQLite-based full-text search. All data stays private on your machine while dramatically improving context retention and personalized assistance.3-
- AlicenseNot gradedqualityNot gradedmaintenanceProvides AI coding agents with persistent, long-term memory through local semantic search and SQLite storage. It enables agents to save and retrieve architectural decisions or project context across different conversation sessions without requiring cloud services.MIT
- AlicenseAqualityBmaintenanceProvides persistent cross-session memory and full-text search for AI coding assistants, storing project context, decisions, and preferences while enabling searchable access to conversation history via local SQLite.81MIT
- AlicenseAqualityBmaintenanceProvides AI coding assistants with persistent memory storage using a local SQLite database. Enables tools to remember project details, notes, and relationships across sessions to maintain context and reduce repetitive explanations.174MIT