Engram
Engram is a self-hosted MCP server that gives AI agents shared, git-backed markdown memory with authority-aware search, temporal validity, write-time conflict guards, and a human dashboard.
Read
brain_schema— Read the vault's taxonomy, frontmatter conventions, and live integrity warningsbrain_search— Keyword search ranked by authority (authoritative→current→provisional→superseded→archived); returns anexcludedlist explaining withheld notes (expired, superseded, etc.)brain_read— Read a full note (frontmatter, body, backlinks, authority) or a specific section by headingbrain_list— List all notes with metadata (path, title, folder, type, tags, status, authority)brain_recent— Get recently changed notesbrain_tree— View the full folder/file treebrain_backlinks— Find all notes linking to a given notebrain_graph— Retrieve the full knowledge graph (nodes + edges from wikilinks andrelated:fields)
Write
brain_write— Create or overwrite a note with structured frontmatter + body; includes conflict and duplicate detectionbrain_edit— Overwrite an existing note (read-then-write pattern)brain_append— Append text to a note (creates it if missing)brain_move— Move or rename a notebrain_create_folder— Create a new folderbrain_supersede— Atomically retire an old fact and link it to its replacement in a single commit; the old note is withheld from search with a reasonbrain_delete— Delete a note (recoverable via git; archiving preferred)
Agentic Capture
brain_capture— Hand off unstructured text; an agent loop reads the schema, searches for existing notes, then files, appends, or supersedes as appropriate — returning a manifest of everything touched
Key Guarantees
Superseded or expired (
valid_until) notes are withheld from search by default, surfaced in anexcludedlist with human-readable reasonsConflicting duplicate writes are rejected with a pointer to
brain_supersedeEvery write is committed to git with attribution, providing a full audit trail
Per-agent tokens with read-only or read/write scopes; read-only tokens never see write tools
Human dashboard with search, note viewer, wikilink/backlink graph, editor with autosave, activity feed with diffs, and multi-workspace management
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., "@Engram search my memory for database schema decisions"
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.
Engram is a self-hosted MCP server + dashboard that gives Claude Code, Cursor, Hermes, and any Model Context Protocol agent shared, long-term memory they read and write — over a plain, git-backed folder of markdown you own. Built for the case a single agent's memory never hits: a team running several agents against one brain.
Autonomous agents forget everything between sessions — and worse, they can't tell what they remember is still true. An agent pulls an old README, a retired price, an API doc you changed months ago, and quotes it with full confidence, because keyword and vector search both rank by resemblance, not truth. Engram makes "is this still true" a first-class, written property: mark a fact superseded or expired and search withholds it — and tells the agent what it skipped and why. Per-agent read/write tokens and a git audit trail of who-wrote-what keep it sane when the writers are a fleet, not just you.
Unlike a headless memory store, you can watch it happen. A fast dashboard lets you search your
brain, see exactly what every agent and teammate changed (with per-file diffs), jump back into
recent notes, and curate it all — while agents read and write the same vault over one MCP endpoint. No
database: your .md files are the source of truth, git is the durable store, and an in-memory index
powers full-text search + a wikilink knowledge graph.
Opinionated about how it stores memory — git-backed markdown, no database, agents write (not just read), self-hosted. Unopinionated about what you keep in it — any markdown vault, any folder structure, any MCP client. Point it at a fresh repo or your existing Obsidian vault: no import step, no lock-in.
What it's for · How it compares · Features · Works with · Quick start · MCP tools · Deploy · FAQ · Contributing
What it's for
Shared memory for a team running multiple agents — one vault, many agents reading and writing concurrently, with per-agent read/write tokens and a git audit trail of who changed what.
Memory that knows what's still true — retire a price, a term, or a changed API doc and your agents stop quoting it; they're told what they skipped and why. The failure a single agent's memory never fixes.
Long-term memory for Claude Code and other coding agents — stop re-explaining your project every session.
A self-hosted, Obsidian-compatible second brain exposed over MCP — your notes, your server, your git repo.
Memory you can see, not a black box — a dashboard to search, watch (with diffs), and curate what your agents remember.
Markdown RAG without the vector database — full-text search + a link graph over human-readable files.
Related MCP server: mem-universe
How it compares
Most agent memory is built to answer "what did I store about this?" Engram is built to answer "what is still true about this?" — a different question, and the one that bites when an agent quotes a price you retired months ago.
Engram | Vector-store memory(mem0, Zep, …) | Markdown memory(Basic Memory, …) | Plain RAG over docs | |
Storage | markdown files, git is the database | embeddings in a vector DB | markdown files | embeddings in a vector DB |
Ranking | relevance × authority | similarity | relevance | similarity |
Knows a fact is retired | ✅ | — | — | — |
Explains what it withheld | ✅ | — | — | — |
Retire + replace atomically | ✅ | — | — | — |
Refuses contradicting writes | ✅ at write time, not read time | — | — | n/a (read-only) |
Audit trail | ✅ git, per-write attribution, per-file diffs | varies | git, if you commit | — |
Per-agent access control | ✅ read / write token scopes | varies | — | — |
Human UI | ✅ dashboard, search, diffs, graph | varies | — | — |
Runs on | your box, one container | mostly hosted SaaS | your box | your box |
The row that matters is the third one. Similarity search cannot tell a contradiction from a duplicate — a retired price and a live one are textually identical, so the retired one often outranks the live one by being longer and more detailed. That can't be fixed at read time, which is why Engram writes the retirement down when it happens.
Categories, not feature-by-feature audits of specific products, and accurate to the best of my knowledge as of July 2026. If something here misrepresents a tool you maintain, open a PR — I'll fix it.
Features
MCP server — 15
brain_*tools over one bearer-authenticated HTTP endpoint (POST /api/mcp, streamable HTTP JSON-RPC). Connect any MCP client to a single URL. Per-agent token scopes: a read-only token never even sees the write tools.Human dashboard — a search-first home, file tree, note viewer with Obsidian callouts, wikilinks, and backlinks, Preview / Edit / Split editor with autosave, ⌘K search + in-page keyboard navigation, "jump back in" recents, and a force-directed knowledge graph.
Authority-aware search — ranking knows relevance, not truth, so a superseded note repeats your query words as often as the live one. Every hit carries an authority (
authoritative→current→provisional→superseded→archived) derived from the note's folder and frontmatter — so your agents quote the locked doc, not the dead one. Markdown RAG that won't hand back yesterday's answer.Temporal validity + explainable rejection — mark a fact
superseded_byanother note or give it avalid_untildate, and search withholds it by default (even if it'slocked) — then hands the agent anexcludedlist of what it skipped, each with a reason ("expired 2026-06-01"). One atomicbrain_supersederetires the old fact and links the new one in a single commit, so add-and-retire can't drift apart. This is the difference between an agent that remembers and one that knows what's still true.Write-time contradiction guards — authority ranking fixes reading; these stop the vault accepting the contradiction in the first place. Engram refuses to create a second live note on a subject a live note already covers (the
acme-pricing-2026.md-beside-acme-pricing.mdbug) and points the agent atbrain_supersedeinstead; refuses to overwrite a note the caller hasn't read; and warns when astatus:isn't a word the ranking model knows, so a typo can't silently strip a note's authority.Audit trail + access control — every write is attributed in git to the token or human that made it, with expandable per-file diffs in the activity feed. Give an agent a read-only token and it never even sees the write tools; a write token can create, edit, move, and archive.
The Curator (optional) — Engram's built-in agent harness over your vault. Chat with your notes (grounded answers, wikilink citations). Or hand
brain_capturea rough dump — a meeting note, a voice transcript — and an agentic loop searches what already exists, then files, merges, or archives and returns a manifest of what it touched. It reads before it overwrites and never deletes. Opus / Sonnet / Haiku, your key.Markdown-native — plain
.md+ YAML frontmatter +[[wikilinks]]. Drop in an existing Obsidian vault and it just works.Git-backed — optional auto commit + push of every change. Full history, no lock-in, your data lives in your repo.
No database — files are the source of truth; an in-memory MiniSearch index + a ported wikilink graph power search and backlinks. Nothing to provision.
Multi-workspace — connect multiple vault repos (URL + token or GitHub OAuth), rename, switch the active one, or remove them — all from the UI.
Self-hosted — one Docker container. Railway / Render / Fly / any host with a volume. Not serverless (it needs a persistent volume, a file watcher, and a long-running index).
Team auth — Google SSO + email allowlist for the dashboard; per-agent bearer tokens — or OAuth for Claude.ai custom connectors — for MCP, created/revoked in the UI. Secrets encrypted at rest.
Runtime config — toggle git-sync and the Curator right from the home; manage commit author, keys, and OAuth in Settings — no redeploy.
Works with
Any client that speaks the Model Context Protocol — one endpoint, bearer-token auth. Most-used first:
Claude Code — Anthropic's agentic coding CLI
Codex — OpenAI's coding agent (CLI + IDE)
Hermes — always-on autonomous agent runtime
openclaw — open-source coding agent
Cursor — AI code editor
Cline — VS Code agent
Windsurf — agentic IDE
Claude Desktop — Anthropic's desktop app
…and any other MCP client — Continue, Goose, Zed, Amp, and the rest
If it speaks MCP, it can read and write Engram as shared memory.
Quick start
Want to poke at it first? There's a live demo — open, no signup, resets a few times a day. Break it all you like.
bun install
bun dev # http://localhost:3000 — runs against ./sample-vaultPoint it at your own vault:
VAULT_DIR=/path/to/your/obsidian-or-markdown/vault bun devTwo ways to run it
Hosted mode (team): the dashboard + HTTP MCP server above — self-host it once, many agents and teammates connect over
POST /api/mcp. This is the main mode.Local mode (stdio): a plain stdio MCP server over a folder, no HTTP/auth/git — for a single machine, Claude Desktop / Cursor, or a registry's Docker introspection:
bun run mcp:stdio /path/to/your/vault # defaults to ./sample-vaultSame
brain_*tools. Built fromDockerfile.mcp.
Each mode ships as its own image, and they are not interchangeable:
Image | Mode | Use it for |
| HTTP — dashboard + | Railway, Render, Fly, any host. This is the one you deploy. |
| stdio — JSON-RPC on stdin/stdout | Claude Desktop, Cursor, MCP registries. Never opens a port. |
Deploying the stdio image as a web service is the one mistake worth calling out: it can only 502, because there is nothing listening. It now refuses to start on a PaaS and tells you this instead.
MCP tools
Agents only ever see the active vault — no repo, workspace, or GitHub tools are exposed.
A read-scope token sees only the read tools. brain_capture appears only when the Curator is full.
Tools | |
Read |
|
Write (needs a |
|
Connect an agent (the dashboard → Connect page shows the exact command + token):
claude mcp add --transport http engram https://<host>/api/mcp \
--header "Authorization: Bearer <token>"Deploy
Runs anywhere you can run a Docker container with a persistent volume — Railway, Render, Fly, or your own box. Serverless (Vercel) won't work: Engram holds a volume, a file watcher, and an in-memory index that a serverless function can't keep alive.
Deploy this repo (root
Dockerfile), mount a volume at/data, setENGRAM_DATA_DIR=/data.Connect your vault repo(s) in the dashboard (Workspaces) — by URL + token, or GitHub OAuth.
Sign in with Google, create MCP tokens on the Connect page, point your agents at the URL.
Most runtime config (git-sync, AI capture, GitHub OAuth, app name) is editable in the Settings page — only auth/infra bootstrap vars live on the host. Full setup: DEPLOY.md.
Railway: New Project → Deploy from GitHub repo → add a Volume at
/data.Render: one-click via the bundled
render.yaml(Docker + a/datadisk).
Deploying from a prebuilt image instead of the repo? Use ghcr.io/rwnalds/engram-app:latest —
not engram:latest, which is the stdio server and cannot answer HTTP. Set the healthcheck to
/api/health.
FAQ
How do I give Claude Code long-term memory?
Deploy Engram, connect a markdown vault, and claude mcp add the endpoint. The brain_* tools let
Claude Code search, read, and write persistent notes across sessions.
Can multiple AI agents share one knowledge base?
Yes. Every agent points at the same MCP URL and reads/writes the same active vault — that's the point.
Give each agent its own bearer token, read or write — a read-only token can't mutate your notes.
How do I stop an agent from quoting outdated facts?
Retire the fact and search stops surfacing it. When a value changes, call brain_supersede(old, new) —
one atomic commit marks the old note superseded_by the new one, and it's withheld from search by
default (even if it's locked). Or set valid_until: 2026-12-31 on a note and it self-expires.
Retired matches don't vanish silently: brain_search returns them in an excluded list with a
reason ("expired 2026-06-01"), so the agent can say what it ignored and why instead of quoting it.
What stops an agent just adding a second, contradicting note?
Engram refuses the write. Told "the price is now X", an agent that can't overwrite a note it never
read will happily add acme-pricing-2026.md next to acme-pricing.md — nothing is corrupted, and
you now have two live notes disagreeing about one number. That write is rejected with a pointer to
brain_supersede, which retires the old note and adds the new one in a single commit. Pass
allow_conflict: true when both notes genuinely belong.
How do I know what an agent changed? Every write is committed to git attributed to the token or human behind it, and the dashboard's activity feed shows per-file diffs — a built-in audit trail for autonomous agents.
Does it work with my Obsidian vault?
Yes. It reads plain markdown with frontmatter and [[wikilinks]], and renders Obsidian-style callouts
and backlinks. No import step.
Do I need a vector database? No. Engram uses full-text search (MiniSearch) plus a wikilink graph over human-readable markdown — no embeddings service, no vector store to run.
Can I chat with my notes? Yes — enable the optional Curator, a chat agent that searches and reads your vault to answer with wikilink citations (Opus / Sonnet / Haiku). It's read-only in chat, so it helps you think without changing anything, and it runs on your own Anthropic key.
Can I see what my agents changed? Yes — the Activity view reads your vault's git history and shows every change (agents and teammates alike), expandable to per-file diffs. Since it's just git, you get the full audit trail for free.
Is my data locked in?
No. It's just .md files in a git repo you own. Turn Engram off and you still have every note and its
full history.
Where does it run / is it self-hosted? You host it. One Docker container on Railway / Render / Fly / any VM with a volume. Your keys, your data.
Contributing
Issues and PRs welcome — especially where the validity model breaks against a vault shaped differently from mine.
CONTRIBUTING.md — setup, conventions, and the pre-PR checklist.
docs/curator.md — how the optional Curator agent loop works.
SECURITY.md — please report vulnerabilities privately, not as an issue.
bun install && bun dev
bun test # the ranking/authority suite, incl. the stale-truth fixturesIf Engram is useful to you, starring the repo genuinely helps other people find it.
Stack
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind v4 · shadcn/ui · bun · MiniSearch · d3-force · MCP SDK. MIT licensed.
Keywords: MCP server · Model Context Protocol · second brain for AI agents · agent memory · long-term memory for Claude Code · shared memory for AI agents · self-hosted knowledge base · Obsidian-compatible · markdown · knowledge graph · wikilinks · PKM · Zettelkasten · git-backed notes · Hermes agent memory · Cursor memory · RAG without a vector database · chat with your markdown notes · git-backed agent activity feed · audit trail for AI agents · authority-aware search · read-only vs write MCP tokens · agent access control · self-organizing notes · agentic note capture · AI that files your notes · temporal validity · stale memory · agents quoting outdated facts · supersede · note expiry · shared memory for a team of agents · Basic Memory alternative · mem0 alternative.
Available Tools
16 toolsbrain_appendA
Append text to a note (creates it if missing).
Inputs: path (required), text (required).
brain_backlinksC
Notes that link to the given note.
Inputs: path (required).
brain_captureA
Hand over a ROUGH note / brain-dump and let the vault file it. An agent loop reads SCHEMA.md, searches for what already exists, then deliberately creates a new note, appends to a matching one, or archives what this supersedes — and returns a manifest of every path it touched. It reads a note before overwriting it, and never deletes. Use when you have unstructured input and don't want to choose the path yourself; use brain_write when you do.
Inputs: text (required).
brain_create_folderA
Create a new folder in the vault (with a .gitkeep).
Inputs: path (required).
brain_deleteA
Delete a note (recoverable via git history). Prefer brain_move into an archive folder — deleting destroys the reasoning trail, archiving only removes it from search. Delete when the note is wrong or duplicated, archive when it is merely no longer true.
Inputs: path (required).
brain_editA
Overwrite a note. Pass content (full raw markdown incl. frontmatter) — read first with brain_read, then write the whole file back. Also accepts body (+ optional frontmatter) like brain_write.
Inputs: path (required), body, content, overwrite, +2 more.
brain_graphC
The knowledge graph (nodes + edges from wikilinks and related:). Optional folder filter.
Inputs: folder.
brain_listA
List every note with metadata (path, title, folder, type, tags, status, authority). Use to discover what exists. authority tells you which notes are source-of-truth and which are history.
Inputs: no named parameters.
brain_moveA
Move or rename a note. This is how you retire something: when a note stops being true, move it to an archive folder (see brain_schema → conventions.ranking.archiveFolders) rather than deleting it. Archived notes are demoted in search and excluded by default, so they stop misleading agents while the reasoning trail survives. Leave a pointer in the replacement note saying what superseded what.
Inputs: to (required), from (required).
brain_readA
Read a note: full markdown (frontmatter + body), its authority, and its backlinks. Path is vault-relative, e.g. 'clients/mks/mks.md'.
Pass section to read just one heading's content instead of the whole file — cheaper on long documents. If the heading isn't found you get the list of available headings back.
Always check the returned authority before acting on the content: archived and superseded notes are history, not instructions.
Inputs: path (required), section.
brain_recentA
Notes changed most recently, newest first. Use to catch up on what humans or other agents have done since you last looked.
Inputs: limit, since.
brain_schemaA
READ THIS FIRST, before searching or writing. Returns the vault's SCHEMA.md (folder taxonomy, frontmatter conventions, wikilink model, write protocol) AND a live description of this specific vault: its folders, the status: values actually in use, how search ranks notes by authority, and any integrity warnings. Vaults differ — never assume conventions, read them here.
Inputs: no named parameters.
brain_searchA
Keyword search across the vault. Returns { hits, excluded }. Each hit has path, title, folder, status, snippet, and authority.
IMPORTANT — ranking is by keyword relevance, NOT by truth. A superseded document repeats the query words just as often as the live one, so it can outrank it. Every hit carries an authority: authoritative (source of truth — prefer it), current, provisional (draft/proposed — never quote as settled), superseded, archived. Rank order is a suggestion; authority is the signal.
excluded is the explainable-rejection list: notes that matched the query but were withheld because they are archived, superseded, or expired (past their valid_until), each with a reason (e.g. "superseded by price-live", "expired 2026-06-01"). When you deliberately ignore a stale note, cite its excluded entry — say what you skipped and why, instead of quoting it. If you need a withheld note, re-search with includeInvalid: true (superseded/expired) or includeArchive: true.
Before quoting a price, guarantee, contract term, or any other single-valued fact, open the authoritative note. If two live notes disagree on such a fact, that is a defect in the vault — report it rather than averaging them.
Inputs: query (required), limit, folder, includeArchive, +1 more.
brain_supersedeA
Retire a fact and replace it, atomically. When a fact changes (a price, a term, a decision), DON'T just add a new note — the old value keeps matching searches and gets quoted. brain_supersede(from, to) marks the old note superseded in place (body preserved) and links it to the new one, in a single commit, so add-and-retire can't drift apart. After this, search withholds the old note with the reason "superseded by ".
from = the note being retired; to = the note that replaces it. If to doesn't exist yet, pass body (its markdown) and it's created; otherwise write to first, then supersede. reason is recorded on the old note. Prefer this over brain_move for a value that changed (move is for relocation).
Inputs: to (required), from (required), body, reason.
brain_treeA
Return the folder/file tree of the vault.
Inputs: no named parameters.
brain_writeA
Create or overwrite a note. PREFER body (markdown, no frontmatter) + frontmatter (an object): the YAML is serialised for you and always parses. Hand-writing frontmatter into content risks invalid YAML — a note whose frontmatter fails to parse loses its status, tags and title on every read, so a note claiming status: locked would rank as an ordinary one. Such a write is REJECTED. Follow SCHEMA.md: kebab-case path, dated names for daily/decisions, frontmatter with title/type/tags/status. Path vault-relative (e.g. decisions/foo-2026-07-09.md).
WHEN A FACT CHANGED, DON'T CREATE A DATED SIBLING. Writing acme-pricing-2026.md next to a live acme-pricing.md leaves two live notes disagreeing about one number, and the older one usually matches the query better — this is exactly how a retired price gets quoted. Such a write is REJECTED; use brain_supersede instead, which retires the old note and adds the new one in a single commit. allow_conflict: true overrides it when both notes genuinely belong.
Inputs: path (required), body, content, overwrite, +2 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 16 tools
Most tools have clearly distinct purposes, but brain_write and brain_edit overlap significantly: both can create or overwrite a note, with the only differentiator being that edit also accepts raw markdown. Other potentially similar tools like brain_supersede vs brain_move and brain_backlinks vs brain_graph are well differentiated by their descriptions.
All tool names share the consistent 'brain_' prefix and snake_case style, making them easy to group. However, the second element mixes verb forms (list, append, move, search, read, write, edit, supersede, capture, delete) with noun forms (schema, recent, tree, backlinks, graph), so the pattern is not purely verb_noun.
At 16 tools, the set is slightly above the typical 3-15 range for a well-scoped server, but the rich feature set (CRUD, search, graph, lifecycle operations) justifies the count. Each tool earns its place, including the specialized supersede and capture tools.
The tool surface covers the full note lifecycle: create (brain_write, brain_capture), read (brain_read, brain_search, brain_list), update (brain_edit, brain_append, brain_supersede), delete (brain_delete), and organization (brain_move, brain_tree, brain_create_folder). Discovery is also complete with recent, backlinks, graph, and schema. No significant gaps are evident for a personal vault manager.
Maintenance
Related MCP Connectors
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Hosted memory for AI agents over MCP. One memory shared by all your agents.
Hosted MCP memory for coding agents: persistent across sessions, editable markdown, team sharing.
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA local-first MCP server that gives AI assistants long-term memory by storing, searching, and recalling notes as Markdown files on your machine.9 npmMIT
- AlicenseAqualityDmaintenanceSelf-hosted MCP memory server that gives a multi-agent fleet one shared, git-backed memory for search, read, and write.81MIT
- AlicenseNot gradedqualityCmaintenanceA self-hostable MCP server that provides permanent memory for AI agents using Postgres + pgvector for semantic search and Markdown file sync.2 npmMIT
- AlicenseNot gradedqualityDmaintenanceMCP server providing persistent, local-first memory for AI agents via Markdown files in a git repo, with search, branching, and auditability.11 npm2MIT