handoff-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@handoff-mcpresume the finance agent project from where I left off"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
handoff-mcp
Your agent's memory between sessions. Persistent, cross-project hand-off for Claude over the Model Context Protocol — it remembers the goal, the decisions, the dead-ends, and what's next, so the next session never starts from zero.
Claude forgets everything between sessions. handoff-mcp gives it a memory that
survives the context window: it tracks the progress of your work — goals,
decisions and their rationale, dead-ends, open questions, the next step — and at
the boundary of a session produces a prioritised, token-budgeted brief so the
next session resumes already knowing where you left off.
It is not a context dump. Two things make it different from similarity-based memory stores (mem0 / OpenMemory style):
Temporal supersession. A new decision retracts an old one; retracted decisions never appear in a future brief. Memory reflects the current state of the world, not a flat pile of contradictory facts.
Deterministic brief. The brief is assembled by an explainable ranker (recency + importance + supersession), not by an LLM — so it is reproducible and stays within a token budget (a soft cap on event content; see Limitations).
Your store, multi-device. The vault is your own private git repo, not a hosted service — so memory can follow you across machines (pull-on-start, push-on-checkpoint, conflict-free entity merges) with zero vendor lock. See Multi-device sync.
Status: v0.4, early. The core (vault, brief, supersession, keyword search, cross-project recall) is tested and stable; the semantic, consolidation, importer, and multi-device sync layers are optional and newer. It leans on the agent calling the tools at the right moments — see Limitations for the honest edges.
It is also cross-project: one vault, namespaced per project. The brief is
project-scoped (where did I leave off here), but search_memory recalls across
all projects — so when you say "in one of my projects we did X", Claude can
find and pull that decision out of another project.
Contents
Connect your MCP client — Claude, Cursor, Codex, Kilo Code, …
Related MCP server: Chronos MCP
Demo: two sessions
python examples/two_sessions_demo.py — session 1 works and stops; session 2 is
a fresh process that resumes from the brief alone.
Session 1 logs its progress (and changes its mind once):
log_event("goal", "Ship the finance agent: income/expense tracking…")
d = log_event("decision", "Store transactions in a flat JSON file.")
log_event("decision", "Use SQLite instead of JSON — need queries.", supersedes=[d]) # retracts ↑
note_entity("Architecture", "SQLite-backed; LLM summary calls run in a worker.") # durable
log_event("deadend", "Provider streaming API times out on long months; needs chunking.")
log_event("question", "Recurring transactions: templates or materialised rows?")
log_event("next_step","Write the SQLite schema, then the ingest function.")
checkpoint("Chose SQLite; finance schema is next.")Session 2 calls get_brief() and gets back only the current state — the
retracted JSON decision is gone:
# Hand-off brief — agent-hub
## Goal
- Ship the finance agent: income/expense tracking with scheduled summaries.
## Next step
- Write the SQLite schema for transactions and categories, then the ingest function.
## Decisions
- Use SQLite for transactions instead of JSON — need queries for summaries. See [[Architecture]].
## Dead ends (tried & failed)
- Tried the provider's streaming API for the summary job — times out on long months. Don't retry without chunking.
## Open questions
- Should recurring transactions be modelled as templates or materialised rows?
## Related knowledge
- [[Architecture]] — SQLite-backed; LLM summary calls run in a worker.The retracted "flat JSON file" decision never appears. The graph-linked
[[Architecture]]note is pulled in automatically. The brief is ~170 tokens.
And cross-project recall — search_memory("timeout chunking", scope="all") pulls
a decision out of a different project:
- [hermes] In the Hermes project we solved long-job timeouts by chunking requests.
- [agent-hub] Tried the provider's streaming API for the summary job — times out on long months…Benchmarks
Two offline, deterministic benchmarks — no LLM, no network — so they regenerate
identically anywhere and are pinned by tests/test_benchmark.py. Full numbers,
methodology, and how to reproduce: benchmarks/RESULTS.md.
1. Supersession in isolation (benchmarks/supersession_benchmark.py). A
project's decisions evolve across 8 statements over 4 topics; each has one decision
a later one retracts (JSON→SQLite, cookies→JWT, …). Retrieved by decision (so
every stale fact is reachable), the flat log vs the active view:
mode | stale leaked | current kept |
supersession OFF (flat log) | 4 / 4 | 4 / 4 |
supersession ON (active view) | 0 / 4 | 4 / 4 |
Supersession removes exactly the retracted decisions while keeping every current one — and scoring current kept too means an empty answer can't pass as a win. A similarity store with no notion of one fact retiring another behaves like the OFF row.
2. Brief vs naive dump (benchmarks/brief_reconstruction.py). What a resuming
session actually reads — the budgeted, supersession-aware brief vs pasting back the
whole log. As history grows the dump balloons and keeps carrying every retraction;
the brief stays bounded (a soft cap) and contradiction-free while retaining all
key items (e.g. at 228 events: 3063→217 tokens, 14×, 3 contradictions → 0).
These measure the mechanism honestly rather than staging a head-to-head against another store — a fair cross-system run needs both under identical retrieval plus an LLM endpoint we can't reproduce in CI (see ADR-0008).
"Tokens" here and elsewhere in this README are estimated as
len(text) / 4(model-agnostic), not counted with a real tokenizer.
How it works
The markdown vault is the source of truth — human-readable, openable in Obsidian, your data on your disk. The SQLite + FTS5 index is derived from the vault and can be rebuilt at any time; it powers ranking, the token budget, and cross-project full-text search.
See docs/architecture.md and the
ADRs for the design rationale.
MCP tools
Tool | When Claude calls it |
| At session start — load where the last session left off. |
| As work happens — record goals, decisions, dead-ends, files, questions, next steps. |
| When the user references past or other-project work. |
| To record durable project knowledge (architecture, conventions, components). |
| At session end — finalise the session and emit the brief. Pass the same |
| To compress old sessions into durable notes (opt-in, needs an LLM). |
| To sync memory across devices — pull, commit, and push the vault's private git remote (opt-in). First call with a repo URL configures it; then a bare call syncs. See Multi-device sync. |
Also exposed: an MCP resource session://brief and a prompt resume for
auto-loading the brief at the top of a session.
log_event types: goal, decision, deadend, file, question, next_step.
Cost & API keys
No subscription. No required API keys. The core is free and fully local — your memory is plain files on your disk, and handoff-mcp never phones home (no hosted service, no telemetry).
Capability | Needs a model / key? |
Memory, brief, supersession, keyword search, cross-project, importers | No — local, offline, free |
Semantic recall (optional) | No by default ( |
Consolidation (optional, occasional) | A model — your own key (a few cents, run rarely; it's not a hot path) or a local model |
So most of the value costs nothing and needs no key. The optional layers either run locally or use your own provider — you're never locked into ours.
Semantic recall (optional)
Keyword search (FTS5/bm25) is the default and needs nothing extra. You can enable a semantic layer that fuses keyword and embedding similarity with Reciprocal Rank Fusion:
HANDOFF_SEMANTIC=1 handoff-mcp # turn the layer on (default: hashing backend)The backend you pick decides whether this actually understands paraphrases.
The default hashing backend is a lexical baseline — it hashes tokens, so it
adds fuzzy lexical matching (and demonstrates the hybrid pipeline) but does not
recall on meaning when the words differ. For genuine paraphrase-tolerant recall,
choose local or openai, which use learned embeddings.
Pluggable embedding backends, selected with HANDOFF_EMBEDDER — one server,
no forks:
Backend | Install | Paraphrase? | Notes |
| — | No — lexical | Deterministic, offline, zero-dependency toy baseline (feature-hashing). Good for demos/tests; not real semantics. |
|
| Yes | Offline |
|
| Yes | Any OpenAI-compatible endpoint (OpenAI, Together, a self-hosted proxy, …). Set |
# Example: semantic recall via any OpenAI-compatible endpoint
pip install -e ".[semantic-openai,semantic]"
export HANDOFF_SEMANTIC=1 HANDOFF_EMBEDDER=openai
export HANDOFF_EMBED_BASE_URL=https://your-openai-compatible-endpoint/v1 HANDOFF_EMBED_API_KEY=sk-…
export HANDOFF_EMBED_MODEL=text-embedding-3-smallDesign (see ADR-0004):
Pluggable embedder behind an
Embedderprotocol — thehashingdefault is deterministic and dependency-free;openai/localplug in for real semantic quality without changing anything else.sqlite-vec is an accelerator, not a requirement (
.[semantic]) — vectors persist as BLOBs and search works with an exact cosine scan; ifsqlite-vecis installed and loadable, avec0table provides fast KNN with the same top-ranked results.The deterministic brief never consults embeddings — semantics only affect
search_memory.Reranking — recall results (any mode) are reordered by a deterministic blend of relevance + recency (time-decay) + importance, so fresh, high-priority memories surface first. No LLM; pass
rerank=Falseto get raw relevance order.Incremental embedding — events are immutable, so startup only embeds new events (cached vectors are reused); the cache self-invalidates if the embedding model's dimension changes. This keeps heavier local models practical.
To use a lighter/faster local model instead, set HANDOFF_EMBED_MODEL (e.g.
Alibaba-NLP/gte-multilingual-base, 305M/768-dim — also set
HANDOFF_EMBED_TRUST_REMOTE_CODE=1 as that model requires it).
Memory consolidation (optional)
Over a long-lived project the episodic log grows without bound — a volume problem, not just an indexing one. Consolidation ("sleep") folds it down:
HANDOFF_LLM_MODEL=gpt-4o-mini handoff-mcp # enables the consolidate toolconsolidate(project?, older_than_days?) distils old finished sessions' active
decisions into the durable entity notes (Architecture, Decisions, Dead-ends, …),
then archives the originals to <project>/archive/ and drops them from the
active index. So the vault shrinks but the lasting knowledge — which the brief
already surfaces — is kept.
It is the only step that calls an LLM, and it's off unless
HANDOFF_LLM_MODELis set (OpenAI-compatible; reuses the embedder's endpoint settings). The brief, search, and supersession stay deterministic.Only active events are distilled — a retracted decision is never immortalised. Dead-ends are kept as cautionary facts.
Originals are archived, not deleted (auditable, reversible).
See ADR-0006.
Import existing history
Bootstrap a project's memory from data you already have, so it's useful from minute one instead of empty:
handoff-import git ./my-repo --project my-project # commit history → memory
handoff-import claude session.jsonl --project my-project # a Claude Code transcriptgit turns each commit into a decision (the subject) plus a files-touched note, timestamped at the commit date — fully deterministic, no LLM.
claude pulls the first prompt as a goal and file edits as file events from a Claude Code transcript (best-effort).
Import is idempotent (ids derive from the source), so re-running only adds what's new. Writes into the same shared vault (
HANDOFF_VAULT).
Quickstart
uv venv && uv pip install -e ".[dev]"
# Run the two-session demo: session 1 works, session 2 reads the brief.
python examples/two_sessions_demo.pyConnect your MCP client
Claude Code — one-minute install (recommended):
/plugin marketplace add kirill-sviridov/handoff-mcp
/plugin install handoff-mcp@handoff-mcpThat bundles the server (auto-installed from PyPI via uvx — needs uv on
PATH), a session-start hook that loads the memory protocol, and the
session-handoff / session-planning skills. Manual setup below is for other
clients (or if you prefer explicit config).
handoff-mcp speaks standard MCP over stdio, so it works with any MCP client —
Claude, Cursor, Codex, Kilo Code, Windsurf, Cline, VS Code, Zed, … The config is
essentially the same everywhere; only the file location (and, for Codex, the
format) differs.
Canonical config — the mcpServers JSON block used by Claude, Cursor, Kilo
Code, Windsurf, Cline, and most others:
{
"mcpServers": {
"handoff": {
"command": "handoff-mcp",
"env": {
"HANDOFF_VAULT": "/path/to/your/vault",
"HANDOFF_PROJECT": "my-project"
}
}
}
}Client | Where it goes |
Claude Code |
|
Claude Desktop |
|
Cursor |
|
Kilo Code | Settings → MCP → Add Server → Local (stdio), or |
Windsurf |
|
Cline / Roo Code | the extension's MCP panel → |
VS Code (Copilot) |
|
Codex CLI uses TOML in ~/.codex/config.toml (or run codex mcp add):
[mcp_servers.handoff]
command = "handoff-mcp"
[mcp_servers.handoff.env]
HANDOFF_VAULT = "/path/to/your/vault"
HANDOFF_PROJECT = "my-project"VS Code uses "servers" and an explicit type:
{ "servers": { "handoff": { "type": "stdio", "command": "handoff-mcp",
"env": { "HANDOFF_VAULT": "/path/to/your/vault", "HANDOFF_PROJECT": "my-project" } } } }Notes:
handoff-mcpmust be onPATH— install it as a tool (uv tool install handoff-mcp; or from source,uv tool install git+https://github.com/kirill-sviridov/handoff-mcp) or, from a checkout, use"command": "python", "args": ["-m", "handoff_mcp.server"].Set
HANDOFF_PROJECTper agent/repo; keepHANDOFF_VAULTpointed at the same shared vault across all of them (see below). Since 0.4.0, whenHANDOFF_PROJECTis unset the project defaults to the git-root/cwd basename, giving per-repo namespaces with zero config; setting it explicitly still wins.
Where your memory lives
One central vault, with a folder per project inside it:
~/.handoff-mcp/vault/ # HANDOFF_VAULT (default; override per machine)
├── .index.db # derived SQLite index — rebuildable, gitignore it
├── my-project/
│ ├── sessions/<id>.md # episodic notes
│ └── entities/<Name>.md # durable knowledge
└── another-project/…One vault, not one-per-repo. Cross-project recall (
search_memory) only works because every project lives in a single store. So point every agent'sHANDOFF_VAULTat the same directory and just varyHANDOFF_PROJECT.It lives outside your code repos, so it never gets committed into your work projects by accident — your project repos stay clean.
Want backup / multi-machine sync? The vault is plain markdown, so version it on its own (a private git repo, Obsidian Sync, Dropbox…). For built-in git sync across devices — pull-on-start, push-on-checkpoint, conflict-free entity merges — see Multi-device sync;
handoff-sync --setupconfigures the remote and gitignores the derived index for you.Prefer memory that travels with one repo? Point
HANDOFF_VAULTinside that repo (e.g../.handoff) — but then search sees only that project. The shared vault is recommended.
Multi-device sync (optional)
Your vault is just a private git repo, so memory can follow you across machines. Sync is strictly opt-in — with no git configured, memory works fully on one device.
Tier | Setup | You get |
Local-only (default) | nothing | full memory, one device, no account |
Manual |
|
|
Automatic | above + | pull at session start, push at checkpoint |
Entity notes merge cleanly across machines via git's built-in union driver
(*/entities/*.md merge=union in the vault's .gitattributes, written by setup).
In a shell-less client (e.g. Cursor), just ask the agent to sync — the sync
tool needs no terminal. Setup needs working git auth (gh auth login or an SSH
key); if a push fails, the command tells you exactly what to fix.
Agent integration
Knowing when to use it. The server never pushes anything to the model; the model decides when to call the tools. Four layers make that reliable, from most portable to most capable:
Tool descriptions (built in) — every tool says when to call it. Works in any MCP client.
Server
instructions(built in) — a short ritual the server sends on connect (load the brief at start, log as you work, checkpoint at the end). Portable across Claude Desktop, Cursor, and other MCP clients.Claude Code skills (
skills/) — encode the workflow and, crucially, trigger on colloquial cues:session-handoff— when you say "го в следующую сессию" / "that's it for today", the agent knows tocheckpointon its own. It also bootstraps the project's instruction file on first use (CLAUDE.md, orAGENTS.md/.cursor/rules/handoff.mdc/.windsurfrulesper client).session-planning— optional companion: breaks a big task into session-sized chunks and persists the plan in memory.
Install by copying into your skills dir:
cp -r skills/handoff skills/planning ~/.claude/skills/ # user-wide # or .claude/skills/ inside a specific project(Skills are a Claude Code / claude.ai feature; other agents rely on layers 1–2.)
For non-Claude clients, drop the memory block into the project's instruction file with the
handoff-initCLI (idempotent):handoff-init # CLAUDE.md handoff-init --client codex # AGENTS.md · --client cursor / windsurfClaude Code plugin — layers 1-3 in one install; see Connect your MCP client.
For Claude Code specifically, also add this to your CLAUDE.md so the brief loads
automatically even without the skill:
At the start of a session call
get_brief. Record decisions, dead-ends and the next step withlog_eventas you work — one atomic item per call (1-2 sentences with the why), not a whole-session summary; reference durable notes as[[Entity]].checkpointbefore you stop. When I mention past work or another project, callsearch_memory.
Limitations
Honest edges of v0.4, so you know what you're adopting:
Supersession is explicit, not inferred. handoff-mcp never decides on its own that one memory retires another — the agent must say so, via
supersedes(by id) orsupersedes_query(by best match). That is deliberate (it's what keeps the brief deterministic and auditable), but it means the quality of the memory depends on the agent actually logging retractions. It won't silently de-duplicate contradictions the way an LLM-extraction store attempts to. Exception:next_step— a newly logged next step auto-retires prior sessions' active next steps (rule-based, recorded on the event; ADR-0009). If a retired step was still valid, re-log it.It depends on the agent's discipline. The server never pushes anything; value comes from the model calling
log_event/get_brief/checkpointat the right moments. The tool descriptions and the skill nudge this, but a client that never calls the tools gets an empty vault. Cross-session memory is only as good as what got logged.The default semantic backend (
hashing) is lexical, not paraphrase-aware. Real paraphrase recall needslocaloropenai(see Semantic recall). The deterministic brief itself never uses embeddings.The token budget is soft. It bounds event content; section headings and the "Related knowledge" block are chrome on top, so the rendered brief can sit a little above the number. It keeps the brief bounded and flat as history grows — it is not a hard byte cap.
Single-process freshness. One vault can be shared across processes/agents (SQLite WAL + a busy timeout let writers coexist), but a running process refreshes its view of the vault at startup (
_sync_index) — it picks up its own writes live, but another process's new events only on the next launch (async— manual or theHANDOFF_AUTO_SYNCpull-on-brief — re-indexes mid-session when it pulls new events). For concurrent threads inside one process, access to the shared index is serialised by a lock.Personal/team scale. Ranking loads a project's events into memory; this is fine for thousands of sessions, not tuned for millions (see ADR-0005 for the localized fixes if that day comes).
Development
uv pip install -e ".[dev]"
ruff check . && mypy && pytest
python examples/two_sessions_demo.py # the hand-off in action
python examples/demo_presentation.py # paced/narrated version (for recording a GIF)
python examples/stdio_smoke.py # run it as a real stdio MCP server
python benchmarks/brief_reconstruction.py # brief vs naive full-dump
python benchmarks/supersession_benchmark.py # supersession on vs off, in isolationLicense
MIT — see LICENSE.
Available Tools
7 toolscheckpointAIdempotent
Close out the current session and produce its hand-off brief.
Call this at the END of a session, or when the user signals they're stopping or switching context. It finalises the session note and returns the brief the next session will read.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project namespace to close; defaults to the current session's project. Pass the SAME project you logged events under — a session that logged with project='X' must be checkpointed with project='X', or its note is left open and the returned brief is the wrong (empty default) one. | |
| summary | No | Optional one-line human summary of what this session accomplished. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond the annotations: it reveals that checkpointing closes the session, finalizes the note, and returns a brief for the next session. It also warns about the project matching requirement, which is a critical behavioral detail not present in annotations. No contradiction with annotations (idempotent, not read-only, not destructive).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is highly concise: three sentences that front-load the purpose, then add usage timing and outcome. Every sentence adds value, with no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema (not shown but indicated), the description does not need to detail return values. It covers the tool's core function, usage context, and a critical warning about project matching. This is sufficient for an AI agent to decide when and how to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, so the schema already defines parameter meanings. The main description does not add parameter information beyond the schema. According to guidelines, baseline is 3 when coverage is high, and the description does not improve upon the schema's parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's operation: 'Close out the current session and produce its hand-off brief.' It uses a specific verb ('close out') and resource ('current session'), and distinguishes from siblings like 'log_event' and 'get_brief' by explicitly marking it as an end-of-session action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: 'Call this at the END of a session, or when the user signals they're stopping or switching context.' It explains what happens ('finalises the session note and returns the brief'), but does not explicitly list when not to use it or contrast with sibling tools like 'get_brief' or 'consolidate'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
consolidateADestructive
Compress old finished sessions into durable entity notes ('sleep').
Call this when a project's session log has grown large and you want to reclaim space while keeping the lasting knowledge: it distils old sessions into the durable entity notes and archives the originals. Requires a configured LLM (HANDOFF_LLM_MODEL); it is the only step that uses one.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project to consolidate; defaults to the current project. | |
| older_than_days | No | Only fold sessions finished more than this many days ago. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint: true. The description adds operational details: it 'distils old sessions into durable entity notes and archives the originals', clarifying the destructive nature. It also reveals the LLM requirement, which is 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise: three sentences, no redundancy. Purpose is front-loaded; each sentence adds value: what it does, when to use it, and a key requirement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (two optional parameters, output schema present), the description covers purpose, usage scenario, and a critical dependency. It does not describe return value but an output schema exists. Some details about parameter defaults (current project) are implied but not explicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description does not add significant meaning beyond what the schema already provides for the two optional parameters (project and older_than_days). It mentions 'old finished sessions' but does not elaborate on parameter usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool compresses old finished sessions into durable entity notes, using a specific verb and resource. It distinguishes itself from sibling tools (checkpoint, get_brief, etc.) by being the only one focused on consolidation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells when to use the tool: when a project's session log is large and space needs to be reclaimed. It also mentions a prerequisite (requires configured LLM model). However, it does not explicitly state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_briefARead-only
Load the prioritised hand-off brief for a project.
Call this at the START of a session, before doing anything else, to learn where the previous session left off: the goal, the next step, key decisions and their rationale, dead-ends already ruled out, and open questions. Retracted decisions are omitted. This is a curated brief, not a raw context dump.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project to summarise; defaults to the current project. | |
| token_budget | No | Max tokens for the brief; lowest-priority items drop first. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true (safe, non-destructive). Description adds that the brief is curated, omits retracted decisions, and is not a raw context dump – giving the agent clear expectations about the content. No contradictions 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise, front-loaded with the core purpose. Every sentence serves a purpose: what it does, when to call it, what it contains, and clarifying it's curated. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema (not shown but indicated), the description doesn't need to detail return format. It covers all relevant aspects: project focus, content summary, and exclusion of raw dumps. Sibling tools are distinct, so no missing comparisons.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (baseline 3). Description adds semantics for token_budget: 'lowest-priority items drop first', explaining behavior beyond the schema's 'Max tokens'. Also notes project defaults to current project, though schema already says default null. Slight value over baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it 'Load the prioritised hand-off brief for a project' and explains what the brief contains (goal, next step, key decisions, etc.). Distinguishes from sibling tools, none of which serve this specific session-start function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to call at the 'START of a session, before doing anything else'. Provides clear when-to-use context and implicitly advises against using it mid-session.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_eventA
Record a progress signal for the current work session.
Call this proactively as work happens — every time you set or change the goal, make a non-trivial decision (and why), hit a dead-end worth not repeating, touch an important file, surface an open question, or decide the next step.
Keep each event ATOMIC and concise: one item per call, 1-2 sentences. Log several small events rather than dumping a whole session summary into one — the brief is meant to stay skimmable. Reference durable notes inline as [[Entity]] so they link in the brief's "Related knowledge".
This is how the next session inherits your context. Returns the new event
id (use it later in supersedes). If supersedes_query retired a prior
event, a second line names which id was retired (or notes that none
matched), so the retraction is auditable.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | One of: 'goal' (what this session is achieving), 'decision' (a choice made — include the rationale), 'deadend' (something tried that failed — so it isn't repeated), 'file' (a file touched or relevant), 'question' (an open question), 'next_step' (the concrete next action). | |
| content | Yes | One atomic item in 1-2 sentences (a decision + its why, a single dead-end, one next step) — not a multi-paragraph session summary. Reference durable notes inline as [[Entity]] to link the graph. | |
| project | No | Project namespace; defaults to the current session's project. | |
| importance | No | Priority 1-5 (5 = critical). Higher items survive the brief budget. | |
| supersedes | No | Ids of earlier events this one makes obsolete (e.g. a reversed decision). Superseded events are excluded from future briefs. | |
| supersedes_query | No | Retire a prior event you don't have the id for: the single best-matching ACTIVE event of the SAME type in this project is found by keyword search and superseded. Use when you change a past decision but don't know its id. The retired id is reported back and recorded, so it stays auditable. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate a non-read-only, non-idempotent, non-destructive tool. The description adds behavioral context beyond annotations: it returns the new event id, and if 'supersedes_query' is used, it reports which prior event was retired. It also notes that superseded events are excluded from future briefs, providing transparency about side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately long (200+ words) but well-structured into paragraphs that front-load the purpose and then detail usage guidelines and return behavior. Every sentence adds value, though some minor redundancy could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 parameters, 2 required, output schema), the description fully covers when to use, how to use (atomic, concise, inline links), return values (event id, optional retirement note), and the lifecycle of events (superseding, budget filtering). No gaps identified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with each parameter well-described. The description adds high-level guidance beyond schema: e.g., 'atomic and concise', 'reference durable notes inline as [[Entity]]', and explains the interplay between 'supersedes' and 'supersedes_query'. This extra context justifies a score above the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Record a progress signal for the current work session.' It specifies the verb 'Record' and the resource 'progress signal', and distinguishes from sibling tools like 'checkpoint' and 'note_entity' by detailing the exact types of events to log (goal, decision, dead-end, etc.).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive guidance on when to use: 'proactively as work happens' with specific triggers (goal changes, decisions, dead-ends, file touches, questions, next steps). It also explicitly advises how to NOT use the tool: 'Keep each event ATOMIC and concise', 'not a multi-paragraph session summary'. This helps the agent decide between this tool and others.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
note_entityA
Record durable, long-lived project knowledge on an entity note.
Use this (rather than log_event) for facts that outlive a single session: the system's architecture, coding conventions, what a component does, or standing open questions. These notes are linked from sessions via [[wiki-links]] and form the project's knowledge graph. Returns the entity name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Entity name, e.g. 'Architecture', 'Conventions', 'Auth Service', 'Open Questions'. Becomes a [[wiki-link]] target. | |
| content | Yes | A durable fact about this entity to remember long-term. | |
| project | No | Project namespace; defaults to the current project. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false. The description adds that notes are linked via wiki-links and returns the entity name, which are useful behavioral traits beyond annotations. Could be improved by noting if notes are overwritten, but overall good.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences plus an example list, front-loaded with purpose. No unnecessary words; every sentence adds information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema and annotations, the description is nearly complete. It clearly explains the tool's purpose, usage, parameters, and return value. Minor gap: does not specify whether existing notes are updated or appended, but overall sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, but the description adds value by explaining that 'name' becomes a wiki-link target and providing examples, and 'content' is a durable fact. It also clarifies the default for 'project'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb and resource: 'Record durable, long-lived project knowledge on an entity note.' It also distinguishes from the sibling 'log_event' by specifying use for facts that outlive a single session, and mentions wiki-links and knowledge graph for added clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use this tool vs 'log_event': 'Use this (rather than log_event) for facts that outlive a single session' and provides concrete examples like architecture, conventions, etc.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_memoryARead-only
Search memory across sessions and projects.
Call this whenever the user references past work, a prior decision, or
ANOTHER project — e.g. "in one of my projects we did X", "how did we solve
Y before", "what did we decide about Z", "last time". Use scope='all'
(the default) to recall across every project; scope='current' to stay in
this one. Returns matching past events with their project, content, and
id — the id can be fed straight into log_event's supersedes to retire
a decision you just found to be outdated.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results to return. | |
| query | Yes | What to look for, in natural language or keywords. | |
| scope | No | 'current' = this project only; 'all' = every project in memory. | all |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=false, which match the read-only search behavior. The description adds context about return structure (project, content, id) and a usage tip (id can be fed into log_event's supersedes), enhancing transparency 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise yet comprehensive. It starts with a clear purpose, then lists use cases, parameter guidance, and output details—all in a few sentences without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (searching multiple sessions/projects), the description covers when, how, and what to expect, plus a practical usage tip. With an output schema present, the description need not detail return schema, but it adds value explaining the id's role.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. However, the description adds valuable context beyond schema: explaining scope meaning in context and how the returned id can be reused, providing extra semantic help.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Search memory across sessions and projects,' with a specific verb and resource. It distinguishes this tool from siblings like 'log_event' or 'checkpoint' as the only search tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to call (user references past work) with concrete examples. It explains the 'scope' parameter options and their use cases, helping the agent choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
syncAIdempotent
Sync this device's memory vault with its private git remote.
Use when the user wants their memory on another device, or to push/pull now. If the vault isn't configured yet, this returns setup instructions — relay them and ask the user for a private repo URL, then call again with remote_url. Once configured, a bare call pulls remote work, commits local changes, and pushes. Safe to call repeatedly.
| Name | Required | Description | Default |
|---|---|---|---|
| remote_url | No | Only for FIRST-TIME setup: a PRIVATE git repo URL to bind this vault to (the user provides it; they can create one via `gh repo create <name> --private`). Omit once configured — a plain call pulls, commits, and pushes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses all behaviors: returns setup instructions if not configured, otherwise pulls remote work, commits local changes, and pushes. No contradiction with annotations (idempotentHint=true aligns with 'Safe to call repeatedly').
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with main purpose, then usage and edge cases. No waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Fully covers setup and normal operation; output schema handles return value details. Adequate for agent decision-making.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% coverage for the single parameter remote_url, and description elaborates on its first-time-only usage and default behavior when omitted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb 'Sync' with specific resource 'memory vault with private git remote'. Uniquely distinguishable from sibling tools that perform different actions like checkpoint, consolidate, or search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'when the user wants their memory on another device, or to push/pull now.' Also provides setup instructions and notes that it's safe to call repeatedly.
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.
7 tool updates
v0.4.0- First observed
checkpoint - First observed
consolidate - First observed
get_brief - First observed
log_event - First observed
note_entity - First observed
search_memory - First observed
sync
TDQS
Scored across 7 tools
Each tool has a clearly distinct purpose: checkpoint ends sessions, consolidates compresses old sessions, get_brief loads the brief, log_event records progress, note_entity stores durable knowledge, search_memory searches across projects, and sync synchronizes with git. No overlap in functionality.
All tool names use a consistent snake_case pattern (e.g., get_brief, log_event, note_entity), which is predictable and easy to understand. No mixing of styles.
7 tools is well-scoped for the server's purpose of managing handoff briefs and memory. Each tool covers a necessary operation without being excessive or insufficient.
The tool set covers the full lifecycle: starting a session (get_brief), recording progress (log_event, note_entity), searching memory (search_memory), ending sessions (checkpoint), compressing old sessions (consolidate), and syncing (sync). No obvious gaps.
Maintenance
Related MCP Connectors
Persistent AI memory shared across Claude, ChatGPT, coding agents, and compatible MCP clients.
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
- HeirmosOAuthcom.heirmos
Persistent memory shared across Claude, ChatGPT, Grok and other MCP clients.
Persistent memory for AI agents — log and recall conversation context over MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that provides persistent memory and conversation continuity for Claude Desktop and Claude Code, allowing users to save and restore project context when threads hit token limits.MIT
- AlicenseNot gradedqualityDmaintenanceProvides Claude with a persistent local memory and structured knowledge graph to track project states, tasks, and historical decisions across different chat sessions. It enables users to recall information using keyword relevance, time-travel queries, and dependency analysis for complex project management.MIT
- AlicenseNot gradedqualityDmaintenanceProvides persistent memory for AI coding agents through the Model Context Protocol, enabling them to store and retrieve project knowledge across sessions.27 npmMIT
- AlicenseNot gradedqualityDmaintenanceGives AI agents durable project memory via the Model Context Protocol, allowing them to read tasks, record decisions, search context, and sync snapshots to the cloud.4 npmMIT