Thoth-Mem
With this server, you can persist, retrieve, audit, and lifecycle-manage local, SQLite-backed coding-agent memory through six MCP tools.
mem_save — save verified evidence, observations, observation reviews/promotions, or directly promoted durable memories such as decisions, conventions, failures, discoveries, and handoffs.
mem_recall — search promoted project memory with current or historical temporal scope and compact or context-return modes.
mem_context — build bounded project-wide or session-specific continuity briefings, prioritizing handoffs.
mem_get — expand a selected memory, summary, observation, or evidence record, optionally including predecessor lineage.
mem_project — inspect project views without mutation: list aliases, view timelines, briefings, history, summaries, and observations.
mem_session — record verified root lifecycle events and versioned summaries for enroll, recover, capture root, checkpoint pre-compact, guide post-compact, and finalize.
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., "@Thoth-Memrecall the auth pattern from last session"
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.
thoth-mem
Persistent memory your coding agents can share — and you can audit.
Local, SQLite-first memory for OpenCode, Codex, Claude Code, and Pi. Six focused MCP tools. Zero model calls required.
Overview • Install • How it works • Use • Tools • Benchmarks • Runtime • Troubleshooting • Development
thoth-mem is under active development. Core concepts, memory protocols, and integration contracts are still evolving. Expect major breaking changes before a stable release.
91.9% | 6 | 4 | 0 |
LongMemEval-S RecallAny@5 | focused MCP tools | native harnesses | model calls required |
Why thoth-mem
Coding agents lose the decisions that matter between sessions: why an approach was chosen, which failure already occurred, what the next safe action is, and which evidence supports the current answer. Static instruction files help with rules, but they do not provide temporal history, scoped retrieval, or attributable provenance.
thoth-mem gives every supported harness one durable local memory without turning memory into an opaque second agent.
Design choice | What it gives you |
SQLite is the source of truth | One local, inspectable ledger with rebuildable FTS5 retrieval. |
Evidence before memory | Immutable supporting records remain separate from promoted conclusions. |
Temporal history | Corrections and supersession preserve how project knowledge changed. |
Progressive retrieval | Start compact, add context only when useful, expand selected records last. |
Scoped identity | Projects and root sessions are explicit; memory does not guess ownership. |
A deliberately small API | Six workflow-level MCP tools instead of a sprawling CRUD surface. |
No embedding model, vector extension, graph engine, LLM, network service, HTTP server, or dashboard is required.
Related MCP server: LumenCore
Install
Requirements: Node.js >=22.12.0 and a supported harness. Pi setup has no version allowlist or upper version limit: it checks package-manager capabilities and verifies the installed extension and resources. New Pi releases do not require a version override. The reproducible SDK test baseline is @earendil-works/pi-coding-agent 1.0.1; passing setup is not certification of every runtime behavior on future releases.
thoth-mem installs memory tooling and lifecycle integration—not agents or subagents. Add --plan --json to any managed npx setup command to preview its changes without writing.
Harness | Native integration | Install |
Claude Code | Marketplace plugin, native hooks, six-tool MCP registration, and memory skill |
|
Codex CLI | Marketplace plugin, native hooks, six-tool MCP registration, and memory skill |
|
OpenCode | Native npm plugin, lifecycle adapter, six-tool MCP surface, and memory skill |
|
Pi | Native package extension, five model-facing tools, lifecycle adapter, and one package-relative six-tool MCP child |
|
Managed setup is global/user-native, idempotent when already current, and requests a host restart after a changed install. Project-scoped copied bundles, broad manager-cache edits, legacy fallback, and fragment migration are intentionally unsupported.
How it works
flowchart LR
subgraph Hosts[Native harnesses]
O[OpenCode]
C[Codex]
A[Claude Code]
P[Pi]
end
O & C & A & P --> H[Lifecycle adapters]
H --> S[MemoryService]
S --> L[(Immutable SQLite ledger)]
S --> F[(Rebuildable FTS5 index)]
L & F --> R[Bounded progressive context]
R --> O & C & A & PNative adapters map each harness into the same project and root-session contract.
Evidence is immutable; session events receive a database-ordered sequence.
Observations stay outside durable memory until a verified review accepts them and an explicit promotion materializes the proposed memory.
Recall combines project isolation, temporal truth, lexical ranking, and a strict character budget.
Every harness receives the same bounded context without introducing another model into the loop.
Pi delivers recovery once as a persisted hidden message on the first root prompt after startup, resume, new, fork, or successful compaction. Reload skips delivery when the active branch already has recovery after its latest compaction. OpenCode adds a persisted synthetic text part to the first root message per plugin process (including resume) and the first after compaction. Neither host puts recovery in the system prompt or refreshes it per prompt, preserving system-prompt cache stability. If memory is unavailable, both deliver locally verified identity first and retry on later root prompts until one verified recovery block is delivered.
Automatic capture is limited to verified root prompts and checkpoint evidence, including available host compaction text. It excludes assistant reasoning, arbitrary tool traffic, delegated/subagent output, filesystem sweeps, and full transcripts. Private blocks and recognizable credentials are filtered before content-dependent keys or persistence; do not submit secrets.
thoth-mem never silently promotes an observation into durable memory. Rejection is terminal, corrections append successors, and provenance remains available through stable IDs.
Use the memory
Optional agent instructions
Optionally paste this snippet into your AGENTS.md or CLAUDE.md for proactive memory use. thoth-mem never writes it or edits those files.
## Memory (thoth-mem)
- Before exploring or planning any non-trivial task, run `mem_recall` with the task's key terms. Don't wait to be asked.
- When a decision is accepted, a root cause is verified, an approach fails, or a non-obvious convention is found, save it with `mem_save` right away.
- If a recovered handoff's pending action is done, close it: save the outcome under the same `topic_key`.
- Before ending meaningful unfinished work, save one handoff (`topic_key: handoff/<workstream>`).
- Skip memory for trivial or purely conversational turns.Check adoption
Run thoth-mem adoption --project <exact-key-or-alias> [--json] [--data-dir <dir>] against an existing database for a read-only baseline. It never creates or migrates a database. It reports open handoffs with ages in seconds, replaced handoffs (superseded by another handoff), and closed handoffs (superseded by a non-handoff under the same topic key). Session totals include zero-save sessions and per-session counts of distinct agent explicit_save/handoff evidence IDs; automatic captures and unattributed evidence are excluded. Recall usage is not measured.
Retrieve progressively
mem_recall mode=compact
↓
mem_recall mode=context or mem_context
↓
mem_get only for selected stable IDsChoose tools by intent
Intent | Tool |
Save evidence or durable knowledge |
|
Find current or historical project memory |
|
Recover a bounded project or session briefing |
|
Expand one selected record with optional predecessor history |
|
Inspect timelines, summaries, observations, or project state |
|
Record verified root lifecycle events and supported summaries |
|
The MCP server exposes exactly these six tools. Pi exposes every tool except mem_session as a native model-facing tool; mem_session is hook-owned and called only by the extension through its MCP child. OpenCode additionally exposes the read-only native thoth_mem_root_identity tool; it is session metadata, not a memory operation. Generic MCP connections attribute sessionless saves to a server-assigned connection session, not a verified native root session.
Tool text is valid JSON capped at 20,000 characters and matches structuredContent. Oversized results clip long strings, then drop trailing array items if needed, with payload_truncated first in warnings; irreducible results return output_too_large. Narrow requests when needed. Pi never slices tool text: unexpected over-cap text becomes a thoth-mem.pi.output_truncated JSON notice with narrowing guidance.
Use
mem_projectwithaction=timelinewhen you need to understand how promoted knowledge changed, rather than which memories best match a query.mem_getreturns the selected record once; lineage is empty unlesshistory: true, then contains only predecessors, newest first. Evidence has no lineage;mem_project action=historystill starts with the selected record.At
checkpoint_pre_compactorfinalize, the core validates a submitted summary or deterministically derives or reuses one from the session's evidence, without model or network calls. Pi, Claude Code, and OpenCode also forward available host compaction text as checkpoint evidence without requiring prior pre-compaction; recognized headings yield a cited harness summary, never promoted memory.Derived summaries omit a compaction's objective, next-action, pending, and blocker claims after a later substantive root prompt (at least 40 code points after whitespace collapse) or support for a memory-derived claim. Decisions, completed work, and changed surfaces remain eligible; persisted summaries at their activity watermark are not regenerated.
Sessions have no lifecycle state and always accept new activity. All summaries share one versioned lineage per session: a new summary supersedes the current one when its coverage end is at least the current one's; a lower end is rejected as late. Derivation reuses a current summary that already covers the latest activity.
Pi uses per-run lifecycle keys so quitting after resume derives a summary covering new activity at exit. Codex and Claude Code may replay an earlier finalize receipt on resume; lazy derivation at the next recovery covers new activity when that session is selected as the previous session. See native lifecycle for this known limitation.
Automatic recovery, including after compaction, shows the newest open handoff, then the previous session's summary, then other project memories within the existing caps. It never shows the current session's own summary; explicit session reads still can.
Observation candidates remain outside memory and FTS until a verified root review accepts them and a separate explicit promotion materializes their exact proposed memory.
LongMemEval-S
The public results use the immutable cleaned LongMemEval-S corpus and its 470 eligible non-abstention questions. The runtime remains lexical and local: no embeddings, models, or evaluation-time network calls.
Lexical strategy | RecallAny@5 | Recall@5 | RecallAll@5 | NDCG@10 | MRR | Retrieval p95 | Role |
| 61/470 (13.0%) | 9.8% | 6.6% | 0.1045 | 0.1287 | 1.1471 ms | Archived control |
| 388/470 (82.6%) | 67.7% | 54.0% | 0.6965 | 0.7947 | 1.4437 ms | Bounded candidate |
| 446/470 (94.9%) | 87.9% | 78.7% | 0.8538 | 0.8717 | 3.9512 ms | Broad quality reference |
| 419/470 (89.1%) | 79.7% | 68.3% | 0.7700 | 0.8177 | 2.0552 ms | Archived E0 candidate |
| 432/470 (91.9%) | 84.8% | 75.5% | 0.8165 | 0.8538 | 9.3504 ms | Current default |
RecallAny@5: questions with at least one gold session in the first five results.
Recall@5: fractional coverage across all gold sessions.
RecallAll@5: questions whose every gold session appears in the first five.
NDCG@10 / MRR: ranking quality and first-gold position.
Retrieval p95: environment-sensitive; compare latency only within the same report.
The first four rows come from the immutable Top-5 lexical comparison. The current-default row comes from the passing stable optimization round, which preserved complete ordered output while reducing p95 by 28.3% from its stable baseline. Every listed run records zero errors and zero model, LLM, or evaluation-time network calls.
The dataset is pinned to revision 98d7416c24c778c2fee6e6f3006e7a073259d48f and SHA-256 d6f21ea9d60a0d56f34a05b609c79c88a451d2ae03597821ea3d5a9678c3a442. Evaluation runs offline through the real built MemoryService, with one isolated SQLite database per question. Gold IDs and oracle data never enter indexed text or ranking.
Protocol sources: LongMemEval repository, official cleaned dataset, and pinned dataset revision.
Runtime data and migration
All harnesses resolve one data directory in this order: an explicit command value, THOTH_MEM_DATA_DIR, strict provider configuration, then ~/.thoth-mem. The database is always memory.sqlite inside the selected directory.
Git repositories keep a stable project ID in the shared Git common directory: worktrees share memory, while independent clones remain separate. Folder renames do not change the display name; use thoth-mem project rename --project <exact-key-or-alias> --name <display-name> [--data-dir <dir>] to change it explicitly.
The provider file lives below XDG_CONFIG_HOME/thoth-mem/config.json when XDG configuration is set, or below ~/.config/thoth-mem/config.json otherwise. Malformed, unreadable, schema-invalid, or missing-runtime configuration fails closed.
Hosts automatically migrate supported older schemas to revision 12 at startup; thoth-mem migrate completes pending migrations manually and reports the changes. On large databases, backups and migration can exceed host timeouts; use that manual path instead. Revision 12 creates or verifies memory.sqlite.pre-v12.bak, rechecks the revision and live source under an immediate write-excluding lock, removes session state and end-time columns, and merges existing summaries into one version lineage per session while keeping IDs. Integrity and foreign-key checks must pass; a mismatched backup or source drift fails closed before mutation.
Older databases first apply the revision-10 Pi harness migration (memory.sqlite.pre-v10.bak) and revision-11 empty-session cleanup (memory.sqlite.pre-v11.bak) as needed. That cleanup removes only unreferenced non-import host sessions and their lifecycle receipts that cite neither evidence nor a summary; all other sessions, receipts, evidence, and memories are preserved.
Stop every process that may hold the target database, then import the conventional ~/.thoth/thoth.db:
thoth-mem import-legacyFor a nonstandard source or explicit mapping:
thoth-mem import-legacy --source ./legacy.sqlite --map ./mapping.json --data-dir ./current-memory
thoth-mem import-legacy --jsonFor a reviewable two-step workflow, write a plan, inspect it, then apply it:
thoth-mem import-legacy plan --source ./legacy.sqlite --target ./current-memory/memory.sqlite --plan ./import-plan.json
thoth-mem import-legacy apply --plan ./import-plan.json --report ./import-report.jsonAdd --map ./mapping.json to plan for explicit mapping. apply uses the target recorded in the plan; existing plan and report output files are refused.
The importer fingerprints its inputs, creates a verified backup and isolated candidate when needed, and publishes only after integrity checks pass. Keep the legacy database, verified backup, and recovery bundle until the migrated runtime has been independently validated.
Troubleshooting
If memory stays unavailable after an upgrade, look for these host diagnostics:
Pi:
thoth-mem degraded: pi_mcp_startup_timeout — the memory server did not start in time; if memory stays unavailable, run `thoth-mem migrate`(at most once per session). Other failures retain codes such aspi_lifecycle_request_failed.OpenCode logs:
OpenCode lifecycle degraded: node_lifecycle_timeout — memory did not respond in time; if memory stays unavailable, run `thoth-mem migrate`(once per plugin session), orOpenCode lifecycle degraded: node_lifecycle_nonzero_exit — <bounded stderr tail>.Codex / Claude Code hook stderr:
thoth-mem public plugin: Lifecycle failed: SQLite migration revision A→B failed: …, including the observed failure and thethoth-mem migraterecommendation.
A timeout alone does not prove a migration is pending. To complete any pending migrations outside host time limits, run:
npx --yes thoth-mem@latest migrateWith an installed command, use thoth-mem migrate; with a package checkout, use node <package>/dist/index.js migrate. Add --data-dir <dir> to select the directory containing your existing memory.sqlite; otherwise the runtime data selection above applies. A missing database is an error, not a new database.
Output such as Migration: 11 → 12 shows the revision change; Backup created: or Backup verified: names the retained backup. Sessions removed: and Lifecycle receipts removed: count only the empty-session cleanup, not evidence or memories; Duration: is elapsed milliseconds. Add --json for the thoth-mem.migrate.v1 envelope with revisions, backups, removal counts, durationMs, and alreadyCurrent. It is safe to rerun: an already-current database reports a no-op (alreadyCurrent: true) without changing the source database or its sidecars.
Keep memory.sqlite.pre-vN.bak backups until recovery is verified. To restore one, first stop all hosts and thoth-mem processes, move the current memory.sqlite and any memory.sqlite-wal / memory.sqlite-shm files aside, then copy the chosen backup to memory.sqlite. Restoring loses changes made after that backup; an older schema will migrate again on the next writable open. Prefer a clean host exit (in Pi, /quit) over killing its terminal.
Killed processes may leave memory.sqlite.pre-vN.bak.<pid>.<uuid>.tmp files. They are unpublished backup candidates, not retained backups; delete them only when no thoth-mem process is running.
Development
Clone, build, local host wiring, verification, benchmark reproduction, and repository layout live in the development guide.
Task-specific engineering, persistence, privacy, lifecycle, and testing guidance starts at the agent context index.
Available Tools
6 toolsmem_contextC
Build bounded handoff-first continuity. project_key is always required. Supply both root_session_key and harness for session context, or omit both for project context.
| Name | Required | Description | Default |
|---|---|---|---|
| harness | No | Native harness for root_session_key; supply both for session context, or omit both for project context. | |
| project_key | Yes | Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content. | |
| budget_chars | No | ||
| correlation_id | No | ||
| finalize_answer | No | ||
| root_session_key | No | Optional verified root session key; supply with harness for session context, or omit both for project context. |
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. 'Build' suggests some construction/side effect, but the description never says whether this reads or writes, what gets persisted, whether auth is required, or how budget_chars bounds output. Only the parameter pairing rule is disclosed.
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 short sentences, front-loaded with purpose and immediately followed by the required-parameter and mode rules. Efficient, with only the opening jargon phrase costing clarity.
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 6-parameter tool with no annotations and no output schema, the description covers only the identity params. It says nothing about budget_chars, correlation_id, finalize_answer, or the shape of what comes back, so an agent cannot 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?
At 50% schema coverage, the description must compensate, and it only reinforces project_key (always required) and the root_session_key/harness pairing – both already documented in the schema. budget_chars, correlation_id, and finalize_answer receive no explanation in either place, leaving half the surface opaque.
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 verb+object phrase 'Build bounded handoff-first continuity' conveys a sense of producing continuity context, but 'bounded handoff-first continuity' is jargon that never plainly states what the tool actually returns or does. Nothing distinguishes it from siblings like mem_session, mem_project, or mem_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?
It does specify a mode rule: supply both root_session_key and harness for session context, or omit both for project context. But this is parameter-shape guidance, not tool-selection guidance – it never says when to reach for mem_context over mem_recall or mem_session, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mem_getA
Expand one selected memory, summary, observation, or evidence id returned by a prior tool result. Set history:true to include predecessor lineage for memory, summary, or observation records; evidence ids return evidence without lineage.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Memory, summary, observation, or evidence id returned by a prior tool result. | |
| history | No | Set true to expand predecessor lineage for memory, summary, or observation records; evidence ids have no lineage. | |
| correlation_id | No |
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 usefully discloses the conditional lineage behavior of history:true and the fact that evidence ids have no lineage, but says nothing about read-only safety, permissions, or what 'expand' actually returns (full record vs. fields).
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 tight sentences with no filler; the core action and its precondition come first, and the second sentence earns its place by covering the history/evidence edge case.
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 read tool with no annotations and no output schema, the description should at minimum say what 'expand' returns and how lineage is presented. It covers the input side adequately but leaves the response shape and correlation_id unexplained.
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 67% and both id and history are already documented in the schema; the description largely restates those semantics (id from prior result, history for lineage) rather than adding syntax or format detail. The undocumented correlation_id is not covered anywhere.
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 ('Expand') and a precise resource (one memory/summary/observation/evidence id), and the phrase 'returned by a prior tool result' distinguishes it from search-style siblings like mem_recall or mem_context. It does not name an alternative sibling explicitly, so it falls short of full differentiation.
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 precondition for use is clear: you must already hold an id produced by a prior tool result, which implicitly routes the agent away from recall/search tools. There are no explicit when-not conditions or named alternatives, but the context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mem_projectA
Inspect project views without mutation. action="list": no fields required. action="timeline": project_key required; optionally since, until, cursor, limit, and budget_chars. action="briefing", "summaries", or "observations": project_key required; optionally supply both root_session_key and harness to select that session's summaries/observations (briefing still includes project-wide memories). action="history": id required from a prior result. temporal filters summaries/observations, not timeline. list returns at most 256 exact aliases per project plus aliasCount and aliasesTruncated metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Required for action="history"; send a record id returned by a prior tool result. | |
| limit | No | Maximum items (1-100) for action="timeline" or "observations". | |
| since | No | Optional inclusive lower ISO-8601 instant for action="timeline" only; must be <= until. | |
| state | No | Optional state filter for action="observations". | |
| until | No | Optional inclusive upper ISO-8601 instant for action="timeline" only; must be >= since. | |
| action | Yes | Inspect project views without mutation. action="list": no fields required. action="timeline": project_key required; optionally since, until, cursor, limit, and budget_chars. action="briefing", "summaries", or "observations": project_key required; optionally supply both root_session_key and harness to select that session's summaries/observations (briefing still includes project-wide memories). action="history": id required from a prior result. temporal filters summaries/observations, not timeline. list returns at most 256 exact aliases per project plus aliasCount and aliasesTruncated metadata. | |
| cursor | No | Unchanged nextCursor from a prior mem_project action="timeline" result; keep project_key, since, and until unchanged. | |
| harness | No | Native harness for the optional root_session_key filter; supply both or omit both. Not accepted for action="timeline". | |
| temporal | No | Filter summaries/observations: current selects current summary versions or observation correction-chain leaves; history includes older summary versions or selects observation predecessors. Not accepted for action="timeline". | |
| project_key | No | Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content. Required for action="timeline", "briefing", "summaries", or "observations"; not required for "list" or "history". | |
| budget_chars | No | Optional aggregate character budget for timeline, briefing, summaries, or observations; timeline clamps a positive integer to 1024-20000 characters. | |
| root_session_key | No | Optional session filter for action="briefing", "summaries", or "observations"; supply with harness or omit both. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden; it explicitly says 'without mutation' (read-only), documents cursor semantics ('unchanged nextCursor'), and states list returns at most 256 aliases plus aliasCount/aliasesTruncated. It omits permissions, rate limits, and error behavior, so 4.
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?
Front-loaded with the tool purpose and then action clauses; no filler sentences. Dense for six actions but appropriately sized, so 4.
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 description covers action routing and key constraints, but with no output schema it explains return shape only for action='list' and leaves briefing/summaries/observations/history outputs unspecified. Schema 100% coverage offsets parameter gaps, but return transparency remains incomplete, so 3.
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% and the top-level text repeats the action property description rather than adding new parameter 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?
States 'Inspect project views without mutation' and enumerates six actions (list, timeline, briefing, summaries, observations, history), which conveys the tool's read-only inspection role. It does not distinguish mem_project from siblings like mem_recall or mem_context, so 4 rather than 5.
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 action-by-action requirements (project_key required for timeline/briefing/summaries/observations, id for history, optional session filters) and notes temporal filters apply to summaries/observations, not timeline. It lacks when-not-to-use or explicit alternatives, so 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mem_recallA
Call at the start of non-trivial repository work before exploring, with task key terms, unprompted. Search promoted project memory with a non-empty query before expanding selected records. temporal="current" (default) searches current guidance; temporal="history" includes historical records. mode="compact" (default) returns bounded snippets; mode="context" adds selected memory content.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | compact (default) returns bounded snippets; context adds selected memory content. | |
| limit | No | ||
| query | Yes | Non-empty search string for promoted project memory. | |
| temporal | No | current (default) searches current guidance; history includes historical records. | |
| project_key | Yes | Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content. | |
| budget_chars | No | ||
| correlation_id | No | ||
| finalize_answer | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose meaningful behavior: default values ('current', 'compact'), what each returns ('bounded snippets' vs 'adds selected memory content'), and the temporal scope difference between current guidance and historical records. It does not address permissions, error behavior, or rate limits, but the mode/temporal semantics are genuinely informative beyond the schema enums.
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?
Front-loaded with the call condition and search scope before mode/temporal detail, and there is little wasted text. The phrasing 'unprompted' is slightly awkward and the mode/temporal clauses duplicate schema content, costing a bit of density, but overall it is tight and well-ordered.
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?
No output schema exists, so the description need not explain return values, and it does describe the compact/context output difference. However, for an 8-parameter tool with half the parameters undocumented anywhere, the description leaves limit, budget_chars, correlation_id, and finalize_answer entirely unexplained, which is a notable gap for calling 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 coverage is 50%, and the description only restates mode and temporal behavior already documented in the schema's own enum descriptions, adding no syntax or format detail for them. The other four parameters (limit, budget_chars, correlation_id, finalize_answer) are undocumented in both the description and the schema, so the description does not compensate for the coverage gap. Baseline 3 fits.
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: 'Search promoted project memory' with a non-empty query. It conveys the recall/search nature of the tool and gestures at its relationship to expansion ('before expanding selected records'), implicitly contrasting with a retrieval sibling like mem_get. It stops short of naming any sibling explicitly, so the differentiation is inferred rather than stated.
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?
Strong when-to-use guidance: 'Call at the start of non-trivial repository work before exploring, with task key terms, unprompted,' and 'before expanding selected records.' This tells the agent both the trigger moment and the follow-up workflow. It does not explicitly name alternative tools or exclusions (e.g., when to prefer mem_context or mem_get), so it falls just shy of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mem_saveA
Save unprompted as soon as decisions, root causes, failed approaches, or non-obvious conventions are verified. Also save durable discoveries and continuation handoffs. For a direct promoted memory other than a handoff, write memory.content as concise labeled Result, Rationale, Scope, and Caveat / safe action lines. Omit Scope or Caveat / safe action when it does not apply, and never invent details to fill the template. Keep evidence compact and factual. Handoff memories keep the dedicated Objective, Completed, First pending action, Blockers, and Key files/checks format and require a stable workstream topic_key; close a finished handoff by saving its outcome under the same topic_key. Send exactly one branch: evidence (optionally + memory for a direct promoted save; structured evidence with metadata forbids memory and requires event_key plus the session pair), observation (requires event_key; session scope also requires the session pair and coverage), observation_review or observation_promotion (each requires event_key plus the session pair). Supply root_session_key and harness together or omit both.
| Name | Required | Description | Default |
|---|---|---|---|
| memory | No | Promoted memory for direct evidence only; requires evidence without metadata. Do not combine with observation, observation_review, or observation_promotion. | |
| harness | No | Native harness for root_session_key; supply both or omit both. Required wherever root_session_key is required. | |
| evidence | No | Direct evidence { kind, content }; optionally add memory for a promoted save. Structured metadata forbids memory and requires event_key, root_session_key, and harness. | |
| event_key | No | Stable event key for idempotency; required for observation, observation_review, observation_promotion, and evidence with metadata. | |
| observation | No | Submit a supported candidate without promotion; requires event_key. Session scope also requires root_session_key, harness, and coverage. | |
| project_key | Yes | Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content. | |
| project_name | Yes | Creation/display metadata only; never participates in project identity equality. Prefer the database-persisted name returned by lifecycle or project output. | |
| root_session_key | No | Verified root session key; supply with harness or omit both. Required for session-scoped observations, observation_review, observation_promotion, and evidence with metadata; blank counts as absent. | |
| observation_review | No | Review one supported observation; requires event_key, root_session_key, and harness. Send no other operation branch or memory. | |
| observation_promotion | No | Promote one accepted observation without new prose; requires event_key, root_session_key, and harness. Send no other operation branch or memory. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose meaningful behavior: unprompted save timing, branch exclusivity ('Send exactly one branch'), the requirement that structured evidence forbids memory and needs event_key plus the session pair, and the topic_key lifecycle for closing handoffs. It omits what the call returns, error/failure behavior, and any auth/permission context.
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 content is dense and largely earns its place given four operation branches, but it is delivered as one long unbroken block of run-on sentences rather than a structured list, hurting front-loading of the branch rules. It is acceptable in length but weak in structure.
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 10-parameter tool with nested objects and no output schema, the description covers the branch logic and content templates well, but says nothing about what a successful save returns (e.g. an id) or how failures are surfaced. The very rich schema compensates on the input side, keeping this at an adequate level.
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 3 is the baseline, but the description adds real semantic value: the required content template (Result, Rationale, Scope, Caveat) and the rule not to invent details, the handoff format, and the topic_key requirement. These are usage semantics not derivable from the schema alone.
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 opening sentence names a specific verb (save) and precise triggers (decisions, root causes, failed approaches, non-obvious conventions), which is well beyond a tautology. It does not explicitly differentiate itself from the read-oriented siblings (mem_context, mem_recall, mem_get), though the write nature is implicit.
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 gives a clear trigger ('save unprompted as soon as ... are verified') and then a detailed routing rule for the mutually exclusive branches (evidence, observation, observation_review, observation_promotion), including which branch forbids what. It stops short of naming the sibling recall tools as alternatives, but the intra-tool branch guidance is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mem_sessionA
Record verified root lifecycle events; never use it as an ordinary save. summary is optional and only valid for operation="checkpoint_pre_compact" with kind="checkpoint" or operation="finalize" with kind="final". summary.coverage starts at 1 and its to_sequence must advance the current ending sequence for this session and kind. Each claim's support_ids must be evidence ids from this project_key + root_session_key/harness session inside summary.coverage.
| Name | Required | Description | Default |
|---|---|---|---|
| content | No | ||
| harness | Yes | Verified native harness for root_session_key in project_key. | |
| summary | No | Optional only for operation="checkpoint_pre_compact" (kind="checkpoint") or operation="finalize" (kind="final"). coverage starts at 1 and to_sequence must advance the current summary for this session and kind. support_ids must be evidence ids from this project_key + root_session_key/harness session inside coverage. Canonical submission limit: 20000 UTF-16 units. | |
| event_key | Yes | Stable lifecycle event key; retries for the same operation must resend identical content/summary. | |
| operation | Yes | Lifecycle operation; summary is allowed only for checkpoint_pre_compact (checkpoint) or finalize (final). | |
| project_key | Yes | Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content. | |
| project_name | Yes | Creation/display metadata only; never participates in project identity equality. Prefer the database-persisted name returned by lifecycle or project output. | |
| root_session_key | Yes | Stable verified root session key; required with harness for every operation. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden. It discloses important constraints around summary validity, coverage advancement, and support_ids scoping, but omits permissions, side effects, failure behavior, and the meaning of 'verified' lifecycle events.
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 compact and front-loads the core purpose before diving into summary constraints. It avoids filler, though some of its content duplicates the already-detailed schema descriptions.
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 complex lifecycle tool with nested objects and no output schema, the description covers core purpose and summary rules. It is incomplete on operation-specific semantics: enroll, recover, capture_root, and guide_post_compact are not explained, leaving invocation guidance thin for a required enum parameter.
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 thoroughly. The description reinforces a few nested constraints around summary, coverage, and support_ids, but adds little beyond what the schema descriptions already state.
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: recording verified root lifecycle events. It explicitly distinguishes the tool from an ordinary save, which routes the agent away from the sibling mem_save for normal persistence.
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 gives a clear exclusion ('never use it as an ordinary save') and specifies exactly when the optional summary payload is valid. However, it does not explain when to choose each lifecycle operation or name alternatives beyond the implicit ordinary-save sibling.
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.
6 tool updates
v0.5.6- Changed
mem_context13 fields changed- added
Input schema / properties / budget_charsAdded value: +{ + "type": "number" +} - added
Input schema / properties / correlation_idAdded value: +{ + "type": "string" +} - added
Input schema / properties / finalize_answerAdded value: +{ + "type": "boolean" +} - added
Input schema / properties / harnessAdded value: +{ + "description": "Native harness for root_session_key; supply both for session context, or omit both for project context.", + "enum": [ + "opencode", + "codex", + "claude", + "pi", + "mcp", + "cli", + "import" + ], + "type": "string" +} - removed
Input schema / properties / limitRemoved value: -{ - "description": "Number of observations to retrieve (default: 20)", - "type": "number" -} - removed
Input schema / properties / max_charsRemoved value: -{ - "description": "Output character budget; 0 disables the context cap", - "minimum": 0, - "type": "number" -} - removed
Input schema / properties / projectRemoved value: -{ - "description": "Filter by project name", - "type": "string" -} - added
Input schema / properties / project_keyAdded value: +{ + "description": "Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content.", + "minLength": 1, + "type": "string" +} - removed
Input schema / properties / recall_queryRemoved value: -{ - "description": "Optional query to append fused recall evidence without changing base context sections", - "type": "string" -} - added
Input schema / properties / root_session_keyAdded value: +{ + "description": "Optional verified root session key; supply with harness for session context, or omit both for project context.", + "minLength": 1, + "type": "string" +} - removed
Input schema / properties / scopeRemoved value: -{ - "description": "Filter by scope", - "enum": [ - "project", - "personal" - ], - "type": "string" -} - removed
Input schema / properties / session_idRemoved value: -{ - "description": "Filter to a specific session", - "type": "string" -} - added
Input schema / requiredAdded value: +[ + "project_key" +]
- Changed
mem_get10 fields changed- removed
Input schema / properties / afterRemoved value: -{ - "description": "Timeline observations after the focus item (default: 5)", - "maximum": 20, - "minimum": 0, - "type": "number" -} - removed
Input schema / properties / beforeRemoved value: -{ - "description": "Timeline observations before the focus item (default: 5)", - "maximum": 20, - "minimum": 0, - "type": "number" -} - added
Input schema / properties / correlation_idAdded value: +{ + "type": "string" +} - added
Input schema / properties / historyAdded value: +{ + "description": "Set true to expand predecessor lineage for memory, summary, or observation records; evidence ids have no lineage.", + "type": "boolean" +} - changed
Input schema / properties / id / descriptionPrevious value: -"Record ID to retrieve, interpreted according to kind"New value: +"Memory, summary, observation, or evidence id returned by a prior tool result." - changed
Input schema / properties / id / typePrevious value: -"number"New value: +"string" - removed
Input schema / properties / include_timelineRemoved value: -{ - "description": "Include surrounding observations in the same session", - "type": "boolean" -} - removed
Input schema / properties / kindRemoved value: -{ - "description": "Memory kind to retrieve (defaults to observation)", - "enum": [ - "observation", - "prompt" - ], - "type": "string" -} - removed
Input schema / properties / max_lengthRemoved value: -{ - "description": "Max characters to return (default: 50000)", - "minimum": 100, - "type": "number" -} - removed
Input schema / properties / offsetRemoved value: -{ - "description": "Character offset for large content (default: 0)", - "minimum": 0, - "type": "number" -}
- Changed
mem_project26 fields changed- changed
Input schema / properties / action / descriptionPrevious value: -"Project view to return"New value: +"Inspect project views without mutation. action=\"list\": no fields required. action=\"timeline\": project_key required; optionally since, until, cursor, limit, and budget_chars. action=\"briefing\", \"summaries\", or \"observations\": project_key required; optionally supply both root_session_key and harness to select that session's summaries/observations (briefing still includes project-wide memories). action=\"history\": id required from a prior result. temporal filters summaries/observations, not timeline. list returns at most 256 exact aliases per project plus aliasCount and aliasesTruncated metadata." - changed
Input schema / properties / action / enumPrevious value: -[ - "list", - "summary", - "graph", - "topics", - "topic", - "health" -]New value: +[ + "list", + "timeline", + "briefing", + "history", + "summaries", + "observations" +] - added
Input schema / properties / budget_charsAdded value: +{ + "description": "Optional aggregate character budget for timeline, briefing, summaries, or observations; timeline clamps a positive integer to 1024-20000 characters.", + "type": "number" +} - removed
Input schema / properties / continuationRemoved value: -{ - "description": "Opaque continuation token returned by graph navigation views", - "type": "string" -} - added
Input schema / properties / cursorAdded value: +{ + "description": "Unchanged nextCursor from a prior mem_project action=\"timeline\" result; keep project_key, since, and until unchanged.", + "maxLength": 4096, + "minLength": 1, + "type": "string" +} - removed
Input schema / properties / focus_node_idRemoved value: -{ - "description": "Graph focus node id for navigation=neighborhood, currently obs:<id>", - "type": "string" -} - added
Input schema / properties / harnessAdded value: +{ + "description": "Native harness for the optional root_session_key filter; supply both or omit both. Not accepted for action=\"timeline\".", + "enum": [ + "opencode", + "codex", + "claude", + "pi", + "mcp", + "cli", + "import" + ], + "type": "string" +} - added
Input schema / properties / idAdded value: +{ + "description": "Required for action=\"history\"; send a record id returned by a prior tool result.", + "minLength": 1, + "type": "string" +} - removed
Input schema / properties / include_supersededRemoved value: -{ - "description": "Explicit history opt-in; honored by navigation=superseded only", - "type": "boolean" -} - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum items to return"New value: +"Maximum items (1-100) for action=\"timeline\" or \"observations\"." - added
Input schema / properties / limit / exclusiveMinimumAdded value: +0 - changed
Input schema / properties / limit / maximumPrevious value: -500New value: +100 - removed
Input schema / properties / limit / minimumRemoved value: -1 - changed
Input schema / properties / limit / typePrevious value: -"number"New value: +"integer" - removed
Input schema / properties / max_charsRemoved value: -{ - "description": "Response character budget; 0 is supported for action=summary only", - "maximum": 20000, - "minimum": 0, - "type": "integer" -} - removed
Input schema / properties / navigationRemoved value: -{ - "description": "Graph navigation mode for action=graph; defaults to ledger", - "enum": [ - "ledger", - "neighborhood", - "lineage", - "community", - "superseded" - ], - "type": "string" -} - removed
Input schema / properties / observation_idRemoved value: -{ - "description": "Observation id for lineage or superseded graph navigation", - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" -} - removed
Input schema / properties / projectRemoved value: -{ - "description": "Project name. Required except action=list and optional for action=topics or health", - "type": "string" -} - added
Input schema / properties / project_keyAdded value: +{ + "description": "Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content. Required for action=\"timeline\", \"briefing\", \"summaries\", or \"observations\"; not required for \"list\" or \"history\".", + "minLength": 1, + "type": "string" +} - removed
Input schema / properties / relationRemoved value: -{ - "description": "Graph relation filter for action=graph", - "enum": [ - "HAS_TYPE", - "IN_PROJECT", - "HAS_TOPIC_KEY", - "HAS_WHAT", - "HAS_WHY", - "HAS_WHERE", - "HAS_LEARNED" - ], - "type": "string" -} - added
Input schema / properties / root_session_keyAdded value: +{ + "description": "Optional session filter for action=\"briefing\", \"summaries\", or \"observations\"; supply with harness or omit both.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / sinceAdded value: +{ + "description": "Optional inclusive lower ISO-8601 instant for action=\"timeline\" only; must be <= until.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / stateAdded value: +{ + "description": "Optional state filter for action=\"observations\".", + "enum": [ + "pending", + "accepted", + "rejected", + "promoted" + ], + "type": "string" +} - added
Input schema / properties / temporalAdded value: +{ + "description": "Filter summaries/observations: current selects current summary versions or observation correction-chain leaves; history includes older summary versions or selects observation predecessors. Not accepted for action=\"timeline\".", + "enum": [ + "current", + "history" + ], + "type": "string" +} - removed
Input schema / properties / topic_keyRemoved value: -{ - "description": "Topic key for action=topic or graph filtering", - "type": "string" -} - added
Input schema / properties / untilAdded value: +{ + "description": "Optional inclusive upper ISO-8601 instant for action=\"timeline\" only; must be >= since.", + "minLength": 1, + "type": "string" +}
- Changed
mem_recall20 fields changed- added
Input schema / properties / budget_charsAdded value: +{ + "type": "number" +} - added
Input schema / properties / correlation_idAdded value: +{ + "type": "string" +} - removed
Input schema / properties / debugRemoved value: -{ - "description": "Include retrieval defaults and semantic input sources", - "type": "boolean" -} - added
Input schema / properties / finalize_answerAdded value: +{ + "type": "boolean" +} - removed
Input schema / properties / hydeRemoved value: -{ - "description": "Request HyDE query expansion when configured", - "type": "boolean" -} - removed
Input schema / properties / limit / descriptionRemoved value: -"Maximum evidence items (default: 5)" - removed
Input schema / properties / limit / maximumRemoved value: -20 - removed
Input schema / properties / limit / minimumRemoved value: -1 - changed
Input schema / properties / mode / descriptionPrevious value: -"compact returns evidence lines; context includes retrieved text"New value: +"compact (default) returns bounded snippets; context adds selected memory content." - removed
Input schema / properties / projectRemoved value: -{ - "description": "Optional project filter", - "type": "string" -} - added
Input schema / properties / project_keyAdded value: +{ + "description": "Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content.", + "minLength": 1, + "type": "string" +} - changed
Input schema / properties / query / descriptionPrevious value: -"Recall/search query"New value: +"Non-empty search string for promoted project memory." - removed
Input schema / properties / scopeRemoved value: -{ - "description": "Optional scope filter", - "enum": [ - "project", - "personal" - ], - "type": "string" -} - removed
Input schema / properties / session_idRemoved value: -{ - "description": "Optional session filter", - "type": "string" -} - added
Input schema / properties / temporalAdded value: +{ + "description": "current (default) searches current guidance; history includes historical records.", + "enum": [ + "current", + "history" + ], + "type": "string" +} - removed
Input schema / properties / time_fromRemoved value: -{ - "description": "Optional inclusive created_at lower bound", - "type": "string" -} - removed
Input schema / properties / time_toRemoved value: -{ - "description": "Optional inclusive created_at upper bound", - "type": "string" -} - removed
Input schema / properties / topic_keyRemoved value: -{ - "description": "Optional exact topic_key filter", - "type": "string" -} - removed
Input schema / properties / typeRemoved value: -{ - "description": "Optional observation type filter", - "enum": [ - "decision", - "architecture", - "bugfix", - "pattern", - "config", - "discovery", - "learning", - "session_summary", - "manual" - ], - "type": "string" -} - changed
Input schema / requiredPrevious value: -[ - "query" -]New value: +[ + "project_key", + "query" +]
- Changed
mem_save19 fields changed- removed
Input schema / properties / contentRemoved value: -{ - "description": "Memory content, prompt text, session summary, or text containing a Key Learnings section", - "type": "string" -} - added
Input schema / properties / event_keyAdded value: +{ + "description": "Stable event key for idempotency; required for observation, observation_review, observation_promotion, and evidence with metadata.", + "type": "string" +} - added
Input schema / properties / evidenceAdded value: +{ + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "content": { + "minLength": 1, + "type": "string" + }, + "kind": { + "enum": [ + "root_prompt", + "explicit_save", + "checkpoint", + "handoff", + "legacy_prompt", + "legacy_observation", + "session_summary" + ], + "type": "string" + }, + "source_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "content" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "content": { + "minLength": 1, + "type": "string" + }, + "kind": { + "const": "explicit_save", + "type": "string" + }, + "metadata": { + "additionalProperties": false, + "properties": { + "observation_validation": { + "additionalProperties": false, + "properties": { + "method": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "observation_id": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "result": { + "enum": [ + "passed", + "failed" + ], + "type": "string" + } + }, + "required": [ + "observation_id", + "result", + "method" + ], + "type": "object" + } + }, + "required": [ + "observation_validation" + ], + "type": "object" + }, + "source_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "content", + "metadata" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "content": { + "minLength": 1, + "type": "string" + }, + "kind": { + "const": "handoff", + "type": "string" + }, + "metadata": { + "additionalProperties": false, + "properties": { + "observation_review_attestation": { + "additionalProperties": false, + "properties": { + "method": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "observation_id": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "reviewer": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "verdict": { + "enum": [ + "accepted", + "rejected" + ], + "type": "string" + } + }, + "required": [ + "observation_id", + "verdict", + "reviewer", + "method" + ], + "type": "object" + } + }, + "required": [ + "observation_review_attestation" + ], + "type": "object" + }, + "source_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "content", + "metadata" + ], + "type": "object" + } + ], + "description": "Direct evidence { kind, content }; optionally add memory for a promoted save. Structured metadata forbids memory and requires event_key, root_session_key, and harness." +} - added
Input schema / properties / harnessAdded value: +{ + "description": "Native harness for root_session_key; supply both or omit both. Required wherever root_session_key is required.", + "enum": [ + "opencode", + "codex", + "claude", + "pi", + "mcp", + "cli", + "import" + ], + "type": "string" +} - removed
Input schema / properties / kindRemoved value: -{ - "description": "Write mode. Defaults to observation", - "enum": [ - "observation", - "prompt", - "session_summary", - "passive_learnings" - ], - "type": "string" -} - added
Input schema / properties / memoryAdded value: +{ + "additionalProperties": false, + "description": "Promoted memory for direct evidence only; requires evidence without metadata. Do not combine with observation, observation_review, or observation_promotion.", + "properties": { + "content": { + "minLength": 1, + "type": "string" + }, + "kind": { + "enum": [ + "decision", + "convention", + "architecture", + "discovery", + "failure", + "project_structure", + "handoff", + "preference" + ], + "type": "string" + }, + "outcome": { + "enum": [ + "unknown", + "succeeded", + "failed", + "mixed" + ], + "type": "string" + }, + "supersedes_id": { + "type": "string" + }, + "title": { + "minLength": 1, + "type": "string" + }, + "topic_key": { + "type": "string" + } + }, + "required": [ + "kind", + "title", + "content" + ], + "type": "object" +} - added
Input schema / properties / observationAdded value: +{ + "additionalProperties": false, + "description": "Submit a supported candidate without promotion; requires event_key. Session scope also requires root_session_key, harness, and coverage.", + "properties": { + "claim": { + "maxLength": 4000, + "minLength": 1, + "type": "string" + }, + "concepts": { + "items": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "type": "array" + }, + "coverage": { + "additionalProperties": false, + "properties": { + "from_sequence": { + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "to_sequence": { + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + } + }, + "required": [ + "from_sequence", + "to_sequence" + ], + "type": "object" + }, + "files": { + "items": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "type": "array" + }, + "generator": { + "additionalProperties": false, + "properties": { + "config_hash": { + "pattern": "^[0-9a-f]{64}$", + "type": "string" + }, + "kind": { + "enum": [ + "root_agent", + "harness", + "model" + ], + "type": "string" + }, + "name": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "version": { + "maxLength": 200, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "kind", + "name" + ], + "type": "object" + }, + "kind": { + "enum": [ + "decision", + "constraint", + "fact", + "procedure", + "result", + "failure", + "preference" + ], + "type": "string" + }, + "predecessor_id": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "proposed_memory": { + "additionalProperties": false, + "properties": { + "content": { + "minLength": 1, + "type": "string" + }, + "kind": { + "enum": [ + "decision", + "convention", + "architecture", + "discovery", + "failure", + "project_structure", + "handoff", + "preference" + ], + "type": "string" + }, + "outcome": { + "enum": [ + "unknown", + "succeeded", + "failed", + "mixed" + ], + "type": "string" + }, + "title": { + "minLength": 1, + "type": "string" + }, + "topic_key": { + "type": "string" + } + }, + "required": [ + "kind", + "title", + "content" + ], + "type": "object" + }, + "scope": { + "enum": [ + "session", + "project" + ], + "type": "string" + }, + "support_ids": { + "items": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "minItems": 1, + "type": "array" + }, + "title": { + "maxLength": 500, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "kind", + "scope", + "title", + "claim", + "proposed_memory", + "support_ids", + "generator" + ], + "type": "object" +} - added
Input schema / properties / observation_promotionAdded value: +{ + "additionalProperties": false, + "description": "Promote one accepted observation without new prose; requires event_key, root_session_key, and harness. Send no other operation branch or memory.", + "properties": { + "observation_id": { + "maxLength": 200, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "observation_id" + ], + "type": "object" +} - added
Input schema / properties / observation_reviewAdded value: +{ + "additionalProperties": false, + "description": "Review one supported observation; requires event_key, root_session_key, and harness. Send no other operation branch or memory.", + "properties": { + "basis": { + "enum": [ + "root_user_confirmed", + "observable_validation", + "independent_review" + ], + "type": "string" + }, + "observation_id": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "policy": { + "additionalProperties": false, + "properties": { + "id": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "version": { + "maxLength": 200, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "id", + "version" + ], + "type": "object" + }, + "reason": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + "support_ids": { + "items": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "minItems": 1, + "type": "array" + }, + "verdict": { + "enum": [ + "accepted", + "rejected" + ], + "type": "string" + } + }, + "required": [ + "observation_id", + "verdict", + "basis", + "policy", + "reason", + "support_ids" + ], + "type": "object" +} - removed
Input schema / properties / projectRemoved value: -{ - "description": "Project name", - "type": "string" -} - added
Input schema / properties / project_keyAdded value: +{ + "description": "Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / project_nameAdded value: +{ + "description": "Creation/display metadata only; never participates in project identity equality. Prefer the database-persisted name returned by lifecycle or project output.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / root_session_keyAdded value: +{ + "description": "Verified root session key; supply with harness or omit both. Required for session-scoped observations, observation_review, observation_promotion, and evidence with metadata; blank counts as absent.", + "type": "string" +} - removed
Input schema / properties / scopeRemoved value: -{ - "description": "Observation scope", - "enum": [ - "project", - "personal" - ], - "type": "string" -} - removed
Input schema / properties / session_idRemoved value: -{ - "description": "Session ID (default: manual-save-{project})", - "type": "string" -} - removed
Input schema / properties / titleRemoved value: -{ - "description": "Short searchable title. Required for kind=observation", - "type": "string" -} - removed
Input schema / properties / topic_keyRemoved value: -{ - "description": "Stable key for observation upserts", - "type": "string" -} - removed
Input schema / properties / typeRemoved value: -{ - "description": "Observation category for kind=observation", - "enum": [ - "decision", - "architecture", - "bugfix", - "pattern", - "config", - "discovery", - "learning", - "session_summary", - "manual" - ], - "type": "string" -} - changed
Input schema / requiredPrevious value: -[ - "content" -]New value: +[ + "project_key", + "project_name" +]
- Changed
mem_session17 fields changed- removed
Input schema / properties / actionRemoved value: -{ - "description": "Session action", - "enum": [ - "start", - "summary", - "checkpoint" - ], - "type": "string" -} - removed
Input schema / properties / content / descriptionRemoved value: -"Full session summary for action=summary" - removed
Input schema / properties / directoryRemoved value: -{ - "description": "Working directory for action=start", - "type": "string" -} - added
Input schema / properties / event_keyAdded value: +{ + "description": "Stable lifecycle event key; retries for the same operation must resend identical content/summary.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / harnessAdded value: +{ + "description": "Verified native harness for root_session_key in project_key.", + "enum": [ + "opencode", + "codex", + "claude", + "pi", + "mcp", + "cli", + "import" + ], + "type": "string" +} - removed
Input schema / properties / idRemoved value: -{ - "description": "Session ID. Required for action=start; defaults to manual-save-{project} for summary/checkpoint", - "type": "string" -} - added
Input schema / properties / operationAdded value: +{ + "description": "Lifecycle operation; summary is allowed only for checkpoint_pre_compact (checkpoint) or finalize (final).", + "enum": [ + "enroll", + "recover", + "capture_root", + "checkpoint_pre_compact", + "guide_post_compact", + "finalize" + ], + "type": "string" +} - removed
Input schema / properties / projectRemoved value: -{ - "description": "Project name", - "type": "string" -} - added
Input schema / properties / project_keyAdded value: +{ + "description": "Exact opaque project_key copied verbatim from verified native identity; never derive it from a display name, path hint, remote, branch, worktree name, host ID, listing, or recalled content.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / project_nameAdded value: +{ + "description": "Creation/display metadata only; never participates in project identity equality. Prefer the database-persisted name returned by lifecycle or project output.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / root_session_keyAdded value: +{ + "description": "Stable verified root session key; required with harness for every operation.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / summary / additionalPropertiesAdded value: +false - changed
Input schema / properties / summary / descriptionPrevious value: -"Short checkpoint summary for action=checkpoint"New value: +"Optional only for operation=\"checkpoint_pre_compact\" (kind=\"checkpoint\") or operation=\"finalize\" (kind=\"final\"). coverage starts at 1 and to_sequence must advance the current summary for this session and kind. support_ids must be evidence ids from this project_key + root_session_key/harness session inside coverage. Canonical submission limit: 20000 UTF-16 units." - added
Input schema / properties / summary / propertiesAdded value: +{ + "claims": { + "description": "1-32 atomic supported claims; keep the canonical summary within 20000 UTF-16 units.", + "items": { + "additionalProperties": false, + "properties": { + "content": { + "description": "Atomic claim content; at most 2000 code points after privacy filtering.", + "minLength": 1, + "type": "string" + }, + "kind": { + "enum": [ + "objective", + "completed", + "decision", + "changed_surface", + "verification", + "pending", + "blocker", + "next_action" + ], + "type": "string" + }, + "outcome": { + "enum": [ + "unknown", + "succeeded", + "failed", + "mixed" + ], + "type": "string" + }, + "support_ids": { + "description": "1-16 distinct evidence ids from this project_key + root_session_key/harness session inside summary.coverage; never memory, summary, or observation ids.", + "items": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "kind", + "content", + "support_ids" + ], + "type": "object" + }, + "maxItems": 32, + "minItems": 1, + "type": "array" + }, + "coverage": { + "additionalProperties": false, + "description": "Inclusive session evidence coverage; start at 1 and advance to_sequence for this session and summary kind.", + "properties": { + "from_sequence": { + "description": "Inclusive first session event sequence; must start at 1.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "to_sequence": { + "description": "Inclusive last session event sequence; must be >= from_sequence and exceed the current summary ending sequence for this session and kind.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + } + }, + "required": [ + "from_sequence", + "to_sequence" + ], + "type": "object" + }, + "generator": { + "additionalProperties": false, + "properties": { + "config_hash": { + "pattern": "^[0-9a-f]{64}$", + "type": "string" + }, + "kind": { + "enum": [ + "root_agent", + "harness", + "model" + ], + "type": "string" + }, + "name": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "version": { + "maxLength": 200, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "kind", + "name" + ], + "type": "object" + }, + "kind": { + "description": "Send checkpoint for operation=\"checkpoint_pre_compact\" or final for operation=\"finalize\".", + "enum": [ + "checkpoint", + "final" + ], + "type": "string" + } +} - added
Input schema / properties / summary / requiredAdded value: +[ + "kind", + "coverage", + "generator", + "claims" +] - changed
Input schema / properties / summary / typePrevious value: -"string"New value: +"object" - changed
Input schema / requiredPrevious value: -[ - "action", - "project" -]New value: +[ + "operation", + "harness", + "project_key", + "project_name", + "root_session_key", + "event_key" +]
5 tool updates
v0.4.13- Added
mem_context - Added
mem_get - Added
mem_project - Added
mem_save - Added
mem_session
5 tool updates
v0.4.1- Removed
mem_context - Removed
mem_get - Removed
mem_project - Removed
mem_save - Removed
mem_session
6 tool updates
v0.3.7- First observed
mem_context - First observed
mem_get - First observed
mem_project - First observed
mem_recall - First observed
mem_save - First observed
mem_session
TDQS
Scored across 6 tools
Write vs. read paths are distinguishable (mem_save, mem_session vs. recall/get/context/project), but the read surface overlaps heavily: mem_context, mem_recall, mem_project, and mem_get all retrieve memory/continuity, and the dense, clause-heavy descriptions are what carry the distinction. An agent could plausibly choose the wrong retrieval tool without careful reading.
All six tools share a clean mem_ prefix and snake_case, which is highly predictable. However, the stems mix verbs (save, recall, get) with nouns (context, project, session), so the pattern is prefix-consistent rather than a strict verb_noun scheme.
Six tools for a memory/continuity server is well-scoped: write (mem_save, mem_session), search/expand (mem_recall, mem_get), context assembly (mem_context), and inspection (mem_project). Each tool covers a distinct capability and none feels redundant in count alone.
The surface covers create, search, expand, context, and project inspection, but there is no update, edit, forget, or delete operation for memories—only new saves and historical lineage. Agents cannot correct or remove a bad memory, which is a notable lifecycle gap for a memory store.
Maintenance
Related MCP Connectors
Persistent memory for AI agents. Search, store, and recall across sessions.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Persistent memory for AI agents. Search and store durable facts, preferences and decisions.
Persistent cross-session memory shared by Codex, Claude Code, ChatGPT, and other AI agents.
Related MCP Servers
- 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
- AlicenseNot gradedqualityDmaintenanceProvides AI coding assistants with persistent project memory to retain architectural decisions, code patterns, and domain knowledge across sessions. It stores data locally in a SQLite database, allowing agents to remember, recall, and manage project-specific context using full-text search.4 npmApache 2.0
- AlicenseNot gradedqualityCmaintenanceGives AI coding agents persistent memory by storing observations, decisions, and learnings in a local SQLite database with vector search, full-text search, and a rules engine.4MIT
- AlicenseAqualityAmaintenanceLocal-first memory for AI coding agents using SQLite, enabling persistent recall of decisions, lessons, and project context without cloud or API keys.10158 PyPI285Apache 2.0