brain-core
This MCP server gives an agent a local, persistent memory and the tools to search it, write to it, manage sessions, capture sources, and check health.
Recall memory (
brain_recall): search facts, patterns, decisions, corrections, notes, raw sources, and relations across vault, SQLite, Hindsight, and graph; get deduplicated, ranked, token-capped results with scope/format/limit controls.Remember things (
brain_remember): write one item to vault, SQLite, Hindsight, and graph; handle duplicate detection, fact-change banners, kind-specific fields, domains, sources, and secret refusal.Run sessions (
brain_session): start with brief/state/models/mission recalls/recovery, or end by archiving, draining queues, rewriting state/critique/sync, moving trait signals, and marking clean close.Distill sources (
brain_distill): capture URLs, GitHub repos, YouTube, PDFs, local files, or pasted text into an immutable raw folder with provenance and dedup.Check health (
brain_status): report store reachability, wiki lint, context token size, unclosed sessions, pending decisions, and twelve trait signals.
brain-core
A memory for your Claude Code agent that survives the session. One local MCP server, five tools, a markdown vault you can read, an eval that proves recall. Installs with one command.
brain-core gives a Claude Code agent a long-term memory that lives on your disk. You name the agent, you tell it who you are, and from then on every session opens with yesterday's brief, the decisions you made, the facts that changed and the corrections you gave. It remembers by writing markdown files you can open in any editor, and it finds things again through a local SQLite index plus Hindsight, a self-hosted vector memory. Nothing leaves your machine except the LLM calls you already make.
It is for one person running one or more agents on their own computer: a solo developer, a founder, anyone tired of re-explaining their project every morning. It is not a hosted service and not a team product.
Is it an MCP server or a tool?
Both. One Python package, three ways in:
Piece | What it is | Who uses it |
| an MCP server that Claude Code starts from the agent's | the agent, every session, without you touching it |
| a CLI: | you, once at setup, then cron |
| the Python library both of the above sit on | the eval runner, the demo script, your own scripts |
To a Claude Code user: an MCP server with five memory tools and a one-line installer. To a Python developer: a memory library with an MCP front end.
curl -fsSL https://raw.githubusercontent.com/xy-claude/brain-core/main/install.sh | bash -s -- --agent Atlas --user AlexThe problem
Every session with a coding agent starts from zero. You explain the project again, the decision you made last week again, the thing it got wrong on Tuesday again. Memory add-ons exist, but they put your notes in someone's cloud, expose 30 tools the agent cannot choose between, and nobody shows you an eval.
brain-core is the opposite: local, five tools, markdown files you own, and a test suite that reports hit rates.
Related MCP server: ChatCrystal
How it works
brain initscaffolds an agent folder. It writes aCLAUDE.mdwith the agent's name and yours, five rule files (identity, doctrine, authority, memory, system), three skills, a safety hook, an.mcp.jsonand an empty vault. Claude Code reads that folder as a project, so the agent knows how to use its memory from the first message.brain serveruns as an MCP server inside Claude Code. It exposes exactly five tools. The agent calls them the way it calls any other tool; you never run them by hand.Every session has a shape. The agent opens with
brain_session('start'), which returns one block: today's brief, the executive state, the mental models, a recall per active mission, and a flag if the previous session crashed. It closes withbrain_session('end'), which files the day's archive and rewrites state for tomorrow.Memory is written, not inferred. When you say something worth keeping, the agent calls
brain_remember(text, kind). The text goes to the vault first, then the SQLite index, then Hindsight, then the relations table, and the reply says what each layer did. A duplicate is skipped. A fact whose value changed gets a⚠ Fact changedbanner and the old line stays, so the history is visible.Recall is one query across every store.
brain_recall(query)searches the vault, the index and Hindsight at once, deduplicates, ranks by relevance and recency, and caps the reply at 6k tokens so it never floods the context.Two cron jobs do the housekeeping.
brain dailywrites the next morning's brief and backs up Hindsight.brain weeklyarchives sessions older than 30 days into a monthly summary and refreshes the mental models.
flowchart LR
CC[Claude Code] -->|MCP, 5 tools| B[brain serve]
B --> V[(vault/ markdown)]
B --> S[(brain.db SQLite + FTS)]
B --> H[(Hindsight vector memory)]
B --> G[(relations table)]
CRON[brain daily / weekly] --> V
CRON --> HThe five tools
Tool | One call does |
| the whole start block: daily brief, executive state, mental models, a recall per mission, inbox count, and a flag if the last session crashed |
| one query across every store, the Claude Code transcripts of this folder included, deduplicated, ranked by relevance and recency, capped at 6k tokens; |
| writes vault → SQLite → Hindsight → graph and reports each layer. Near-duplicates are skipped; a changed value gets a |
| captures a URL, GitHub repo, YouTube video, PDF, file or pasted text into an immutable |
| drains the queue, closes the day's session file, rewrites state and critique, writes the clean-close marker |
Plus brain_status() for health in one call: which stores are up, how many tokens the always-loaded context costs, whether a session is open, and which decisions are waiting on you.
Install
Before you start
You need | Why | Check |
macOS, or Linux with systemd | the installer sets up a background service and cron |
|
about 2 GB of disk and 10 minutes | Hindsight ships an embedded Postgres and a CPU embedding model | |
an Anthropic API key, or a Claude Code login | Hindsight uses an LLM to reason over memories |
|
Claude Code | the agent runs inside it; the installer adds it if missing |
|
Pick two names before you run the command: the agent's name (--agent), which becomes its folder and identity, and your own (--user), which is how the agent addresses you. Both can be changed later by editing CLAUDE.md.
macOS, one line
curl -fsSL https://raw.githubusercontent.com/xy-claude/brain-core/main/install.sh | bash -s -- --agent Atlas --user AlexWhat it does, in order. Re-running skips what is already there, so after a failure you fix the cause and run the same line again.
== 1/8 Xcode command line tools present
== 2/8 Homebrew present
== 3/8 uv, gh, gitleaks, node, Claude Code
== 4/8 brain-core (v0.3.0) installed with uv tool
== 5/8 Agent Atlas at ~/Agents/Atlas 31 files written
== 6/8 Hindsight (required store) service: healthy
== 7/8 Cron daily 06:07, weekly Sun 07:13
== 8/8 Doctor Health check: OKStep | What happens | If it stops here |
1 | checks for | macOS opens an install dialog; finish it, then re-run |
2 | installs Homebrew if missing | Homebrew asks for your password itself |
3 | installs | anything already present is left alone |
4 | installs the |
|
5 | runs | an existing |
6 | installs Hindsight as a launchd service on | first start downloads the embedding model; give it a few minutes |
7 | installs | |
8 | runs |
|
After the installer
Two things the installer cannot do for you:
export ANTHROPIC_API_KEY=sk-ant-... # add it to ~/.zshrc too
brain hindsight install # copies the key into ~/.config/hindsight/env (mode 600) and restarts the service
claude # sign in to Claude Code onceThe installer prints a note if the key was not in your shell when it ran. If you would rather not use an API key, pass --provider claude-code and Hindsight uses your Claude Code login instead. That mode is for personal use only.
Flag | Meaning |
| the agent's name (required) |
| how the agent addresses you |
| where the agent lives, default |
|
|
| read the key from a variable other than |
| a folder copied over the generic rules last, for your own doctrine |
| the Hindsight web UI on http://localhost:9999 |
| pin a git tag instead of the PyPI release |
Linux
The same one line. It needs git and curl already present. It then installs uv from astral.sh, installs Claude Code with npm when node is present, runs Hindsight as a systemd --user service, and writes the two jobs into your user crontab as tagged lines it can find and replace on re-run.
Manual, any platform
uv tool install brain-core-mcp # or: uv tool install git+https://github.com/xy-claude/brain-core@v0.3.0
brain init Atlas --path ~/Agents/Atlas --user Alex
brain hindsight install # launchd on macOS, systemd --user on Linux
brain cron install ~/Agents/Atlas
brain doctor ~/Agents/AtlasCheck it worked
brain doctor ~/Agents/AtlasIt prints the agent name, the config path, row counts per table, and Health check: OK. Store health shows up in the first brain_session('start') reply and in brain_status(). The common problems:
Symptom | Cause | Fix |
| the |
|
| wrong path | pass the agent folder, or the |
| the service is still starting, or not installed | wait a minute; still down, run |
installer note | the key was not in the shell when the service was installed | export it, then |
Claude Code shows no | it was started outside the agent folder |
|
First session
cd ~/Agents/Atlas && claudeThe agent's CLAUDE.md tells it to open with brain_session('start'). What comes back:
{
"session_id": "s-20261102-a1b2c3",
"brief": "# Daily Brief — 2026-11-02 ...",
"executive_state": "## Primary Objective ... ## Top Missions ... ## Pending Decisions ...",
"mental_models": {"active-priorities": "..."},
"missions": {"M-001 first mission": [ ...3 recall hits... ]},
"inbox": 0,
"recovery": null
}On day one the brief is empty and the executive state is the template. That is expected. Spend the first session telling the agent what you are working on: the project, the stack, the decisions already made, how you like to work. Each statement that matters becomes a brain_remember call, and the reply shows what every layer did:
{"status": "written", "layers": {"vault": {"status": "written", "detail": "facts.md › System"},
"sqlite": {"status": "written"},
"hindsight": {"status": "written", "detail": "op 162bdbaa"}}}Things to try in that first session:
State a fact, then change it. "The API listens on 8887." Later: "Correction, it is 8888." The second write returns a
⚠ Fact changedbanner andvault/facts.mdkeeps both lines.Give it a source. Paste a URL or a GitHub repo and ask it to distill it. The page lands in
vault/raw/untouched, and the agent compiles a page invault/knowledge/.Ask about something from earlier. "What did we decide about the database?" is one
brain_recallcall, and each hit names the file it came from.Open the vault in your editor. Every write you just saw is a line in a markdown file. Edit it if the agent got it wrong.
Say "thanks, we're done" and it runs brain_session('end'). Tomorrow at 06:07 brain daily writes the next brief from what you did today, and the next claude session opens with it.
What is in the agent folder
~/Agents/Atlas
├── CLAUDE.md identity and the five-tool protocol (3k tokens always loaded)
├── .claude/
│ ├── rules/ 01-identity 02-doctrine 03-authority 04-memory 05-system
│ ├── skills/ distill, session-end, brain-check
│ └── hooks/ block-dangerous-bash.sh (rm -rf, force-push, curl|sh …)
│ + recall of past sessions when a command fails
├── .mcp.json brain serve . + Hindsight
├── brain.yaml stores, session files, cron schedule
├── vault/ facts.md patterns.md decisions_log.md corrections.md
│ ├── sessions/ one file per day (HSAM)
│ ├── knowledge/ raw/ the LLM-wiki: immutable sources, compiled pages
│ └── executive_state.md objective, missions, pending decisions
└── data/brain.db SQLite + FTS5 + relations + transcript indexEverything is markdown or SQLite. Open the vault in Obsidian, grep it, commit it, delete a line. The agent will not mind.
Does it work?
The eval is part of the test suite and runs in CI.
Set | Hits |
28 recall tasks on a synthetic fixture vault (CI), stratified: 20 single-hop, 2 multi-hop, 1 knowledge-update, 2 abstention, 3 temporal, each run three times (pass^3) | 28 / 28 |
20 tune + 10 held-out recall tasks on the author's real vault, 7 months of sessions | 20 / 20 and 10 / 10 |
11 write scenarios: dedup, value-change banner, relation routing, secret refusal | 11 / 11 |
Growth: the fixture brain after thirty days of sessions scores higher than the same brain on day one on every defensible trait signal (CI) | holds |
The slices are the ones the memory benchmarks (LoCoMo, LongMemEval) say a single hit-rate hides: a changed value must outrank the stale one, an unanswerable question must return nothing, a question about a day must surface that day's archive. Recall takes about 1.7 s per query with Hindsight; a full start block is about 4 s and under 6k tokens.
python tests/eval/run_recall.py --config ~/Agents/Atlas/brain.yaml # your own vaultTwelve traits, innate and grown
A brain-core agent is born with twelve traits and grows them with experience. Innate is what brain init ships and what survives a cold start with the vault wiped; grown is what accumulates in the vault. brain_status() scores each from evidence on disk, and brain daily logs one line a day so the curve shows over weeks.
Memory | Control | Social |
Working memory | Learning | User model |
Episodic memory | Reasoning and planning | Authority |
Semantic memory | Decision | |
Procedural memory | Metacognition | |
Execution | ||
Goal management |
A trait never gets one number. It gets signals, each with a sample size and a verdict: defensible when the answer key comes from a file the agent did not write that session, cost when it is a size or an age, pending when the evidence does not exist yet. Artefact counts and self-written scores are not signals. The list and the research behind it: docs/TRAITS.md.
How memory is organised
Kind | Lives in | Written as |
fact |
|
|
pattern |
|
|
decision |
|
|
correction |
|
|
note |
| a bullet under an HSAM section |
relation |
| subject —[predicate]→ object |
raw |
| immutable source with sha256; the agent compiles |
Rules: idempotent by content hash, append-only, nothing deleted, secrets refused before any store sees them. Details in docs/VAULT_SCHEMA.md.
Requirements
macOS or Linux for the installer; the library and MCP run anywhere Python 3.12 does
Hindsight (MIT) as the vector store, installed for you. Postgres is embedded; embeddings run on CPU
an LLM key for Hindsight's reasoning, or a Claude Code login for personal use
On PyPI the package is brain-core-mcp (the plain name collides with an unrelated project); the command is still brain and the import is still brain_core.
Roadmap
SQLite-only mode for a first run without Hindsight
an
importfor existing notes folders
How it compares to claude-mem, mem0 OpenMemory and a plain CLAUDE.md: docs/COMPARISON.md. Shipped milestones: docs/MILESTONES.md. Design: docs/SPEC_v0.2.md. Threat model for a memory that reads untrusted text: docs/THREAT_MODEL.md.
Contributing
Issues and pull requests welcome. uv sync --all-extras --all-groups, then ruff check, mypy, pytest. See CONTRIBUTING.md.
License
MIT.
Available Tools
5 toolsbrain_distillAIdempotent
Capture an external source into the agent's immutable raw/ folder as a dated markdown file with provenance: source, title, author, published, sha256, word count. This is step 1 of /distill; compiling the knowledge page from the raw file is your job afterwards.
Use it for a web page (defuddle with a stdlib fallback), a GitHub repo README, YouTube
subtitles via yt-dlp, a PDF saved as bytes, a local file, or pasted text. Not for short
facts (brain_remember).
Fetches over the network for URLs. The same source or body a second time returns
`status: exists` and writes nothing. A `note` flags a thin capture (JS-only or paywalled
page) so you can read it in a browser and call again with `text`.| Name | Required | Description | Default |
|---|---|---|---|
| text | No | The body itself, when you already have it; skips fetching. | |
| title | No | Override the detected title. | |
| author | No | Override the detected author. | |
| source | Yes | A URL (web page, GitHub repo, YouTube video, PDF), a local file path, or a short name for pasted `text`. | |
| published | No | Publication date YYYY-MM-DD, if known. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses network fetching for URLs, that raw/ is immutable, that a repeat submission is idempotent and returns 'status: exists' without writing, and that a `note` flags thin JS-only or paywalled captures with a recommended retry path. Those are exactly the behavioral traits (side effects, retry semantics, partial-failure signaling) annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and scope in the first sentence, then capability, then exclusion, then behavioral caveats — a sensible order with no filler. It is on the dense side for a description, but nearly every clause carries decision-relevant 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?
An output schema exists, so return shapes need not be spelled out, and the description still covers the one return value an agent must branch on ('status: exists'). For a 5-param write tool with openWorld behavior, nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the field meanings are already documented; the description still adds real semantics by explaining the interplay between `source` and `text` ('call again with `text`' when a capture is thin) and that supplying the body skips fetching. That is useful beyond the per-field descriptions, though it does not cover `published`/`author` overrides explicitly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and destination ('Capture an external source into the agent's immutable raw/ folder as a dated markdown file') plus the provenance fields written. It also explicitly separates itself from brain_remember for short facts, so an agent can distinguish it from siblings 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Enumerates the supported input kinds (web page, GitHub README, YouTube subtitles, PDF bytes, local file, pasted text) and gives an explicit exclusion ('Not for short facts (brain_remember)'). It also positions the tool as step 1 of /distill and states what the caller must do afterward, which removes ambiguity about the follow-up workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
brain_recallARead-onlyIdempotent
Search the agent's long-term memory: facts, patterns, decisions, corrections, session notes, raw sources, entity relations and the Claude Code session transcripts of this folder, across SQLite, the markdown vault, Hindsight and the graph, returned as one deduplicated list ranked by relevance and recency and capped at about 6k tokens. scope='transcript' searches only what past sessions said and ran.
Use it before answering anything about past sessions, earlier decisions or the user's
preferences, and before brain_remember to avoid writing a duplicate. Not for health
checks (brain_status) and not for reading a file you already know the path of.
Read-only. Partial results are normal: `stores` lists hits per store and names any store
that was unreachable instead of failing the call. A value a `⚠ Fact changed` banner
superseded is returned but ranked below the banner.| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max results after dedup; default 10. | |
| query | Yes | Free-text search; keywords beat sentences. | |
| scope | No | 'all' (default), one kind (fact|pattern|decision|correction|note|raw|relation|transcript) or one store (sqlite|vault|hindsight|graph|transcripts). | all |
| format | No | 'concise' (default) for text to quote; 'detailed' adds ids, scores and store names for chained calls. | concise |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/idempotent annotations: it discloses deduplication, relevance+recency ranking, a ~6k token cap, and that partial results are normal with a `stores` field naming unreachable stores rather than failing. It also explains the `⚠ Fact changed` supersession ranking rule, which is non-obvious behavior an agent must interpret correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core verb and scope, then usage guidance, then behavioral caveats — a clear three-part structure with no filler sentences. It is somewhat dense and long, but nearly every clause carries actionable 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?
For a multi-store search with a full output schema, the description covers everything an agent needs to call and interpret it: scope semantics, ranking/cap, partial-failure behavior, supersession banners, and sibling routing. Return-value detail is correctly delegated to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds real meaning on top by explaining that scope='transcript' searches only what past sessions said and ran, and by framing results as a single deduplicated list. It does not re-explain limit/format, but the schema already does that well.
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?
Opens with a specific verb+resource ('Search the agent's long-term memory') and enumerates exactly what content kinds and backends are covered (SQLite, markdown vault, Hindsight, graph), plus the ranking/dedup/cap behavior. An agent can immediately tell this apart from brain_remember and brain_status without inspecting the schema.
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?
Explicit when-to-use ('before answering anything about past sessions, earlier decisions or the user's preferences, and before brain_remember to avoid writing a duplicate') and explicit when-not ('Not for health checks (brain_status) and not for reading a file you already know the path of'), naming the sibling to route to.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
brain_rememberAIdempotent
Write one memory item to every store in one call, in order: markdown vault, SQLite, Hindsight, and the entity graph (relations only).
Use it the moment the user states a fact, decision, correction, preference or
relationship worth keeping across sessions; one call per item. Not for whole documents
or web pages (brain_distill) and not for the end-of-session summary (brain_session).
Never deletes. A near-duplicate fact returns `status: duplicate` with the existing entry
and writes nothing. A changed value is appended under a `⚠ Fact changed` banner with the
old line kept, reported as `contradiction`. `layers` reports each store as
written|exists|pending|failed|refused, so a dead store is visible, never silent. Text
that looks like a secret is refused.| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | One of fact|pattern|decision|correction|note|raw|relation. | |
| text | Yes | The memory itself, one item, plain text. | |
| extra | No | Kind-specific fields. decision: title, reason, classification, confidence. correction: title, error, correction, rule, theme. relation: subject, predicate, object (or text 'S —[p]→ O'). note: section. | |
| force | No | Write even when a near-duplicate exists. | |
| domain | No | Topic tag such as 'trading' or 'system'; empty = none. | |
| source | No | Where it came from: a URL, file path or 'user'. | |
| mission | No | Mission id to tag, e.g. 'M-012'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that nothing is ever deleted, that a near-duplicate returns status duplicate with the existing entry and writes nothing, that changed values are appended under a '⚠ Fact changed' banner with the old line preserved and reported as a contradiction, and that secrets are refused. It also explains the per-store `layers` report (written|exists|pending|failed|refused), which makes partial-failure behavior legible. Only auth/permission requirements are left unstated, keeping it just off 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight paragraphs ordered by importance: what it does, when to use it, then the behavioral contract. The multi-line formatting is slightly denser than necessary and the store enumeration could be a single clause, but every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter multi-store write with an output schema present, the description covers the missing pieces: mutation semantics, duplicate/contradiction handling, partial-failure visibility, and safety refusals. An agent has enough to call it correctly and interpret the outcome without further context.
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 `kind`, `text`, `extra`, `force`, `domain`, `source` and `mission` are already documented in the schema, and the description does not add new syntax or format detail for them. It only implicitly reinforces `kind` values by naming fact/decision/correction/preference/relationship in the usage sentence and by pairing the duplicate behavior with `force`. Baseline 3 is appropriate when the schema carries the load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Write one memory item to every store in one call') and enumerates the target stores in write order (markdown vault, SQLite, Hindsight, entity graph). It explicitly names the two siblings it is not (brain_distill for documents, brain_session for summaries), so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete trigger ('the moment the user states a fact, decision, correction, preference or relationship worth keeping across sessions'), a cardinality rule ('one call per item'), and explicit exclusions mapped to the correct alternatives. Nothing about when-to-use is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
brain_sessionADestructive
Open or close the agent's working session. Call phase='start' once at the beginning of every conversation, before any other brain tool; call phase='end' once when the user signals they are done. Not for single facts (brain_remember).
start returns the whole context block: the cron daily brief with a stale flag,
executive state (objective, missions, pending decisions), the configured Hindsight
mental models, a recall per top mission, the staged-inbox count, and `recovery` when
the previous session never closed.
end drains the Hindsight queue, appends a close line to today's session archive,
replaces executive_state, session_critique and the cross-agent sync file with the
bodies you pass (or a stub built from this session's brain_remember calls), reports
which trait signals moved, and writes the clean-close marker. A second end overwrites
the first.| Name | Required | Description | Default |
|---|---|---|---|
| sync | No | end only: full markdown body of the cross-agent sync note. | |
| phase | Yes | 'start' or 'end'. | |
| critique | No | end only: full markdown body that replaces session_critique. | |
| session_id | No | Caller's session id; omit to keep the one the server opened. | |
| executive_state | No | end only: full markdown body that replaces executive_state. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=false; the description supplies the specifics behind those flags — which stored artifacts get replaced (executive_state, session_critique, cross-agent sync file), the stub fallback, and that a second end overwrites the first. Start's payload plus the `recovery` flag for an unclosed prior session is also disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the call rules, then split into start-return and end-effect paragraphs, each sentence carrying distinct information. It is dense and longer than most definitions, but no sentence is filler; the return-value detail is arguably redundant given an output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent session lifecycle tool with five params, the description covers timing, prerequisite ordering, mutation targets, fallback behavior, and re-invocation semantics. An output schema exists, yet the extra explanation of start's context block only reinforces the contract.
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 per-parameter descriptions already carry the baseline. The description goes further by explaining that the body parameters replace stored documents and that omitting them triggers a stub assembled from this session's brain_remember calls — behavior the schema never states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair and resource — opening or closing the agent's working session — and enumerates the two phase values inline. It also contrasts itself with brain_remember ('Not for single facts'), so an agent can separate it from siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit invocation rules: phase='start' once at the beginning of every conversation before any other brain tool, phase='end' once when the user signals they are done. It also names the exclusion (single facts) and routes that case to brain_remember.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
brain_statusARead-onlyIdempotent
Report the agent's health in one read-only call: reachability of every store (vault,
SQLite, Hindsight, graph), knowledge-wiki lint (pages missing from _index, index links
to missing pages, pages without sources, raw files never compiled), always-loaded
context size in tokens per file, the last session start and close ids with an
unclosed flag, the pending-decision count, and the twelve trait signals.
Use it when a store seems down, before maintenance, or when the user asks how the
memory is doing. Not a search (brain_recall). `ok` is false when any store is down or
lint found issues; `stores` names the failing one.| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, and closed-world behavior, but the description adds meaningful semantics: what each health check covers, when `ok` is false, and that `stores` names the failing store. This goes well beyond the annotation surface and clarifies the output's operational meaning.
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 dense but well organized: the first sentence front-loads the full scope, the second gives usage guidance, and the third explains the `ok`/`stores` semantics. Every sentence contributes to correct invocation or interpretation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters, full annotation coverage, an output schema, and sibling tools, the description supplies everything an agent needs: what is inspected, when to call it, how to interpret `ok` and `stores`, and what it is not (a search).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate. The baseline for a parameterless tool applies, and the description correctly does not invent parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Report the agent's health') and enumerates the exact checks performed across vault, SQLite, Hindsight, graph, wiki lint, context size, session ids, decisions, and traits. It also explicitly distinguishes the tool from brain_recall by stating 'Not a 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?
It gives clear triggers: when a store seems down, before maintenance, or when the user asks how memory is doing. It also names the closest alternative (brain_recall) and excludes search use, so an agent can route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.3.0- Changed
brain_recall1 field changed- changed
Input schema / properties / scope / descriptionPrevious value: -"'all' (default), one kind (fact|pattern|decision|correction|note|raw|relation) or one store (sqlite|vault|hindsight|graph)."New value: +"'all' (default), one kind (fact|pattern|decision|correction|note|raw|relation|transcript) or one store (sqlite|vault|hindsight|graph|transcripts)."
4 tool updates
v0.2.6- Changed
brain_distill5 fields changed- added
Input schema / properties / author / descriptionAdded value: +"Override the detected author." - added
Input schema / properties / published / descriptionAdded value: +"Publication date YYYY-MM-DD, if known." - added
Input schema / properties / source / descriptionAdded value: +"A URL (web page, GitHub repo, YouTube video, PDF), a local file path, or a short name for pasted `text`." - added
Input schema / properties / text / descriptionAdded value: +"The body itself, when you already have it; skips fetching." - added
Input schema / properties / title / descriptionAdded value: +"Override the detected title."
- Changed
brain_recall4 fields changed- added
Input schema / properties / format / descriptionAdded value: +"'concise' (default) for text to quote; 'detailed' adds ids, scores and store names for chained calls." - added
Input schema / properties / limit / descriptionAdded value: +"Max results after dedup; default 10." - added
Input schema / properties / query / descriptionAdded value: +"Free-text search; keywords beat sentences." - added
Input schema / properties / scope / descriptionAdded value: +"'all' (default), one kind (fact|pattern|decision|correction|note|raw|relation) or one store (sqlite|vault|hindsight|graph)."
- Changed
brain_remember7 fields changed- added
Input schema / properties / domain / descriptionAdded value: +"Topic tag such as 'trading' or 'system'; empty = none." - added
Input schema / properties / extra / descriptionAdded value: +"Kind-specific fields. decision: title, reason, classification, confidence. correction: title, error, correction, rule, theme. relation: subject, predicate, object (or text 'S —[p]→ O'). note: section." - added
Input schema / properties / force / descriptionAdded value: +"Write even when a near-duplicate exists." - added
Input schema / properties / kind / descriptionAdded value: +"One of fact|pattern|decision|correction|note|raw|relation." - added
Input schema / properties / mission / descriptionAdded value: +"Mission id to tag, e.g. 'M-012'." - added
Input schema / properties / source / descriptionAdded value: +"Where it came from: a URL, file path or 'user'." - added
Input schema / properties / text / descriptionAdded value: +"The memory itself, one item, plain text."
- Changed
brain_session5 fields changed- added
Input schema / properties / critique / descriptionAdded value: +"end only: full markdown body that replaces session_critique." - added
Input schema / properties / executive_state / descriptionAdded value: +"end only: full markdown body that replaces executive_state." - added
Input schema / properties / phase / descriptionAdded value: +"'start' or 'end'." - added
Input schema / properties / session_id / descriptionAdded value: +"Caller's session id; omit to keep the one the server opened." - added
Input schema / properties / sync / descriptionAdded value: +"end only: full markdown body of the cross-agent sync note."
5 tool updates
v0.1.0- First observed
brain_distill - First observed
brain_recall - First observed
brain_remember - First observed
brain_session - First observed
brain_status
TDQS
Scored across 5 tools
Each tool occupies a distinct slot: search (brain_recall), ingest (brain_distill), write a fact (brain_remember), session lifecycle (brain_session), and health/diagnostics (brain_status). Every description ends with an explicit 'Not for X (brain_Y)' boundary statement, so an agent has no path to confuse one with another.
All five tools share a strict `brain_` prefix followed by a single lowercase token, which reads as a coherent namespace. Minor deviation: recall/remember/distill are verbs while session/status are nouns, so the pattern is prefix-consistent but not uniformly verb_noun.
Five tools is tight and each earns its place: with the memory domain you need read, write, ingest, session boundary, and diagnostics, and nothing is redundant. brain_session reasonably bundles start/end into one phase-parameterised tool rather than splitting into two.
The read/write/ingest/lifecycle/diagnostic loop is fully closed, including partial-failure reporting and duplicate/contradiction handling. The gap is that memory is strictly append-only: there is no forget/prune/retract or explicit edit path, so a user cannot remove an obsolete item, and brain_status hints at 'maintenance' for which no tool exists.
Maintenance
Related MCP Connectors
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Persistent memory layer for AI tools. Save and recall notes across Claude and other MCP clients.
Persistent memory for AI assistants. Save once; recall from Claude, ChatGPT, or any MCP client.
Persistent AI memory shared across Claude, ChatGPT, coding agents, and compatible MCP clients.
Related MCP Servers
- AlicenseAqualityCmaintenancePersistent memory + FTS5 full-text search for Claude Code conversation history. Indexes ~/.claude/projects/ JSONL into SQLite, exposes 10 MCP tools (store/recall/search memories, browse sessions, get summaries) plus prompts. Includes a web UI for visual exploration1046 npm97MIT
- AlicenseAqualityAmaintenanceLocal-first AI PKM memory server for coding conversations. Imports Claude Code, Cursor, Codex CLI, Trae, and GitHub Copilot chats into notes, semantic search, tag graphs, Markdown exports, and MCP memory tools.7121 npm61Apache 2.0
- AlicenseAqualityCmaintenanceLocal-first memory for Claude Code and any MCP client: hybrid vector + keyword search and a bi-temporal knowledge graph in one SQLite file. Local embeddings, no API key, $0/token.51249 npm2PolyForm Noncommercial 1.0.0
- AlicenseAqualityBmaintenanceA local-first shared memory layer for MCP-aware agents like Claude, Codex, and Hermes, enabling persistent memory across chats and clients via Markdown files and SQLite FTS.62MIT