Skip to main content
Glama

sessionmem

Project memory between sessions, stored on your machine.

New session. Claude starts fresh.

WITHOUT sessionmem:
  You explain the stack. The JWT bug from last week.
  The Stripe migration that's halfway done. The billing code to stay away from.
  Same questions. Different day.

WITH sessionmem:
  [warning] JWT blacklist must be checked before issuing new tokens. Fixed PR #47.
  [decision] Stripe migration ~50% done. Do NOT use /lib/billing-v1.
  [fact] Stack: TypeScript, Next.js, Postgres.

  Claude: "Looks like you're mid-Stripe migration. Where do you want to pick up?"

sessionmem is an MCP server that stores decisions, warnings, and project context across sessions. Claude Code hooks capture supported tool events and load relevant memories automatically. Other hosts use its MCP tools and installed instructions; session automation depends on the host. It works with Claude Code, Cursor, Cline, Codex, Windsurf, and other MCP hosts.

Default retrieval uses SQLite FTS5 BM25 and entity overlap. An optional local MiniLM model adds semantic candidates. Weights are installed separately; queries make no network calls and fall back to BM25 when local inference is unavailable. See measured comparisons for quality gains, missed questions, and latency costs.

By default, everything stays on your machine. You don't need an account or a cloud service. Data only leaves your computer if you enable sharing or cloud summarization.


Quickstart

You need a terminal (Command Prompt, Terminal, or PowerShell) and Node.js, version 20.19+ on the Node 20 line, or 22.13+. Node 22 LTS is recommended. No programming experience is required.

1. Install sessionmem

npm install -g sessionmem

2. Register it with your AI tool

Run this in your project folder after configuring your AI tool (Claude Code, Cursor, etc.):

sessionmem install
# Optional: select one host explicitly, including in automation:
sessionmem install --adapter claude-code
# Other names: cursor, cline, codex, windsurf, antigravity, qcoder, generic

install detects installed hosts from local executables, including from a plain terminal, and configures every host found. Automatic discovery currently supports Claude Code on PATH or in its standard native install locations. Use --adapter <name> for the other adapters or to override discovery. The existing SESSIONMEM_ADAPTER environment override also works; the flag takes precedence. If no supported host is found, the command says so and exits nonzero before creating files. Discovery and configuration work fully offline.

This initializes the database and configures the selected adapters:

  • Registers sessionmem with your AI tool's MCP host so the host can start it automatically.

  • Creates ~/.sessionmem/config.json with secret redaction enabled and a 90-day retention window, if the file doesn't already exist.

  • Adds instructions to the selected host's guidance file, such as ~/.claude/CLAUDE.md for Claude Code or ~/.codex/AGENTS.md for Codex. You can re-run the command without duplicating those instructions.

  • Installs Claude Code's SessionStart, SessionEnd, and PostToolUse hooks and prints what was configured per host. If a host fails, the remaining hosts are still attempted and the command exits nonzero.

  • Enables and starts one per-user login service for sessionmem watch. Re-running install updates that registration in place and restarts capture. Capture continues after closing the terminal and starts again at login.

Login capture uses a LaunchAgent in ~/Library/LaunchAgents on macOS, a systemd --user service on Linux, and a Scheduled Task with a user logon trigger on Windows. Linux requires systemd and an available user service manager; macOS requires a GUI login session. If registration or startup fails, install exits nonzero, preserves completed setup, and prints a repair hint. After fixing the OS service error, run sessionmem autostart enable.

The watcher captures existing and updated Claude Code, Codex CLI, and Cursor history offline, without API keys. It starts immediately after install; no manual scan or watch process is required. Hosts outside these three can use MCP memory tools, but do not have a transcript reader.

3. Restart your AI tool

Restart your editor or agent so it loads the MCP registration. Your host starts sessionmem run automatically; running it directly starts a stdio server that waits for MCP messages, so it can appear to hang in a terminal. For an unknown host (generic), install writes a project-local .mcp.json; if your host uses another format or location, copy its server entry into that host’s MCP config.

After restarting:

  • In Claude Code, the installed PostToolUse, SessionEnd, and SessionStart hooks capture supported tool events, summarize them, and load prior memories automatically.

  • Codex and Cursor use the auto-started watcher for transcript capture. Install does not wire lifecycle capture hooks for these hosts. Their MCP tools and installed instructions provide recall and explicit memory operations.

  • Other MCP hosts use sessionmem's tools and installed instructions; automatic transcript capture requires a supported transcript reader.

Check the installation offline:

sessionmem doctor
# For an explicitly selected host:
sessionmem doctor --adapter claude-code

Related MCP server: codemem

Table of Contents


What problem does this solve?

Most AI coding assistants rely on the current conversation for context. Start a new session and you may need to explain the project's setup, libraries, fixed bugs, and design decisions again.

sessionmem keeps short notes between sessions:

  1. While you work, it captures session events.

  2. At session end, it summarizes decisions, warnings, and useful facts into stored memories.

  3. At the next session start, it loads the most relevant memories within a small token budget.

Claude Code runs these steps through the installed hooks. Other hosts need their agent to call the MCP memory and lifecycle tools; the installed guidance explains how to do that.


How is sessionmem different?

Compared with projects such as claude-mem and other cloud or Claude-only memory tools, sessionmem focuses on local storage and support for multiple MCP hosts:

sessionmem

Typical cloud/Claude-only memory tools

Where is data stored?

A single SQLite file on your computer (~/.sessionmem/memories.db)

Often a hosted service, a cloud vector database, or a separate server process you have to run

Account / sign-up required?

No

Sometimes

Which AI tools does it work with?

Claude Code, Cursor, Codex, Cline, Windsurf, Antigravity, QCoder, and any other MCP-compatible host

Usually just one specific tool (commonly Claude Code only)

Secret redaction

Built in, on by default. API keys, tokens, passwords, and private keys are scrubbed before anything is saved.

Often not handled, or left to the user

Token budget control

Injected memories are trimmed to a small, fixed token budget (see benchmarks below)

Varies, often unbounded

Entity boost (optional)

Case-insensitive names and explicit aliases add a bounded score boost alongside relevance, recency and importance. Local only, defaults off.

Varies

Scopes

Optional local context labels on sessions, memories and entity associations. Capture detects a directory or project label; queries can filter or boost a selected scope. All scopes by default.

Varies

Old/stale memory cleanup

Built-in retention policy automatically prunes old memories (configurable, on by default)

Often no automatic cleanup ("memory rot")

Team sharing

Optional, via a shared folder you already control (network drive, synced directory). No server needed.

Usually requires a shared hosted backend

Offline-capable

Yes. Works with no network connection by default.

Usually requires network access to the memory service

The SQLite file is easy to inspect, back up, or delete, and you can use it across AI tools from different vendors.


Benchmark results

npm run benchmark evaluates conversational retrieval on the committed LoCoMo corpus: 10 conversations, 272 sessions, 5,882 turns, and 1,527 scored questions. It captures dialogue through the public storeMemory API and asks the original questions through retrieveMemories, fully offline with no API keys.

The evaluation reports hit rate, precision, recall, complete-evidence retrieval, and latency. Production retrieval uses offline BM25 ranking with English stemming; conversational questions test recall beyond exact copies of memory text. See benchmark results and the methodology, dataset license, and metric definitions.

npm run build
npm run benchmark
npm run benchmark -- --output benchmarks/results/locomo.json

How it works (in plain English)

        ┌──────────────────────────────────────────────┐
        │                  Your AI tool                 │
        │   (Claude Code, Cursor, Codex, Cline, ...)    │
        └───────────────────────┬──────────────────────┘
                                 │
                     ┌───────────▼───────────┐        ┌──────────────┐
                     │   sessionmem adapter   │        │ sessionmem   │
                     │ (translates for your   │        │     CLI      │
                     │   specific AI tool)    │        │ (you type    │
                     └───────────┬───────────┘        │  commands)   │
                                 │                     └──────┬───────┘
                                 ▼                            │
                     ┌──────────────────────────────────────────────┐
                     │              sessionmem core engine           │
                     │  watches sessions · writes summaries ·        │
                     │  finds relevant memories · trims to fit       │
                     └───────────────────────┬──────────────────────┘
                                              │
                                              ▼
                     ┌──────────────────────────────────────────────┐
                     │         One SQLite file on your computer      │
                     │     ~/.sessionmem/memories.db                 │
                     └──────────────────────────────────────────────┘
  • Adapters connect each AI tool to sessionmem. Supporting another tool doesn't require changing the memory engine.

  • The core engine stores memories, ranks their relevance, and selects what fits in the next session's context budget. Every adapter uses the same engine.

  • The database is a local file. You can back it up, move it, inspect it, or delete it.

See docs/architecture.md for the technical overview.


CLI command reference

Command

What it does

sessionmem install [--adapter <name>]

Detect installed hosts, configure integrations, write default config, and enable login capture; the flag selects one host.

sessionmem doctor [--adapter <name>]

Check the store, schema, auto-start, binary paths, capture freshness, transcript discovery, hooks, MCP wiring, and canary recall offline; print PASS/FAIL and repair hints.

sessionmem autostart enable|disable|status

Start login capture, stop and unregister it, or inspect its registration and binary paths.

sessionmem uninstall [--adapter <name>] [--purge]

Stop and unregister login capture, then remove sessionmem from the selected host. --purge also deletes the local database.

sessionmem run

Start the MCP server.

sessionmem ui [--port N]

Open the local read-only web viewer (default port 3777).

sessionmem serve --api [--port N]

Start the local single-user REST API (default port 3778).

sessionmem ping

Check the local version and database reachability.

sessionmem search <query> [--limit <n>] [--include-history]

Search current memories by text query (limit 1–100, default 10). Include superseded facts with --include-history.

sessionmem list

List up to 200 recent memories for the current project; warns when truncated.

sessionmem entities [--project <id>] [--json]

List extracted entities, typed relations, and their source memory IDs. Defaults to the current project.

sessionmem history [--project <id>] [--json]

List supersession chains with old/new values, source memory IDs, reasons, and timestamps.

sessionmem show <id>

Show memory details (content capped at 2000 characters; use export for full content).

sessionmem forget <id> [--force]

Delete a memory by ID.

sessionmem export [path]

Export all current-project memories to JSON (default ~/.sessionmem/export-YYYY-MM-DD.json).

sessionmem import <path> [--merge]

Import up to 1000 valid records from UTF-8 JSON into the current project. Existing IDs are preserved, including with --merge; invalid records are skipped with warnings.

sessionmem scan [--host <host>] [--transcripts-dir <path>]

Import existing Claude Code, Codex CLI, and Cursor transcripts into local session memories. Reports files found, sessions imported, memories created, skips, and errors.

sessionmem watch [--once] [--interval <seconds>] [--host <host>] [--transcripts-dir <path>]

Capture new or updated Claude Code, Codex CLI, and Cursor transcripts. Polls every 5 seconds by default; --once runs a single sweep.

sessionmem stats

Show memory statistics for the current project.

sessionmem savings [--json]

Show token savings from compression and injection, with percentage.

sessionmem redact-scan [--apply]

Scan stored memories for secrets; --apply redacts in place.

sessionmem retention prune [--force] [--days <n>]

Prune old memories (dry-run by default).

sessionmem config get <key> / config set <key> <value>

Read and write policy config.

sessionmem team enable <path> / team disable [--remove-team-memories] / team status

Manage shared-path team memory mode.

sessionmem sync

Push local memories and pull teammate memories via the shared path.

sessionmem browse [--project <id>]

List projects or preview up to 50 recent memories from one project.

sessionmem dedupe [--apply] [--threshold <n>]

Preview duplicate memories; --apply deletes them (threshold >0–1, default 0.85).

sessionmem re-embed

Refresh memories with stale embedding versions.

sessionmem session-start

Print prior context as Claude Code SessionStart hook JSON.

sessionmem ingest-hook

Read a Claude Code PostToolUse JSON payload from stdin and capture supported tool events.

sessionmem session-end

Summarize ingested events and apply retention pruning; reads the hook session ID from stdin.

Use sessionmem --help or sessionmem <command> --help for options, and sessionmem --version for the installed version. Destructive commands require --force, --apply, or --purge as shown above. team disable preserves teammate memories unless --remove-team-memories is passed.

The default database is ~/.sessionmem/memories.db. Set SESSIONMEM_DB_PATH to use another file; its parent directories are created automatically and the default directory is not created by database commands. Server logs are written to logs/mcp.log beside the selected database (disabled for :memory:). Config remains at ~/.sessionmem/config.json. uninstall --purge deletes the selected database. Quote paths containing spaces (for example "C:\Users\Ada Lovelace\memory.db" on Windows). In JSON config files, use forward slashes or escaped backslashes for Windows paths. Imports accept CRLF and a UTF-8 BOM; convert other encodings to UTF-8.

SESSIONMEM_PROJECT_ID pins the project bucket (useful when moving a repository); otherwise it is derived from the repository root or working directory. SESSIONMEM_ADAPTER selects the install/doctor/uninstall host unless --adapter is set. SESSIONMEM_DEBUG=1 enables ingest-hook diagnostics on stderr.

Local REST API and JavaScript client

sessionmem serve --api
curl 'http://127.0.0.1:3778/v1/search?query=database&limit=5'

This is a local single-user API, not a hosted service. It binds to 127.0.0.1 and uses the current repository's project, including SESSIONMEM_PROJECT_ID overrides. It supports compact search, timelines, full details, saves and deletes through the same service methods as MCP. Other projects cannot be selected by a request. Set SESSIONMEM_API_TOKEN or --token to require bearer authentication on every route. Cross-origin browser requests and unexpected Host headers are rejected. Non-loopback binds require --allow-remote and print a warning.

import { SessionmemClient } from "sessionmem/client";
const client = new SessionmemClient("http://127.0.0.1:3778");
const index = await client.searchMemoryIndex({ query: "database", limit: 5 });
if (index.memories.length) console.log(await client.getMemory(index.memories[0].id));

The fetch client includes TypeScript declarations and adds no runtime dependencies. See API documentation for authentication, limits, all client methods and curl examples.

Inspect memories in your browser

sessionmem ui
sessionmem ui --port 8080
sessionmem ui --port 0  # Pick an available port

The command prints its URL and opens your default browser. It binds only to 127.0.0.1, needs no authentication, and serves all assets locally using Node's built-in HTTP server. No external services, CDNs, or additional runtime dependencies are used. If browser launch is unavailable, open the printed URL manually. Press Ctrl-C to stop the server and close its database connection.

The viewer starts on the current project, with a selector for other projects in the same store. Browse saved memories, search through the existing recall path, inspect extracted entities and relations with their source memories, and follow supersession chains with old/new values, source IDs, assertion times, detection times, and partial/full status. Search returns up to 50 results and defaults to current facts; select Include superseded facts in search to recall history. Browsing lists all saved records, including superseded and expired ones, in pages of 50. Source IDs open full memory details. Entity visibility and history links use the same rules as sessionmem entities and sessionmem history.

The database is opened read-only. Browsing and on-demand search do not increment access counts, migrate the schema, or change memories. Only HTTP GET and HEAD are accepted; no write, delete, or edit routes are exposed. Responses are not cached, and cross-origin browser requests and unexpected Host headers are rejected. Run sessionmem ping first to initialize a missing store or upgrade an older schema. The usual SESSIONMEM_DB_PATH and SESSIONMEM_PROJECT_ID overrides apply. Anyone with access to this computer can read the local viewer while it is running; stop it when finished inspecting private memories.

Import existing sessions and watch for new ones

When a fact changes, sessionmem can link its replacement locally. For example, “I use VS Code” followed by “I switched to Neovim” supersedes the earlier editor choice. Recall excludes fully superseded memories by default. retrieveMemories accepts the optional includeHistory: true; sessionmem search --include-history searches earlier facts too. sessionmem history shows what replaced what. The old memory stays available through show, list, and export.

Detection uses deterministic entity/relation rules, shared purpose words, a small tool-category vocabulary, and explicit negation or replacement phrases. It needs no API or model. Unfamiliar wording can be missed, and ambiguous changes can be misclassified. A memory with independent claims remains searchable while any claim is current; history labels these partial supersessions. See supersession details.

Install starts capture for existing history and new sessions automatically. For a manual import or a foreground diagnostic run:

sessionmem scan
sessionmem watch --once
sessionmem watch --interval 10
sessionmem scan --host cursor

Both commands sweep all detected transcript histories by default:

  • Claude Code: ~/.claude/projects/**/*.jsonl.

  • Codex CLI: ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl.

  • Cursor: User/globalStorage/state.vscdb under ~/Library/Application Support/Cursor on macOS, ~/.config/Cursor on Linux, or %APPDATA%/Cursor on Windows.

Missing history directories are allowed. Use --transcripts-dir "/path/to/history" to select another transcript tree; each JSONL file's host is detected from its records. For Cursor, the override accepts its User directory or a state.vscdb path. Use --host cursor, --host codex, or --host claude-code to select one host, including when using an override. A Cursor User directory or .vscdb file is also detected without --host. Files that do not match a supported format, or the selected host, produce an explicit unsupported format error.

Both commands work offline without API keys and always use the local summarizer, even if cloud summarization is enabled elsewhere. sessionmem doctor checks transcript discovery for all three hosts, parses JSONL samples, and validates Cursor's composer indexes and message rows when history is present.

Transcript user/assistant text, supported Claude tool uses (Bash, Edit, Write, MultiEdit), and Codex function calls pass through the existing event-ingestion, redaction, and session-summary pipeline. Codex tool events retain the native tool name and call_id. Encrypted agent_message payloads and obvious injected machine blocks, including plugin catalogues and environment context, are excluded. Each session gets one summary memory, including short sessions with only one event. Updated sessions refresh that summary. Project buckets come from each Claude transcript's cwd, Codex session_meta.payload.cwd, or Cursor's workspace path, using the repository root when available; the directory where you run scan/watch does not select the project. SESSIONMEM_PROJECT_ID can explicitly pin all imports to one bucket. Transcripts without capturable events are skipped. Claude transcripts without a working directory are also skipped; Codex session metadata must contain an ID and working directory. Nested subagent files get separate session summaries. Summary memories record sourceAdapter as claude-code, codex, or cursor according to the transcript host. Cursor session IDs come from composerId.

Cursor stores messages in cursorDiskKV bubble rows in its global SQLite database. The importer supports workspace composer.composerData indexes (Cursor 2.6 and earlier) and the central composer.composerHeaders index (Cursor 3.0 and later). It captures up to 4,000 characters of user/assistant text per bubble and excludes tool-only bubbles and internal tool/code fields. Missing tables, index keys, or required conversation data produce an explicit unsupported format for cursor error.

Cursor databases are never written. Each sweep copies the database and its WAL to a private temporary directory, checking for concurrent changes during the copy. SQLite opens the copy read-only, using immutable mode when URI support is available and there is no WAL to replay. Cursor's live database is never opened by SQLite. Busy copies are reported and retried. Each sweep reads a fresh snapshot; per-composer checkpoints skip unchanged messages, and streamed bubble updates refresh the existing event without duplicating it.

Codex resumes create new rollout files. Files with the same session ID are grouped, and replayed events are deduplicated across files, sweeps, and restarts. A Codex sub-agent keeps its own session_meta.payload.id, even when parent_thread_id points to a parent session.

Re-running either command does not duplicate memories or transcript events. File and composer checkpoints live in the selected memory database, and unchanged files or composers are skipped across restarts. For Cursor, files found counts global databases, and skipped counts unchanged or empty composers. Stable event IDs also make interrupted imports safe to retry. Partial or malformed JSONL lines are reported and retried on later sweeps; valid events in the same file can still be captured. A single sweep exits with status 1 if it encounters errors. The daemon keeps running and retries errors.

watch prints its first sweep and subsequent imports or errors. A manual run stays in the foreground until SIGINT or SIGTERM. Login capture uses the same watcher with an absolute Node executable and absolute sessionmem entry point; it does not need a shell, a TTY, or your interactive PATH.

Control login capture explicitly:

sessionmem autostart status
sessionmem autostart disable
sessionmem autostart enable

enable updates one registration and starts capture immediately. disable stops the registered watcher and removes its login registration, preserving memories. The next sessionmem install enables it again. This control affects the login watcher; Claude Code hooks and explicit MCP memory tools remain active.

Registrations:

OS

Registration

macOS

~/Library/LaunchAgents/io.sessionmem.watch.plist

Linux

~/.config/systemd/user/sessionmem-watch.service

Windows

Scheduled Task sessionmem-watch-<user-home-hash>, for the current user only

Capture output and failures are appended with timestamps to logs/watch.log beside the selected database (default ~/.sessionmem/logs/watch.log). The watcher also writes memories.db.watch-checkpoint.json beside the default store after each completed sweep. Doctor checks this checkpoint's age, capture errors, and transcript checkpoint count; unchanged history and an empty history are healthy when the watcher continues completing sweeps. A checkpoint older than two minutes fails the default 5-second watcher check. For a custom polling interval, the limit is the greater of two minutes and three intervals.

SESSIONMEM_DB_PATH selected at install or enable is saved as an absolute watcher argument. Run enable with that variable again to switch stores. The policy config remains ~/.sessionmem/config.json. After moving sessionmem or changing Node versions, run sessionmem autostart enable to update the absolute paths. For failures before the watcher can open its log, inspect launchctl print gui/<uid>/io.sessionmem.watch, journalctl --user -u sessionmem-watch.service, or Windows Task Scheduler's task history.

Uninstall

sessionmem uninstall --adapter claude-code
# Also delete the selected memory database:
sessionmem uninstall --adapter claude-code --purge

Uninstall stops capture and removes the login registration before removing MCP configuration, Claude hooks, and agent guidance for the selected host. It keeps the database, config and logs by default. Use the same SESSIONMEM_DB_PATH as install when selecting a custom database to purge. If stopping or unregistering the watcher fails, uninstall reports the OS error and leaves the database intact. For multiple installed hosts, repeat uninstall with each adapter to remove its MCP configuration and guidance.


Privacy, secrets, and your data

Storage, retrieval, and summarization run locally by default. There is no account, telemetry, or hosted memory service. Settings live in ~/.sessionmem/config.json.

Secrets are scrubbed automatically

Before saving memory content, sessionmem replaces common secret patterns with REDACTED:

  • Email addresses

  • API keys (sk-..., AWS AKIA..., GitHub ghp_.../gho_..., etc.)

  • Bearer tokens and JWTs

  • Private key blocks (-----BEGIN ... PRIVATE KEY-----)

  • Connection-string style secrets (password=..., secret=...)

Redaction is on by default. To scan and clean up older memories:

sessionmem redact-scan          # see what would be redacted
sessionmem redact-scan --apply  # actually redact in place

Full details: docs/privacy-and-retention.md.


Memory rot: keeping memory accurate over time

Old decisions and duplicate facts can accumulate in a memory store, causing the assistant to use outdated information. This is sometimes called "memory rot."

sessionmem handles it through retention, ranking, and sync rules:

  1. Retention pruning: memories older than a configurable window (90 days by default) are eligible for deletion. A lightweight check runs at session end. You can also run it manually:

    sessionmem retention prune          # dry run - shows what *would* be deleted
    sessionmem retention prune --force  # actually deletes
  2. Importance-weighted ranking: retrieval ranks memories by offline BM25 lexical relevance, entity overlap, recency, and importance. Older, less important notes rank lower even before they are pruned.

  3. Token-budgeted injection: only the highest-ranked memories are loaded, trimmed to a small token budget (see benchmarks). The context stays within that budget as the store grows.

  4. Conflict resolution in team mode: merging teammate memories uses last-write-wins by id to avoid stale duplicates and keeps the higher importance score so a warning isn't downgraded.

The conversational benchmark measures retrieval quality separately from retention and startup token budgets.

Export your memories before pruning if you want to keep a copy:

sessionmem export

Team mode (optional)

To share decisions and warnings across your team's AI assistants, point sessionmem at a folder everyone can read and write, such as a network drive or synced directory:

sessionmem team enable <shared-path>
sessionmem sync
  • Team mode is off by default. Nothing is shared until you enable it.

  • Memories are shared as files in that folder; no server is needed.

  • Teammate memories appear with an author: prefix identifying their source.

  • Redaction runs on every pulled memory using your redaction policy.

Full details, including the trust model: docs/team-mode.md.


Cloud summarization (optional, off by default)

By default, session summaries are created locally, with no API calls.

To use Claude's API for higher-quality summaries, set allowCloudSummarization=true and provide an ANTHROPIC_API_KEY. If cloud summarization fails after retries, sessionmem uses local summarization. Failures are recorded for diagnosis; see the configuration guide below.

Details: docs/cloud-summarization.md.


Automatic memory by host

After installation, the login-started watcher captures supported local transcripts. Recall on hosts without native hooks follows installed agent instructions, so it depends on the agent executing the memory tools.

Host

Capture

Recall

Claude Code

Tool/end hooks and transcript watcher

SessionStart and UserPromptSubmit hooks inject context

Codex

Rollout watcher

Global AGENTS.md and MCP instructions require startup and new-topic searches

Cursor

Composer SQLite watcher

Project always-apply rule and MCP instructions require searches

Windsurf, Cline

Instructed agent saves; no transcript importer

Installed rules and MCP instructions

Antigravity, QCoder

Instructed saves; native adapter paths remain unverified

Instruction-driven, subject to host loading

Generic MCP

Instructed saves if the host reads AGENTS.md or MCP instructions

Instruction-driven, subject to host support

Install detects available Claude Code, Codex, Cursor and Windsurf CLI executables. Other hosts use --adapter at setup. Missing guidance now fails installation. Doctor checks capture and recall separately, identifies instruction-driven modes, and provides repair hints. See automatic memory for exact scope, supported formats, tool permissions and the CI install-to-recall test.

Memory retrieval tools

Use searchMemoryIndex for a compact list of matches, memoryTimeline to inspect nearby records, and getMemory for selected full details. Compact tools default to 10 results and cap one-line summaries at 160 characters. See retrieval tools and optional ranking for inputs, visibility rules and measured token costs.

Temporal retrieval defaults off because it did not improve the pinned-clock LoCoMo run. Entity coverage is enabled for BM25 and disabled when MiniLM is active. This raises default hit rate from 63.92% to 64.44%, precision from 14.05% to 14.32%, and recall from 57.45% to 58.27%; optional hybrid quality is preserved. The entityLinkBoost setting overrides this automatic choice. Source-informed adaptive and additive alternatives remain opt-in. See all before/after results and losses.

An independent bounded entity boost is available with sessionmem config set entityBoost true. Exact names and explicit aliases can add at most 0.06 to the final ranking score, while recency and importance still apply. Queries without known entities keep their scores. It defaults off: LoCoMo hit rate @5 rose from 64.44% to 64.51%, but precision and recall fell. See the measured tradeoffs. Compact search, timeline and details by ID keep the same interfaces and response limits.

Capture also records an optional context label called a scope. It uses the real working directory name, falling back to the project ID for headless capture. Override it with scope on capture requests, --scope <name> on scan/watch, SESSIONMEM_SCOPE, or sessionmem config set scope <name> for new sessions. Run sessionmem scopes --json to inspect local labels and counts. sessionmem search "deployment" --scope release filters a context; adding --scope-mode boost favors that context while retaining other results. Queries without a scope keep their existing response bytes and ranking. Existing databases upgrade automatically without labelling historical records. See scope behavior and migration safety.

Supported tools

sessionmem works with any MCP-compatible host, including:

  • Claude Code

  • Cursor

  • Codex

  • Cline

  • Windsurf

  • Antigravity

  • QCoder

Other tools that implement the Model Context Protocol can connect too.


Further documentation


Troubleshooting

For install failures, adapter issues, missing session data, or better-sqlite3 native-build problems, see docs/troubleshooting.md.

Start with offline diagnostics:

sessionmem doctor
sessionmem doctor --adapter claude-code  # explicit host override

doctor reports a separate PASS or FAIL for the memory store, schema, transcript discovery for Claude Code, Codex and Cursor, login auto-start registration, registered binary paths, watcher capture checkpoint freshness, hook definitions shipped with the current version, configured MCP command, and a canary write/recall. It exits nonzero if any check fails and prints fix hints, including exact commands for safe repairs. It does not create a missing store or apply migrations. Its temporary canary is isolated from your projects and rolled back even on failure. The MCP check starts the installed local command and verifies its version, tools, and a stats response; it does not require a running agent.

Use sessionmem ping to initialize a missing store or apply pending schema migrations, or sessionmem install --adapter claude-code to refresh Claude Code's MCP registration and hooks. Use sessionmem autostart enable to refresh the login service and absolute binary paths; inspect logs/watch.log beside the database when capture fails. Run repairs with the same SESSIONMEM_DB_PATH as doctor when using a custom store.

If stats shows sessions: 0 after real work, see “0 sessions” / no session data recorded. Memories are keyed to the repository root, so every directory inside one repo shares a bucket; outside a repo the working directory itself is the key.

To check database access and memory counts:

sessionmem ping     # can the local database be opened?
sessionmem stats    # is data being stored?

FAQ

How do I give Cursor, Cline, or Windsurf memory between sessions? Install sessionmem (npm i -g sessionmem), then run sessionmem install in your project. Use --adapter cursor, --adapter cline, or --adapter windsurf when auto-detection cannot identify your host.

How do I give Claude Code persistent memory? Use the same install steps above. sessionmem also ships as a Claude Code plugin (the .claude-plugin directory in the repo) for Claude Code's native plugin system.

Is there a local MCP memory server that works offline with no API key? Yes. sessionmem stores memories in a single SQLite file at ~/.sessionmem/memories.db and works offline by default. Sharing and cloud summarization are optional and off by default.

How is sessionmem different from claude-mem? sessionmem works with Claude Code, Cursor, Cline, Codex, Windsurf, Antigravity, QCoder, and other MCP hosts. It redacts secrets (API keys, tokens, JWTs) by default, prunes old memories automatically, and includes reproducible benchmarks.

Does sessionmem send my code to the cloud? No. Nothing leaves your machine by default. The optional cloud summarization path is opt-in and off by default.

How do I see how many tokens sessionmem saved me? Run sessionmem savings to see a breakdown of storage compression (raw session tokens vs memory tokens) and injection efficiency. Add --json for machine-readable output.


Security

See the security policy for supported versions, private vulnerability reporting through GitHub security advisories, and response expectations.


Contributing

Issues and pull requests are welcome. The codebase is TypeScript, tested with Vitest, and linted with ESLint:

npm ci
npm run build
npm run typecheck
npm test
npm run lint

MCP config for local development: Clone the repository, build it, copy .mcp.json.example to .mcp.json, and replace the example path with the absolute path to your checkout’s dist/cli/index.js. This runs your local build. sessionmem install registers the sessionmem executable on PATH instead. The .mcp.json file is gitignored because it contains machine-specific paths.


License

MIT

Available Tools

15 tools
batchStoreMemoryA

Persist multiple memory units in a single atomic SQLite transaction. Significantly faster than calling storeMemory repeatedly for session-end writes of 10-20 memories.

WHEN TO CALL: At session end or whenever you have multiple memories to store at once. Reduces overhead from per-insert fsync by wrapping all writes in one transaction.

WHEN NOT TO CALL: For a single memory — use storeMemory instead. For imports from external files — use importMemories.

Each item in the memories array follows the same schema as storeMemory (memoryId, sessionId, sourceAdapter, kind, content, importance). Invalid items are reported individually; valid items are still stored atomically.

NOTE: the per-item memory echoed back in the response has its content truncated to 2000 characters (a batch can return many rows). The full body is still persisted — fetch it with getMemory if you need the complete text. (Single-record storeMemory echoes the full content.)

NameRequiredDescriptionDefault
memoriesYesArray of memory objects to store. Each must include: memoryId (unique UUID), sessionId, sourceAdapter, kind, content (self-contained text), importance (1-10). Minimum 1 item, maximum 100. Per-item results may include `warningCodes` (e.g. 'session_write_limit_warning', 'redaction_partial_failure') — advisory signals, not failures.

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful context beyond the annotations (idempotentHint=false, destructiveHint=false): atomic wrapping, per-insert fsync savings, per-item partial success where invalid items are reported but valid items still commit, and 2000-char content truncation in the echoed response with a pointer to getMemory. That is rich disclosure. However, the interaction between 'atomic' and 'valid items are still stored' is ambiguous, and it doesn't state duplicate-memoryId behavior despite declaring non-idempotency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then WHEN/WITHOUT/NOTE blocks that make scanning easy. Minor redundancy: 'Significantly faster than calling storeMemory repeatedly' and 'Reduces overhead from per-insert fsync' say the same thing twice.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the return-value burden and does so: per-item error reporting, warningCodes semantics, and content truncation with a recovery path via getMemory. 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.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the primary parameter additionally carries its own inline description with required fields and warningCodes. The prose mostly restates that structure and points to storeMemory's schema, so this is the baseline case where the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Persist multiple memory units in a single atomic SQLite transaction') and immediately scopes it against siblings: not storeMemory for singles, not importMemories for file imports. An agent can pick this over the 14 siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Has explicit WHEN TO CALL (session end, 10-20 memories at once) and WHEN NOT TO CALL sections that name the two alternative tools and the condition selecting each. No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fetch_memoriesA

Fallback memory retrieval for hosts that do not support MCP resources. Call this instead of accessing the sessionmem:// resource URI directly when the host lacks resource support. Semantically equivalent to retrieveMemories — returns stored memories ranked by relevance to the query. Read-only; no side effects.

WHEN TO CALL: At session start and mid-session when you need to retrieve context and the host does not support MCP resources. Do not call if the host supports MCP resources — use the sessionmem:// resource URI or retrieveMemories tool instead.

Parameter query: natural-language description of what context you need to recall (e.g. 'API design decisions', 'database schema choices').

NameRequiredDescriptionDefault
queryYesNatural-language description of what context you need to recall.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses it is read-only with no side effects, and returns memories ranked by relevance. No annotations provided, so description fully informs agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise paragraphs, front-loaded with purpose, then usage, then parameter detail. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given one parameter, no output schema, and moderate complexity, description fully covers purpose, usage, and parameter meaning.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers parameter with description, and description adds examples of query values. Since schema coverage is 100%, baseline is 3; the added examples justify a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it is a fallback memory retrieval for hosts without MCP resource support, returns memories ranked by relevance, and distinguishes from siblings like retrieveMemories and the resource URI.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly specifies when to call (session start, mid-session when host lacks resource support) and when not to call (host supports resources, instead use URI or retrieveMemories).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

forgetMemoryA
Destructive

Permanently delete a single memory by ID. The record is removed from the local SQLite store immediately and CANNOT be recovered. Destructive and irreversible.

WHEN TO CALL: Only when a memory is known to be incorrect, dangerously outdated, or a duplicate that would mislead future sessions.

WHEN NOT TO CALL: If there is any doubt. A memory that is merely old or low-relevance does not need deletion — retrieval ranking deprioritizes it automatically.

NameRequiredDescriptionDefault
memoryIdYesExact UUID of the memory to permanently delete. Obtain from a prior listMemories or retrieveMemories call. Deletion is immediate and irreversible.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true), description adds details: deletion from local SQLite store, immediate, irreversible, and unrecoverable, providing full behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise with a main sentence plus structured WHEN TO CALL/WHEN NOT TO CALL sections. Every sentence adds value; no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given one required parameter, no output schema, and simple functionality, the description covers purpose, usage guidelines, and behavioral transparency completely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already describes memoryId in detail (UUID, obtain from prior calls, immediate deletion). Description adds no new parameter info beyond the schema, so baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (permanently delete) and the resource (a single memory by ID), distinguishing it from siblings like batchStoreMemory or storeMemory. The 'WHEN TO CALL' and 'WHEN NOT TO CALL' sections further clarify scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides when (memory incorrect/dangerously outdated/duplicate) and when not to call (doubt, merely old/low-relevance), with clear alternatives implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

getMemoryA
Read-onlyIdempotent

Fetch a single memory record by its exact ID. Returns the full record: content, kind, importance, timestamps, and session metadata. Read-only; no side effects.

WHEN TO CALL: After searchMemoryIndex or memoryTimeline, fetch selected IDs for full details. IDs from retrieveMemories or listMemories also work.

For topic searches, start with searchMemoryIndex. getMemory requires an exact ID.

NameRequiredDescriptionDefault
memoryIdYesExact memory ID from searchMemoryIndex, memoryTimeline, retrieveMemories or listMemories.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, and the description's 'Read-only; no side effects' reinforces rather than contradicts them. It adds genuine value beyond the annotations by enumerating the returned payload (content, kind, importance, timestamps, session metadata), which matters because there is no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and return shape, then a clearly labeled WHEN TO CALL section, then a short alternative hint. No sentence is redundant and length is proportionate to a one-parameter read tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because there is no output schema, the description usefully lists returned fields and covers the exact-ID prerequisite. It stops short of stating behavior on a missing/invalid ID (empty result vs error), which is the one remaining gap for an agent calling with a stale ID.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single memoryId parameter is already documented with its origin sources. The description restates the 'exact ID' constraint without adding format, length, or failure-mode detail the schema lacks, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch a single memory record by its exact ID') and immediately distinguishes itself from the search/timeline siblings by requiring an exact ID. The returned fields are enumerated, so the agent knows precisely what it gets back.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The WHEN TO CALL block is explicit: call after searchMemoryIndex or memoryTimeline to hydrate selected IDs, and it names retrieveMemories and listMemories as additional ID sources. It also gives an exclusion — for topic searches start with searchMemoryIndex instead — so the routing decision is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

handleSessionEndA
Idempotent

Run the full session-end pipeline: auto-summarize the session's ingested events into a durable memory (when enough events exist) and apply a light retention prune of stale memories. Idempotent on the summary memory (upsert by sessionId).

WHEN TO CALL: Once, at the very end of a session, after ingesting session events via ingestSessionEvents. Lets sessionmem generate and store the session summary for you.

WHEN NOT TO CALL: Mid-session, or when you have already written your own summary (use summarizeSessionToMemory instead). On Claude Code this also runs automatically via the installed SessionEnd hook, so calling it explicitly is usually unnecessary there.

Provide sessionId and sourceAdapter. memoryId (optional) pins the summary's id; omit to derive ${sessionId}-summary. config (optional) tunes autoSummarize / minimumEventThreshold / cloud summarization; omit for sensible local-only defaults.

RESPONSE status is one of: 'stored', 'skipped_threshold' (too few events), 'skipped_disabled', 'failed'. warningCodes may carry cloud/local fallback signals.

NameRequiredDescriptionDefault
scopeNo
configNo
memoryIdNo
sessionIdYes
sourceAdapterYes
workingDirectoryNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint and destructiveHint=false, but the description adds real value beyond them: the idempotency mechanism (upsert by sessionId), the existence of a retention prune of stale memories, threshold-gated summarization, and the four possible status outcomes plus warningCodes for cloud/local fallback. It does not detail what the prune actually removes or what permissions/keys cloud summarization requires.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded: one-sentence pipeline summary, then labeled WHEN TO CALL / WHEN NOT / parameter notes / response codes. Slightly padded by the repeated 'omit for sensible defaults' phrasing and some incidental detail, but nothing is genuinely wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, yet the description enumerates the status values and warningCodes, which is the main return-value need. The remaining gap is undocumented optional params (scope, workingDirectory, several config keys) that an agent could mis-set silently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 6 params including a nested config object, so the description must compensate. It explains sessionId, sourceAdapter, memoryId's default derivation, and three config fields — helpful — but leaves scope, workingDirectory, factMode, summaryTokenCap, redactionEnabled, and anthropicApiKey entirely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific composite action (summarize ingested events into durable memory plus a light retention prune) and names the exact alternative (summarizeSessionToMemory) it differs from. An agent can distinguish it from siblings like ingestSessionEvents or storeMemory without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit WHEN TO CALL (once, at the very end, after ingestSessionEvents) and WHEN NOT TO CALL (mid-session, or when a summary already exists — use summarizeSessionToMemory instead). It even notes the Claude Code SessionEnd hook makes explicit invocation usually unnecessary, which is exactly the routing info an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ingestSessionEventsA
Idempotent

Push raw session events (tool calls, decisions, file edits, user turns) to sessionmem so they can be summarized at session end and counted toward token-savings analytics. Writes immediately, in a single transaction. Re-ingesting the same (sessionId, eventIndex) is a no-op, so retries are safe.

WHEN TO CALL: Periodically during a session (e.g. at task boundaries) to record what happened, OR in one batch shortly before the session ends. This is what powers automatic session-end summarization and sessionmem savings.

WHEN NOT TO CALL: For durable, individually-important facts/decisions — use storeMemory for those. Session events are transient raw material for summarization, not first-class memories.

Each event needs: id (unique), eventIndex (monotonic 0-based order within the session), eventType (e.g. 'tool_use', 'user_message'), payloadJson (a JSON string of the event body).

LIMITS: at most 500 events per call. For more than 500 events, call this tool multiple times in chunks — re-ingestion of already-stored events is safe (idempotent via the (project, session, eventIndex) UNIQUE index), so overlapping chunks never double-count.

NameRequiredDescriptionDefault
scopeNo
eventsYes
sessionIdYes
replaceExistingNo
workingDirectoryNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing immediate single-transaction writes, idempotency keyed on the (project, session, eventIndex) UNIQUE index, and the 500-event cap. It is consistent with idempotentHint=true, but never mentions the replaceExisting parameter, which could change the no-op-on-reingest behavior an agent relies on.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads what the tool does, then organizes when-to/when-not/limits into scannable blocks. Every sentence carries actionable information; nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations covering safety beyond idempotency, the description covers transactionality, idempotent retry semantics, and batch limits thoroughly. The one material gap is the undocumented replaceExisting flag and scope, which affect how an agent should shape repeat calls.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the documentation burden; it does explain the nested event fields (id, eventIndex, eventType, payloadJson) but omits createdAt, scope, workingDirectory and especially replaceExisting, whose effect on the idempotency guarantee is unstated. Useful but incomplete compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Push raw session events ... to sessionmem') plus the downstream purpose (session-end summarization, token-savings analytics). It explicitly distinguishes itself from storeMemory, so an agent can tell ingestion of transient events from storing first-class memories without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit WHEN TO CALL (periodically at task boundaries, or one batch before session end) and WHEN NOT TO CALL, naming storeMemory as the alternative for durable facts. It also gives operational guidance for oversized batches (chunk at 500, overlapping is safe).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

listMemoriesA
Read-onlyIdempotent

Return every memory stored for the current project, unfiltered and without ranking. Read-only; no side effects.

WHEN TO CALL: When you need a complete inventory of stored memories — to audit what has been saved, detect duplicates, or build a full summary of all known context.

WHEN NOT TO CALL: For normal context loading at session start — use retrieveMemories instead, which ranks by relevance. listMemories returns the entire store unfiltered and can be very large.

NameRequiredDescriptionDefault
limitNo

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true; description confirms read-only with no side effects and warns the output can be very large, adding value beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with a clear main sentence followed by structured usage guidelines (WHEN TO CALL, WHEN NOT TO CALL), front-loading essential information with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a list tool without output schema, the description covers purpose, usage, and behavioral traits well. Minor gap: does not describe the return format, but given the simplicity and annotations, it is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not explain the 'limit' parameter or its effect, despite the parameter having constraints in the schema. The description should compensate for low schema coverage but fails to do so.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns every memory unfiltered, and contrasts with retrieveMemories which ranks by relevance, making the purpose specific and distinguishable from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides WHEN TO CALL (audit, detect duplicates, build full summary) and WHEN NOT TO CALL (session start; suggests retrieveMemories instead), with clear alternative named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memoryTimelineA
Read-onlyIdempotent

Browse compact memories in capture order around memoryId, or within an inclusive UTC fromDate/toDate range. Provide an ID or both dates. Includes superseded history by default. Default limit 10, maximum 50. Use getMemory for full details. Does not update access counters.

NameRequiredDescriptionDefault
limitNo
scopeNo
toDateNo
fromDateNo
memoryIdNo
includeHistoryNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations by disclosing that superseded history is included by default, that the default limit is 10 with a max of 50, and that the call does not bump access counters — a non-obvious side-effect distinction that matters for agents reasoning about memory usage stats.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Six short sentences, zero filler, with the primary selection modes front-loaded and constraints (limits, defaults, counter behavior) trailing. Every sentence carries a distinct operational fact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Six optional parameters, no output schema, and no annotations beyond safety hints — the description covers modes, bounds, defaults, and history behavior, and notes output is 'compact' versus getMemory's full records. Only the undocumented `scope` parameter keeps it from being complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description carries the burden well: it explains memoryId, fromDate/toDate (inclusive, UTC), limit (default 10, max 50), and includeHistory (superseded history included by default). The `scope` parameter is never mentioned anywhere, which is the one real gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource (browse compact memories) with two precise selection modes: capture order around memoryId, or an inclusive UTC fromDate/toDate range. It also distinguishes itself from getMemory, which returns full details rather than compact entries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Provide an ID or both dates" gives a clear admission condition, and "Use getMemory for full details" routes the agent to the right sibling for the expanded-record case. It does not position itself against listMemories, retrieveMemories, or searchMemoryIndex, so the sibling routing is only partial.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resetAccessCountsA
Idempotent

Reset access-pattern counters for all memories in the current project. Sets access_count to 0 and clears last_accessed timestamps without deleting any memories. Useful after large refactors when old access patterns no longer reflect current relevance.

WHEN TO CALL: After major codebase restructuring, project pivots, or when access-boosted rankings no longer reflect current relevance.

WHEN NOT TO CALL: During normal operation — access patterns self-correct as usage shifts.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide destructiveHint=false and idempotentHint=true. The description adds context by detailing the exact state changes (setting counters to 0, clearing timestamps) and affirming no deletions. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is clear and well-structured with separate sections for purpose and usage guidelines. Slightly verbose but efficient; could be trimmed without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (no params, no output schema), the description fully covers purpose, behavior, usage contexts, and side effects. Leaves no relevant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With zero parameters and 100% schema coverage (empty schema), baseline is 4. The description compensates by explaining the action and its effects, adding value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool resets access-pattern counters for all memories in the current project, specifying it sets access_count to 0 and clears timestamps without deletion. It distinguishes from siblings like forgetMemory or listMemories by focusing on counters rather than 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides 'WHEN TO CALL' and 'WHEN NOT TO CALL' sections, advising use after major refactors and against use during normal operation where self-correction occurs. This gives clear context and alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

retrieveMemoriesA

Semantically search stored memories and return the top matches ranked by a weighted combination of relevance, recency, and importance. Read-only; no side effects.

WHEN TO CALL: (1) At the start of every session — pass the current task or file as the query to pre-load relevant context. (2) Mid-session whenever a new topic, file, or decision area arises that may have prior context. Do NOT call on every user turn.

WHEN NOT TO CALL: If you already retrieved memories for this topic this session. Use getMemory if you have a specific memoryId. Use listMemories only to audit the full store, not for context loading.

Returns up to limit results (default 20). mode='auto' is the standard startup path; mode='on-demand' signals an explicit mid-session lookup. depth='deep' runs a broader semantic sweep at higher latency — use when the topic is unfamiliar. Phrase query as what you need to recall, not what you are about to do.

NOTE: this tool updates access-pattern counters on the memories it returns (used to boost frequently-recalled memories in future ranking), so it is NOT side-effect-free despite being a lookup.

NameRequiredDescriptionDefault
modeNo'auto' for the standard startup context-load path. 'on-demand' for an explicit mid-session retrieval triggered by a specific task or question.auto
tagsNoOptional tag filter. When provided, only return memories that have ALL listed tags.
depthNo'default' for standard semantic search. 'deep' for a broader sweep that surfaces less-similar memories — use when the topic is new or unfamiliar.default
limitNoMaximum number of memories to return. Integer 1-100, default 20. Increase for broad topic sweeps; keep at default for focused lookups.
queryYesNatural-language description of what you need to recall. Phrase as a topic or question (e.g. 'database connection settings', 'auth flow decisions') — not an action ('store info about...').
includeHistoryNoInclude superseded facts for historical questions. Omit for current facts only.

TDQS

A3.7/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The opening claims 'Read-only; no side effects,' which directly contradicts the readOnlyHint=false annotation. Although a later NOTE admits that access-pattern counters are updated and the tool is not side-effect-free, the definition remains internally inconsistent in a way that could mislead an agent about mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is front-loaded with purpose and organized into clear WHEN TO CALL / WHEN NOT TO CALL sections. It is somewhat long and repeats schema details, and the incorrect 'Read-only; no side effects' line is wasted and harmful, but the structure is otherwise efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter retrieval tool with no output schema, it covers ranking, default result count, mode/depth usage, and alternatives well enough to call correctly. The side-effect contradiction prevents a higher score, but the schema fills in tag and includeHistory semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 input schema. The description largely restates mode, depth, query phrasing, and limit behavior, with no additional syntax or edge-case guidance beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: semantically search stored memories and return top matches ranked by relevance, recency, and importance. It distinguishes itself from siblings by naming getMemory for memoryId lookups and listMemories for store auditing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit WHEN TO CALL triggers for session start and mid-session topic changes, plus WHEN NOT TO CALL conditions including avoiding repeated retrieval and not calling every user turn. It also routes specific cases to getMemory and listMemories.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

searchMemoryIndexA
Read-onlyIdempotent

Search a compact memory index. Returns IDs, one-line previews, kinds, capture dates and scores. Start here for topic lookups, use memoryTimeline for nearby context, then getMemory for selected full bodies. Default limit 10, maximum 50. Does not update access counters. hasMore refers to the bounded candidate pool.

NameRequiredDescriptionDefault
tagsNo
limitNo
queryYes
scopeNo
scopeModeNo
includeHistoryNo

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavioral context beyond the annotations: it describes return fields, default and maximum limit, that access counters are not updated, and how hasMore relates to the bounded candidate pool. Annotations already cover read-only and idempotent behavior, and the description complements them well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded, information-dense, and free of filler. Each sentence adds practical value about workflow, return shape, limits, or side effects.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

It covers the search workflow, return shape, limit defaults, and hasMore semantics, which is useful for a tool without an output schema. However, for a six-parameter tool with no schema descriptions, it leaves key parameters like tags, scope, scopeMode, and includeHistory unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain parameter meanings. It only clarifies limit (default 10, maximum 50) and implies query via "topic lookups"; tags, scope, scopeMode (filter vs boost), and includeHistory are not explained at all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Search a compact memory index." It also distinguishes the tool from memoryTimeline and getMemory by positioning it as the starting point for topic lookups and full-body retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: "Start here for topic lookups, use memoryTimeline for nearby context, then getMemory for selected full bodies." This gives clear when-to-use guidance and names the relevant alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

startup_inject_memoriesA

Fallback startup-injection for hosts that do not support MCP prompts. Call this once at the very start of a session instead of relying on the automatic sessionmem startup prompt when the host lacks prompt support. Injects the top relevant memories for the current project into the working context. No parameters required.

WHEN TO CALL: Once per session start, before any user task work begins, when the host does not surface MCP prompts automatically. Do not call if the host already surfaces the sessionmem startup prompt — calling both duplicates injected context.

Note: access counts are incremented on retrieval.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. Discloses that access counts are incremented on retrieval and that it is a fallback. However, does not detail criteria for 'top relevant memories' or side effects if called multiple times.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise paragraphs with clear structure, including a 'WHEN TO CALL' note. No redundant sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and no annotations, description covers purpose, usage, and a behavioral note. Could mention behavior when no relevant memories exist or if called multiple times, but overall adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters, so baseline 4. Description adds context about the injection purpose but no need for parameter details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it's a fallback to inject memories when host doesn't support MCP prompts. It specifies the action (injects top relevant memories for current project) and distinguishes from siblings like 'retrieveMemories' or 'fetch_memories' by explaining it's a session start injection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to call (once per session start, when host lacks prompt support) and when not to call (if host already surfaces sessionmem startup prompt). Provides alternative guidance (rely on automatic prompt) to avoid duplication.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

statsA
Read-onlyIdempotent

Return aggregate statistics for the current project: total stored memory count and total ingested session event count. Read-only; no side effects.

WHEN TO CALL: For diagnostic or monitoring purposes — to confirm memories were stored after a session, check store health, or report usage numbers.

WHEN NOT TO CALL: As part of normal context loading. stats returns counts only, not content; use retrieveMemories to load actual context.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint and idempotentHint. Description adds the specific statistics returned and reaffirms no side effects. Valuable context but not essential beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three well-structured sentences: purpose, when to call, when not to call. No redundancy, every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a simple parameterless tool with no output schema. Covers purpose, usage guidelines, and differentiates from siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so description adds no param info. Baseline is 4; description is clear about what the tool does without needing to reference parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description specifies the exact resource and action: returning aggregate statistics (total stored memory count and total ingested session event count) for the current project. It clearly distinguishes from sibling tools like retrieveMemories.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to call (diagnostic/monitoring) and when not to call (not for normal context loading), with an alternative tool suggested.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

storeMemoryA

Persist a single memory unit to the local SQLite store. Accepts decisions, facts, architectural choices, warnings, and session summaries. NOT idempotent — each call creates a new record even with identical content. Writes to disk immediately.

WHEN TO CALL: After any significant decision, discovery, or conclusion that should be available in a future session. Good candidates: technology choices, non-obvious constraints, bug root-causes, architectural decisions, key facts about the codebase.

WHEN NOT TO CALL: For trivial observations, transient state, or content that duplicates what was just retrieved. Do not store entire files or full conversation transcripts.

kind categories: 'decision', 'fact', 'summary', 'warning', 'preference'. Write content to be self-contained — it must be useful without any surrounding conversation context. importance 1-10 (10 = most critical); directly affects retrieval ranking in future sessions.

RESPONSE may include warningCodes: 'session_write_limit_warning' (this session has stored many memories — stop storing trivia and prefer batchStoreMemory) and 'redaction_partial_failure' (a redaction rule errored; the write still succeeded). Treat them as advisory signals, not errors.

NameRequiredDescriptionDefault
kindYesCategory of this memory. One of: 'decision', 'fact', 'warning', 'preference', 'summary'. These are the only recognized kinds — others are rejected.
tagsNoOptional array of tag strings (max 10, each max 50 chars) for categorizing this memory. Example: ['auth', 'db-schema']. Tags are filterable via retrieveMemories.
contentYesThe memory text. Must be self-contained and specific — written so it is useful without surrounding conversation context. Avoid vague phrases like 'the user decided to...'.
memoryIdYesCaller-supplied unique UUID for this memory (e.g. crypto.randomUUID()). Used for deduplication and for later retrieval by ID via getMemory.
expiresAtNoOptional UTC ISO timestamp (e.g. '2026-12-31T00:00:00Z') after which this memory is excluded from retrieval. Use for time-limited context like a temporary workaround.
sessionIdYesIdentifier for the current session. Used to group memories by session for diagnostics. Use a consistent ID within a single session.
importanceYesInteger 1-10 indicating criticality (10 = most important). Directly affects ranking in future retrieveMemories calls. Use 8-10 for decisions that must not be forgotten; 3-5 for useful but non-critical facts.
sourceAdapterYesName of the adapter or host creating this memory (e.g. 'claude-code', 'cursor', 'generic'). Used for provenance tracking.
redactionEnabledNoIf true, PII is stripped from content before storage. Omit to use the project-level redaction setting from config.json.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry idempotentHint=false and destructiveHint=false; the description adds material context beyond them — immediate disk writes, the non-idempotent duplicate-record behavior, redaction behavior, and the meaning of advisory warningCodes. Nothing contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core operation, then cleanly partitioned into WHEN TO CALL / WHEN NOT TO CALL / parameter notes / response notes. Despite its length, each block carries distinct, actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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 output schema, the description covers invocation context, behavioral caveats, and return-signal semantics (warningCodes). An agent has everything needed to call it correctly and interpret the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 9 parameters. The description's notes on kind categories and importance's effect on retrieval ranking largely restate the schema rather than adding syntax or format detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Persist a single memory unit to the local SQLite store') and immediately scopes it as single-unit, which distinguishes it from the sibling batchStoreMemory. An agent can identify the operation without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit WHEN TO CALL and WHEN NOT TO CALL sections with concrete examples (technology choices, bug root-causes vs. trivial observations, transcripts). It also routes to the alternative (batchStoreMemory) inside the write-limit warning, giving a clear switch condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

summarizeSessionToMemoryA
Idempotent

Store an agent-authored session summary as a durable 'summary' memory in one call. Upserts on memoryId, so calling it again with the same memoryId replaces the prior summary rather than duplicating it.

WHEN TO CALL: At session end when you have already written a concise summary of what was accomplished and want to persist it directly (the simpler alternative to handleSessionEnd's automatic summarization).

WHEN NOT TO CALL: When you want sessionmem to generate the summary from ingested session events — use handleSessionEnd for that. For non-summary facts/decisions use storeMemory.

Provide: memoryId (stable id for this session's summary), sessionId, sourceAdapter, summary (the text), importance (1-10; 7 is typical for summaries).

NameRequiredDescriptionDefault
scopeNo
summaryYes
memoryIdYes
sessionIdYes
importanceYes
sourceAdapterYes
workingDirectoryNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description usefully explains *why*: upserting on memoryId replaces the prior summary instead of duplicating, so an agent understands the overwrite behavior. It does not cover auth requirements, size/retention limits, or what a successful call returns, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and upsert semantics, then organized into WHEN TO CALL / WHEN NOT TO CALL / Provide blocks. Slightly list-heavy for the payload, but nearly every line carries decision-relevant information rather than restating the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotation coverage of returns, the description still gives an agent everything needed to invoke it correctly: purpose, routing, idempotency behavior, and key parameter meanings. Only the response shape and the meaning of scope/workingDirectory are absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry the load, and it does for five of seven parameters — notably defining memoryId as a stable per-session id and giving a practical anchor for importance (1-10; 7 is typical). scope and workingDirectory are left entirely unexplained, so it does not fully compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action and resource: storing an agent-authored session summary as a durable 'summary' memory, and explicitly frames it as the one-call, caller-written counterpart to summarization. The upsert-on-memoryId clause further pins down the semantics so it is distinguishable from storeMemory and handleSessionEnd.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Has explicit WHEN TO CALL and WHEN NOT TO CALL blocks naming the alternatives (handleSessionEnd for generated summaries, storeMemory for non-summary facts). The selection condition between the two paths is stated plainly rather than inferred.

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. 6 tool updatesv1.10.0
    • ChangedbatchStoreMemory2 fields changed
      • addedInput schema / properties / memories / items / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 160,
        +      "minLength": 1,
        +      "pattern": "^[^\\x00-\\x1f\\x7f]+$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / memories / items / properties / workingDirectory
        Added value: +{
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
    • ChangedhandleSessionEnd2 fields changed
      • addedInput schema / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 160,
        +      "minLength": 1,
        +      "pattern": "^[^\\x00-\\x1f\\x7f]+$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / workingDirectory
        Added value: +{
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
    • ChangedingestSessionEvents2 fields changed
      • addedInput schema / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 160,
        +      "minLength": 1,
        +      "pattern": "^[^\\x00-\\x1f\\x7f]+$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / workingDirectory
        Added value: +{
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
    • ChangedmemoryTimeline1 field changed
      • addedInput schema / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 160,
        +      "minLength": 1,
        +      "pattern": "^[^\\x00-\\x1f\\x7f]+$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
    • ChangedsearchMemoryIndex2 fields changed
      • addedInput schema / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 160,
        +      "minLength": 1,
        +      "pattern": "^[^\\x00-\\x1f\\x7f]+$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / scopeMode
        Added value: +{
        +  "enum": [
        +    "filter",
        +    "boost"
        +  ],
        +  "type": "string"
        +}
    • ChangedsummarizeSessionToMemory2 fields changed
      • addedInput schema / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 160,
        +      "minLength": 1,
        +      "pattern": "^[^\\x00-\\x1f\\x7f]+$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / workingDirectory
        Added value: +{
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
  2. 3 tool updatesv1.9.0
    • ChangedgetMemory1 field changed
      • changedInput schema / properties / memoryId / description
        Previous value: -"Exact UUID of the memory to fetch. Obtain from a prior retrieveMemories or listMemories result."New value: +"Exact memory ID from searchMemoryIndex, memoryTimeline, retrieveMemories or listMemories."
    • AddedmemoryTimeline
    • AddedsearchMemoryIndex
  3. 4 tool updatesv1.6.0
    • ChangedbatchStoreMemory3 fields changed
      • addedInput schema / properties / memories / items / properties / expiresAt
        Added value: +{
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$",
        +  "type": "string"
        +}
      • addedInput schema / properties / memories / items / properties / tags
        Added value: +{
        +  "items": {
        +    "maxLength": 50,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "type": "array"
        +}
      • changedInput schema / properties / memories / items / required
        Previous value: -[
        -  "memoryId",
        -  "sessionId",
        -  "sourceAdapter",
        -  "content",
        -  "importance"
        -]New value: +[
        +  "memoryId",
        +  "sessionId",
        +  "sourceAdapter",
        +  "kind",
        +  "content",
        +  "importance"
        +]
    • ChangedingestSessionEvents2 fields changed
      • changedInput schema / properties / events / items / required
        Previous value: -[
        -  "id",
        -  "eventIndex",
        -  "eventType",
        -  "payloadJson"
        -]New value: +[
        +  "id",
        +  "eventType",
        +  "payloadJson"
        +]
      • addedInput schema / properties / replaceExisting
        Added value: +{
        +  "type": "boolean"
        +}
    • ChangedretrieveMemories2 fields changed
      • addedInput schema / properties / includeHistory
        Added value: +{
        +  "description": "Include superseded facts for historical questions. Omit for current facts only.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / tags
        Added value: +{
        +  "description": "Optional tag filter. When provided, only return memories that have ALL listed tags.",
        +  "items": {
        +    "maxLength": 50,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "type": "array"
        +}
    • ChangedstoreMemory3 fields changed
      • addedInput schema / properties / expiresAt
        Added value: +{
        +  "description": "Optional UTC ISO timestamp (e.g. '2026-12-31T00:00:00Z') after which this memory is excluded from retrieval. Use for time-limited context like a temporary workaround.",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$",
        +  "type": "string"
        +}
      • addedInput schema / properties / tags
        Added value: +{
        +  "description": "Optional array of tag strings (max 10, each max 50 chars) for categorizing this memory. Example: ['auth', 'db-schema']. Tags are filterable via retrieveMemories.",
        +  "items": {
        +    "maxLength": 50,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "type": "array"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "memoryId",
        -  "sessionId",
        -  "sourceAdapter",
        -  "content",
        -  "importance"
        -]New value: +[
        +  "memoryId",
        +  "sessionId",
        +  "sourceAdapter",
        +  "kind",
        +  "content",
        +  "importance"
        +]
  4. 11 tool updatesv1.1.2
    • ChangedbatchStoreMemory10 fields changed
      • changedInput schema / properties / memories / description
        Previous value: -"Array of memory objects to store. Each must include: memoryId (unique UUID), sessionId, sourceAdapter, kind, content (self-contained text), importance (1-10). Minimum 1 item."New value: +"Array of memory objects to store. Each must include: memoryId (unique UUID), sessionId, sourceAdapter, kind, content (self-contained text), importance (1-10). Minimum 1 item, maximum 100.\n\nPer-item results may include `warningCodes` (e.g. 'session_write_limit_warning', 'redaction_partial_failure') — advisory signals, not failures."
      • addedInput schema / properties / memories / items / properties / content / maxLength
        Added value: +10000
      • addedInput schema / properties / memories / items / properties / kind / enum
        Added value: +[
        +  "decision",
        +  "fact",
        +  "warning",
        +  "preference",
        +  "summary"
        +]
      • removedInput schema / properties / memories / items / properties / kind / minLength
        Removed value: -1
      • addedInput schema / properties / memories / items / properties / memoryId / maxLength
        Added value: +200
      • addedInput schema / properties / memories / items / properties / sessionId / maxLength
        Added value: +200
      • addedInput schema / properties / memories / items / properties / sourceAdapter / maxLength
        Added value: +100
      • addedInput schema / properties / memories / items / properties / sourceAdapter / pattern
        Added value: +"^[^\\n\\r\\x00-\\x08\\x0e-\\x1f\\x7f]*$"
      • changedInput schema / properties / memories / items / required
        Previous value: -[
        -  "memoryId",
        -  "sessionId",
        -  "sourceAdapter",
        -  "kind",
        -  "content",
        -  "importance"
        -]New value: +[
        +  "memoryId",
        +  "sessionId",
        +  "sourceAdapter",
        +  "content",
        +  "importance"
        +]
      • addedInput schema / properties / memories / maxItems
        Added value: +100
    • Addedfetch_memories
    • ChangedforgetMemory1 field changed
      • addedInput schema / properties / memoryId / maxLength
        Added value: +200
    • ChangedgetMemory1 field changed
      • addedInput schema / properties / memoryId / maxLength
        Added value: +200
    • AddedhandleSessionEnd
    • AddedingestSessionEvents
    • ChangedlistMemories1 field changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "exclusiveMinimum": 0,
        +  "maximum": 1000,
        +  "type": "integer"
        +}
    • ChangedretrieveMemories1 field changed
      • addedInput schema / properties / query / maxLength
        Added value: +1000
    • Addedstartup_inject_memories
    • ChangedstoreMemory9 fields changed
      • addedInput schema / properties / content / maxLength
        Added value: +10000
      • changedInput schema / properties / kind / description
        Previous value: -"Category of this memory. Recommended values: 'decision', 'fact', 'summary', 'warning', 'architecture'. Any non-empty string is valid."New value: +"Category of this memory. One of: 'decision', 'fact', 'warning', 'preference', 'summary'. These are the only recognized kinds — others are rejected."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "decision",
        +  "fact",
        +  "warning",
        +  "preference",
        +  "summary"
        +]
      • removedInput schema / properties / kind / minLength
        Removed value: -1
      • addedInput schema / properties / memoryId / maxLength
        Added value: +200
      • addedInput schema / properties / sessionId / maxLength
        Added value: +200
      • addedInput schema / properties / sourceAdapter / maxLength
        Added value: +100
      • addedInput schema / properties / sourceAdapter / pattern
        Added value: +"^[^\\n\\r\\x00-\\x08\\x0e-\\x1f\\x7f]*$"
      • changedInput schema / required
        Previous value: -[
        -  "memoryId",
        -  "sessionId",
        -  "sourceAdapter",
        -  "kind",
        -  "content",
        -  "importance"
        -]New value: +[
        +  "memoryId",
        +  "sessionId",
        +  "sourceAdapter",
        +  "content",
        +  "importance"
        +]
    • AddedsummarizeSessionToMemory
  5. 6 tool updatesv1.0.6
    • AddedbatchStoreMemory
    • ChangedforgetMemory1 field changed
      • addedInput schema / properties / memoryId / description
        Added value: +"Exact UUID of the memory to permanently delete. Obtain from a prior listMemories or retrieveMemories call. Deletion is immediate and irreversible."
    • ChangedgetMemory1 field changed
      • addedInput schema / properties / memoryId / description
        Added value: +"Exact UUID of the memory to fetch. Obtain from a prior retrieveMemories or listMemories result."
    • AddedresetAccessCounts
    • ChangedretrieveMemories4 fields changed
      • addedInput schema / properties / depth / description
        Added value: +"'default' for standard semantic search. 'deep' for a broader sweep that surfaces less-similar memories — use when the topic is new or unfamiliar."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of memories to return. Integer 1-100, default 20. Increase for broad topic sweeps; keep at default for focused lookups."
      • addedInput schema / properties / mode / description
        Added value: +"'auto' for the standard startup context-load path. 'on-demand' for an explicit mid-session retrieval triggered by a specific task or question."
      • addedInput schema / properties / query / description
        Added value: +"Natural-language description of what you need to recall. Phrase as a topic or question (e.g. 'database connection settings', 'auth flow decisions') — not an action ('store info about...')."
    • ChangedstoreMemory7 fields changed
      • addedInput schema / properties / content / description
        Added value: +"The memory text. Must be self-contained and specific — written so it is useful without surrounding conversation context. Avoid vague phrases like 'the user decided to...'."
      • addedInput schema / properties / importance / description
        Added value: +"Integer 1-10 indicating criticality (10 = most important). Directly affects ranking in future retrieveMemories calls. Use 8-10 for decisions that must not be forgotten; 3-5 for useful but non-critical facts."
      • addedInput schema / properties / kind / description
        Added value: +"Category of this memory. Recommended values: 'decision', 'fact', 'summary', 'warning', 'architecture'. Any non-empty string is valid."
      • addedInput schema / properties / memoryId / description
        Added value: +"Caller-supplied unique UUID for this memory (e.g. crypto.randomUUID()). Used for deduplication and for later retrieval by ID via getMemory."
      • addedInput schema / properties / redactionEnabled / description
        Added value: +"If true, PII is stripped from content before storage. Omit to use the project-level redaction setting from config.json."
      • addedInput schema / properties / sessionId / description
        Added value: +"Identifier for the current session. Used to group memories by session for diagnostics. Use a consistent ID within a single session."
      • addedInput schema / properties / sourceAdapter / description
        Added value: +"Name of the adapter or host creating this memory (e.g. 'claude-code', 'cursor', 'generic'). Used for provenance tracking."
  6. 6 tool updatesv1.0.0
    • First observedforgetMemory
    • First observedgetMemory
    • First observedlistMemories
    • First observedretrieveMemories
    • First observedstats
    • First observedstoreMemory

TDQS

A3.9/5.0

Scored across 15 tools

Disambiguation3/5

Four tools retrieve memories (retrieveMemories, fetch_memories, searchMemoryIndex, startup_inject_memories) and three browse the store (listMemories, memoryTimeline, searchMemoryIndex), creating real selection risk. Descriptions do explain the distinctions (host-capability fallback vs. ranked search vs. index scan), but an agent must read carefully to avoid duplication, and startup_inject_memories overlaps heavily with retrieveMemories at session start.

Naming Consistency3/5

Most tools use camelCase verb_noun (storeMemory, getMemory, forgetMemory, batchStoreMemory), but two use snake_case (fetch_memories, startup_inject_memories). Also, for a memory domain, the noun is sometimes 'Memory' and sometimes omitted (stats, handleSessionEnd), which weakens the pattern.

Tool Count3/5

15 tools sits at the upper bound for a memory server, and several earn their place only in niche host configurations (fetch_memories, startup_inject_memories, resetAccessCounts). The core lifecycle could be covered with roughly 10 tools; the extra fallback/administrative surface makes the set feel heavy.

Completeness4/5

Coverage is broad: create, batch create, semantic retrieve, index search, timeline browse, get, list, delete, session events, summaries, and stats. The notable gap is updating/editing an existing memory's content or importance — only summaries upsert, so corrections require forget + store.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Persistent memory MCP server for Claude Code, Cursor, and GitHub Copilot. Semantic search, Git sync, project-based, Persistent memory MCP server for Claude Code, Cursor, and GitHub Copilot. Semantic search, Git sync, project-based organization, and team collaboration via Model Context Protocol.
    11
    415 npm
    2
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Persistent memory MCP server that captures coding session context and automatically injects relevant memories into prompts using hybrid search for OpenCode and Claude Code.
    14
    73
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Local-first MCP server that gives any AI coding agent per-project memory, workflow intelligence, and always-on, lossless token & context optimization.
    37
    13 npm
    6
    MIT