MAGNEMO

Manual

MAGNEMO 0.6.11 · PYPI · README · MCP SERVER

MAGNEMO

The Memory MCP. Your AI remembers. You keep what matters.

MAGNEMO is Memory for your AI, kept on your computer in plain files. Your AI writes down what it learns as it works; nothing becomes Memory until you approve it, and every Memory shows who wrote it and who approved it.

Your agent writes one line down and keeps working. Say keep, and it is Memory.

PyPI downloads tests license stars MCP registry

Site · Manual · Changelog · X @Magnemo_AI · Known limits

Install in one paste

In three lines:

pip install MAGNEMO      # Python 3.11 or newer
magnemo init             # makes the vault: a folder of plain files
magnemo mount            # writes .mcp.json, the file Claude Code reads, and the first line in CLAUDE.md

Or let your agent do it. Open Claude Code in any of your project folders, and paste this. (Its magnemo mount step writes .mcp.json, the file Claude Code reads, and a short block in CLAUDE.md that tells every new session where this project's Memory is. In Cursor, Windsurf or another client, use the block for your client under "Install in your client".)

Set up MAGNEMO in this project:
1. Install it: pip install MAGNEMO. It needs Python 3.11 or newer. If pip can't find it, install uv (curl -LsSf https://astral.sh/uv/install.sh | sh) and then run: uv tool install MAGNEMO
2. Initialize the vault: magnemo init
3. Register the MCP server: run magnemo mount — it adds MAGNEMO to this project's MCP config and keeps any servers already there.
4. Verify: run magnemo doctor and confirm everything passes.
5. Then ask me to restart you, so MAGNEMO's tools load, and to say this when you are back: "Look around this folder, tell me what this project is for, and stage that as the first note." Your agent never waits on you. When you want something kept, say keep.
If anything fails, show me what went wrong and fix it if you can.

Plant the seed: one paste, and your agent grows a Memory.

After the restart, say it: Look around this folder, tell me what this project is for, and stage that as the first note. Your agent writes one line down and keeps working. Say keep, and it is Memory. Then ask what it remembers.

Works with

One server, the same in every client. Tested where it says so; the rest follow each client's own docs.

ClientTestedHow
Claude Codeyes: Oct 26–28, 2026, Claude Code 2.1.309. Seven tools; the yes in the chat; pending reads a body.magnemo mount, or claude mcp add magnemo -e MAGNEMO_VAULT=/absolute/path/to/vault -- uvx magnemo-mcp
Claude Desktopuntested end to endthe uvx block under "Install in your client", with absolute paths
Cursoruntestedthe Add to Cursor link below, or .cursor/mcp.json
VS Codeuntested.vscode/mcp.json
Windsurfuntested~/.codeium/windsurf/mcp_config.json
Clineuntestedcline_mcp_settings.json
Continueuntested~/.continue/config.yaml
Gemini CLIuntested~/.gemini/settings.json
Codex CLIuntested~/.codex/config.toml
Zeduntestedsettings.json → context_servers

Each client's exact block is under "Install in your client".

How it compares

Five questions, answered from each project's own docs (read Oct 12, 2026, checked again Oct 22; the pages are linked under the table).

MAGNEMOMem0ZepLettaBasic Memory
Where the memory livesPlain markdown files in a folder on your computerA hosted platform run by Mem0; open source: a local Qdrant store and a SQLite history fileZep: a managed cloud service, or in your own VPC. Graphiti, its open-source engine: a graph database you runMarkdown files in a git repository that belongs to the agent: hosted by Letta, or on your device in local modeMarkdown files on your disk with a local SQLite index; an optional cloud
Who approves a writeYou. An agent's write waits in staging until your yesAn LLM extracts facts from the messages and stores them; their docs describe no approval stepMessages are ingested into the graph as they arrive; their docs describe no approval stepThe agent updates its own memory; the background review "does not ask you for approval"The assistant writes notes directly; the cloud has suggested edits that can be accepted or rejected
Author and approver on every entryBoth, in each file's header (author, reviewed_by) and in an append-only ledgerUser, agent, app and run ids, timestamps, and a change history per memory; their docs name no approver fieldWhen a fact was true and when it stopped, traced to its source episode; their docs name no approver fieldEvery memory edit is a git commit; their docs do not say what the commit recordsTitle, type, tags and dates; author is a field you may add; their docs name no approver field
Network calls of its ownNone. No model call and no embedding call; git push to a backup, if you add oneOpenAI by default for the model and the embeddings; other providers are listed, Ollama among themZep is a cloud API. Graphiti defaults to OpenAI; local model servers are documentedLocal mode keeps state on your device; inference goes to the provider you choose, which can be a local oneRuns locally; the default embeddings run on your machine with no API key
What you can take backA no is kept with its reason; a replaced note is archived with a forward link; nothing deletes; the files are yours to editDelete, update, and a history per memory; export is on the hosted platformDelete nodes, edges and episodes; a replaced fact is invalidated, not deletedThe git history of every memory edit; the files can be read and editedPlain files you edit and can track with git; a delete tool; the cloud keeps every saved version

Where each of them is ahead. Mem0 extracts memories for you, searches them by meaning, and has Python and JavaScript SDKs, a REST API and a hosted platform. Zep keeps a knowledge graph that knows when each fact was true, as a managed service with SDKs in three languages. Letta is a whole agent platform, with an SDK, a CLI and background agents that tend the memory. Basic Memory searches by keyword and by meaning with embeddings that run on your machine, links notes into a graph, and syncs through its cloud. MAGNEMO has none of that: its search is keyword search (KNOWN_LIMITS.md), there is no graph and no hosted service. What it has is the approval and the record.

Their pages: Mem0 overview, platform and open source, add, history, quickstart, delete, export · Zep concepts, facts, security, deleting data, Graphiti · Letta MemFS, memory settings, local mode · Basic Memory README, what it is, tools, note format, semantic search, suggestions, file history. A cell that is wrong or out of date: open an issue and it is fixed.

Listed on the official MCP registry (ai.magnemo/magnemo) · PyPI · mcpservers.org · Glama · awesome-mcp-servers. Tested on every push, on Python 3.9, 3.11 and 3.12: 370 tests, as of Oct 28, 2026 (the runs).

What's new

  • 0.6.11 · Oct 28, 2026 · magnemo mount writes the first line in CLAUDE.md, so every new session knows where this project's Memory is. pending reads a note nobody has kept yet.
  • 0.6.10 · Oct 26, 2026 · Your agent never stops to ask. Say keep in the chat, and the record says how the yes was given.
  • 0.6.9 · Oct 22, 2026 · A seat's report files itself as a receipt and asks nothing; a yes is for Memory. Sentinel reads a seat's quote as a quote.

Every release: CHANGELOG.md.

For builders. MAGNEMO is an MCP server with four verbs — retrieve, stage, bootpack, handoff — plus keep, drop, pending, and a CLI for your side: review, promote, reject. It runs on your machine, in plain markdown files you own. The package imports no network module (magnemo doctor scans for one on every run); the only traffic is git push to a backup destination, if you add one. Every promotion is recorded with who wrote the entry, the name given for the yes, when, and through which gate. Trust is computed from that record, never asserted. It mounts beside any memory you already run (a folder of notes, Obsidian, a RAG stack). Python 3.11+, zero dependencies, Apache-2.0.

Fresh vault? THE CHARTER section will say it isn't promoted yet — that is the governance speaking: MAGNEMO never fabricates canon. Stage a charter, review it, promote it, and every boot thereafter serves it back verbatim. (magnemo not found after install? pip's script folder isn't on PATH — python3 -m magnemo always works.)

Open beta — read KNOWN_LIMITS.md before trusting it with anything you can't lose. Honest caveats, no fine print.

Install in your client

One server, said ten ways. Every block below is the same thing: uvx magnemo-mcp with MAGNEMO_VAULT pointing at the folder your Memory lives in (make one with magnemo init ./vault). Tested on this Mac where it says so; the rest is from each client's own docs and marked untested — corrections welcome, open an issue.

Claude Code — tested: a Claude Code session mounts the server, lists the seven tools and calls them; a yes in the chat keeps a note, and pending reads a body (last run Oct 28, 2026: Claude Code 2.1.309, the 0.6.11 server).

claude mcp add magnemo -e MAGNEMO_VAULT=/absolute/path/to/vault -- uvx magnemo-mcp

(claude mcp list shows magnemo … ✔ Connected. Add -s project to write it into the repo's .mcp.json for your team.) Only have the desktop app? claude may not be a command in your shell. On a Mac the app keeps its own copy at ~/Library/Application Support/Claude/claude-code/<version>/claude.app/Contents/MacOS/claude; run that in place of claude.

Claude Desktop — untested end to end here. The server this block starts was run the way Claude Desktop starts it (Oct 28, 2026, the 0.6.11 server). Claude Desktop → Settings → Developer → Edit Config, then claude_desktop_config.json. Claude Desktop does not read your shell's PATH, so both paths are absolute: which uvx prints the first.

{
  "mcpServers": {
    "magnemo": {
      "command": "/absolute/path/to/uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault", "MAGNEMO_AGENT": "claude-desktop" }
    }
  }
}

Restart Claude Desktop after saving.

Cursor — untested here (not installed on this Mac); the link and the block follow Cursor's docs. Add to Cursor Or ~/.cursor/mcp.json (or .cursor/mcp.json in the project):

{
  "mcpServers": {
    "magnemo": {
      "command": "uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault" }
    }
  }
}

VS Code / Copilot — untested here; per VS Code's docs. Install in VS Code Or .vscode/mcp.json in the workspace:

{
  "servers": {
    "magnemo": {
      "type": "stdio",
      "command": "uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault" }
    }
  }
}

Windsurf — untested; ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "magnemo": {
      "command": "uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault" }
    }
  }
}

Cline — untested; Cline → MCP Servers → Configure → cline_mcp_settings.json:

{
  "mcpServers": {
    "magnemo": {
      "command": "uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault" },
      "disabled": false
    }
  }
}

Continue — untested; ~/.continue/config.yaml (or a file in .continue/mcpServers/):

mcpServers:
  - name: magnemo
    command: uvx
    args: ["magnemo-mcp"]
    env:
      MAGNEMO_VAULT: /absolute/path/to/vault

Gemini CLI — untested; ~/.gemini/settings.json:

{
  "mcpServers": {
    "magnemo": {
      "command": "uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault" }
    }
  }
}

Codex CLI — untested; ~/.codex/config.toml:

[mcp_servers.magnemo]
command = "uvx"
args = ["magnemo-mcp"]
env = { MAGNEMO_VAULT = "/absolute/path/to/vault" }

Zed — untested; settings.json → context_servers:

{
  "context_servers": {
    "magnemo": {
      "source": "custom",
      "command": "uvx",
      "args": ["magnemo-mcp"],
      "env": { "MAGNEMO_VAULT": "/absolute/path/to/vault" }
    }
  }
}

After the install, the loop is the same everywhere: your agent writes to staging, you review.

magnemo yes             # promote the top of the queue (yes <id-fragment> · yes --all)
magnemo no <id> --reason "…"   # reject one — the reason is required; rejections teach
magnemo review          # the interactive queue, when you want to read first
magnemo doctor          # python, vault, config, ledger, and the mount — scans the package for network modules too

Anything that speaks MCP over stdio mounts the same way. The remote door (ChatGPT and hosted clients) is on its way in 0.7.0.

How it works

The yes is checked: nothing becomes Memory without a yes, and the engine can tell a person's yes from an agent's; a yes in the chat counts, and the record says how it was given.

MAGNEMO is Memory with a constitution: every fact carries provenance, every agent write waits in your review queue before it becomes Memory, and every decision lands in a Trust Ledger.

Your agent gets four verbs and cannot keep a note on its own authority; it carries your yes, and the record says so. Say yes in the chat and keep carries it, ledgered unverified; a click your client draws or a yes at your terminal is a verified one. KNOWN_LIMITS.md says what that does and does not stop; docs/MCP.md has the clients it works in.

ActorDoorCan do
AgentsMCP server (stdio)retrieve canonical memory · stage → staging only, the one write tool · bootpack on wake · handoff at the boundary · keep / drop carry your yes or no · pending lists what waits
YouCLI + git (any editor)review the queue · promote / reject · edit anything · own everything

Zero dependencies. Pure Python standard library, 3.11 or newer. Nothing else to install, nothing to trust but this code.

The vault

vault/
  dev/      knowledge/ playbooks/ decisions/ debt/        ← example: a dev team's partition
  ops/      knowledge/ playbooks/ clients/ decisions/ style/  ← example: an ops team's partition
  shared/   tickets/ changelog/                            ← interop bus (gated)
  _staging/   agent writes await review here
  _index/     machine-managed
  _ledger/    trust_ledger.jsonl — append-only, never forgets

Every note is markdown with provenance frontmatter (author, written, source, status, reviewed_by, supersedes, strength). Provenance is the file format.

Privacy

Your Memory lives on your computer, in plain files you can open. No network calls of its own. Add a backup remote and it pushes there, nowhere else. The precise version: the package imports no network module, and magnemo doctor scans for one every time it runs. If you add a backup destination, the engine runs git push to it. The full page: https://magnemo.ai/privacy

Guarantees (Phase 1 — Governed Recall)

  • Through the MCP server, agent writes NEVER reach canonical stores directly — staging only, always.
  • Search returns canonical (promoted) notes only. Staged notes are not searched. The boot pack shows staged material marked as staged: the titles of open threads and of the top staged notes, and the last handoff's cut line with a pointer to its note.
  • Partition walls enforced per agent (MAGNEMO_PARTITIONS); cross-partition = DENIED.
  • Supersession is explicit: old notes archive with a forward link. Nothing deletes.
  • Rejections are kept and recorded — rejections teach.
  • Every promote/reject lands in the append-only Trust Ledger with actor + reason.

Tests

python -m unittest discover -s tests -v     # incl. full MCP round-trips (legacy + four-verb)
# or: pip install -e ".[test]" && pytest

The same suite runs on every push, on Python 3.9, 3.11 and 3.12: the runs.

Everything that shipped

Release by release, with the design notes that used to live here: CHANGELOG.md.

— Silver Valley Technologies Inc. · Phase 1 of 3 · The memory that learns is the memory that is governed.


mcp-name: ai.magnemo/magnemo · Source · Security · Privacy

The four-verb MCP server

magnemo.mcp is a Model Context Protocol server over stdio. It exposes four verbs, two tools that carry the person's answer, and pending, each bound to code that already exists in the package. Nothing is reimplemented; the server is a governed door, not a second brain.

retrieve(query, scope?, budget?, k?)   read   → search.Index.search
stage(note, provenance)                WRITE  → governance.agent_write   (the only write verb)
bootpack(scope?, class?)               read   → bootpack.generate
handoff(usage, trigger, cut?)          write* → handoff.record           (* telemetry + staged note)
keep(note)                             the person's yes → governance.promote  (chat-text, unverified)
drop(note, reason?)                    the person's no  → governance.reject   (chat-text, unverified)
pending(note?)                         read   → what waits for the person's keep; with an id, that note's body

The agent cannot keep a note on its own authority; it carries your yes, and the record says so. keep is for one moment: the person has said yes to this note, in their own words, in this conversation. The ledger writes that yes chat-text:<client> · unverified, because over MCP the engine cannot tell the person's keyboard from the model's tool call. It counts half in the Trust Ledger, at most 50 a day are kept this way (chat_keeps_per_day; the day is the local day of the computer the vault is on, reset at its midnight), and a note Sentinel is holding is not kept by it: a hold needs a verified yes (a click the client draws, or magnemo yes at the person's terminal). approve and reject are other names for keep and drop. There is no shell, eval, or file tool — least privilege is the surface itself.


Install & mount

pip install -e .                 # zero runtime deps; Python ≥ 3.11
magnemo init ./vault         # once

One-line .mcp.json (Claude Code reads it from the project root; any MCP client takes the same shape):

{"mcpServers":{"magnemo":{"command":"python3","args":["-m","magnemo.mcp"],"env":{"MAGNEMO_VAULT":"/abs/path/to/vault","MAGNEMO_AGENT":"my-agent","MAGNEMO_SCOPE":"dev,ops,shared","MAGNEMO_PARTITIONS":"dev,ops,shared"}}}}
envmeaningdefault
MAGNEMO_VAULTvault root (created if missing)required
MAGNEMO_AGENTidentity stamped on every stage/handoff/receiptagent
MAGNEMO_SCOPEpartitions this agent may read (retrieve / bootpack) — the scope wallall
MAGNEMO_PARTITIONSpartitions this agent may stage intoall

Diagnostics go to stderr; stdout is pure JSON-RPC.


The yes: never mid-work, asked at the pause

stage never waits. It asks nothing, on any transport: the note lands in the review queue and the result says one line for the agent to repeat, Staged. Say keep when you want it kept. The agent keeps working. A person who steps away from the desk comes back to a finished build and a queue, never to a question that stopped it.

The ask is at a pause, once, about everything that waits. pending lists the staged notes nobody has answered, and the line to say: N notes staged since you left. keep all / pick / later. The agent says it at the end of its own turn. The person says keep all (keep with "all": each note its own ledger line), picks, or says later. Later and no answer are the same thing: nothing blocks, nothing is lost, the notes wait for the next pause.

On handoff, a client that said at initialize that it can put a form to its user is sent one MCP elicitation request for the whole batch:

3 notes staged since you left. keep all / pick / later.

- <a note's title> (<the seat>)
- …

Keep them as Memory?    Keep all · Pick · Later

The client draws that in its own window and sends back what the person chose. The model is not on that path. It does not see the request, and none of its tools answers it. Keep all promotes each note on its own ledger line with answered_by: elicitation:<client>, a verified yes. Pick sends the agent back to the chat to ask which. Later, a declined or dismissed question, or no answer in two minutes leaves every note staged; the question is withdrawn when the wait ends, and the handoff completes. A note Sentinel is holding is never put to the person this way.

ClientSeenSays it can askWhat happened
Claude Code, a person at it2.1.296, Oct 12 2026yes (the dialog was drawn in the chat)0.6.8–0.6.9, when the question was asked inside stage: the agent staged one note; the person pressed Yes; the note was promoted 9 seconds after it was written. The ledger line: approved, actor founder, ran_by: mcp:drill-seat, answered_by: elicitation:claude-code 2.1.296.
Claude Code, run with nobody at it (claude -p)2.1.296, Oct 12 2026yes (form and url)It let go of the question in 5 ms. MAGNEMO left the note staged.
Claude desktop appuntested
Cursoruntested
VS Codeuntested

A client that cannot draw a question (claude.ai today) gets the line in the handoff and pending results for the agent to say. When the person says yes, keep carries it, and the ledger line says chat-text, unverified. magnemo yes <id> at their own terminal is the verified yes: it clears a hold, and on a note kept in the chat it re-ledgers the yes as verified, the first one kept on the record. It needs their own terminal and a name the vault lists, and it refuses an agent's shell (KNOWN_LIMITS.md).

For a harness with nobody at it:

  • MAGNEMO_ASK=off on the server: the batch question is never drawn, and every note waits.
  • Or leave it on and have the harness dismiss the request. In Claude Code that is an Elicitation hook that exits 2. A dismissed or declined request is never read as a no.
  • An accepted answer that arrives in under 300 ms is refused and logged (judgment.refused, answered_by: refused:too-fast): it was not read by a person. A harness that waits longer and then accepts is not caught by this; answered_by on the ledger is what shows where a yes came from.

The server speaks the initialize handshake (protocol revisions up to 2025-11-25). A client on the 2026-07-28 revision probes first and falls back to it, as Claude Code 2.1.296 was seen to do. On that newer revision the same question travels a different way (an input request inside the tool's result); the server does not speak it yet.


The tools

retrieve(query, scope?, budget?, k?)

Canonical memory only: retrieve does not search staged notes. Returns a JSON payload, never a raw dump:

{"rid":"…","scope":["dev"],"budget":4000,"rendition":"snippet","truncated":false,
 "candidates":3,"served":3,
 "results":[{"pointer":"mn://dev/knowledge/<id>","id":"…","title":"…","score":2.1,
             "yield":"+2/-0","snippet":"first 240 chars…"}],
 "payload_bytes":812}
  • scope must lie inside MAGNEMO_SCOPE; otherwise SCOPE WALL and nothing is logged.
  • budget (bytes, 200–32 000, default 4 000) is honoured deterministically: snippet → fewer snippets → mn:// pointers only. truncated tells you it happened.
  • rid is the retrieval receipt. Cite it with magnemo outcome <rid> approved|denied and every note that informed the action earns or loses yield.

stage(note, provenance)

The only write verb. Lands in _staging/ as a memory candidate; never touches canon.

{"note":{"title":"…","body":"…","partition":"ops","store":"knowledge",
         "impact":"money","tags":"pattern","taint":"inbound-email"},
 "provenance":{"source":"run#1847","author":"ops-agent"}}

Refused before touching disk: missing provenance (paperless), blank source, missing title/body/partition/store, unknown store, partition outside MAGNEMO_PARTITIONS. Returns {staged, salience, salience_components, duplicate_of, duplicate_similarity, taint, bytes}.

bootpack(scope?, class?)

The document a session reads first. class = worker (lean) | partner (adds the relationship layer when a codex exists). Sections, in doctrine order: Charter (verbatim, never fabricated) → gates (the Gate Map at ledger time) → your autonomy (the mounting agent's own scorecard, MAGNEMO_AGENT) → canon digest → open threads & KAIROS-ranked queue → last handoff → ledger tail. Pure function of vault state: same state, same bytes. The MCP path returns the pack; it never writes _index/.

handoff(usage, trigger, cut?)

trigger ∈ wall|planned|compaction|other. Appends one entry to _ledger/handoffs.jsonl (with the agent's autonomy levels at the boundary) and stages a provenance-complete handoff note. The next bootpack serves it under LAST HANDOFF. Doctrine: hand off at ~88–90%.

keep(note) · drop(note, reason?)

Carry the person's yes or no from the chat. Call them only when the person has answered this note in their own words in this conversation; never draw a panel, never on the agent's own judgment. note is the staged note's id (its last eight characters are enough). keep returns one line to repeat: Kept. Written by <writer>, your yes in the chat (<client>). "<title>" is Memory now. The refusals: no note waiting by that id; Sentinel is holding it (it stays held with its alert); the day's cap is reached. keep with "all" keeps every note pending lists as waiting, one ledger line each, when the person said keep all; it opens with the same count pending gives (N waiting · M held: kept K of the N waiting.). A note carrying contact details keeps like any other; its contact line rides the ledger's yes.

pending(note?)

Read-only. The staged notes nobody has answered (not Sentinel's alert notes, not handoff telemetry), which of them Sentinel holds, and the one line to say at a pause: N notes staged since you left. keep all / pick / later. Its header is the one count the boot pack and keep all also say: N waiting · M held. Times are local, with their offset (Oct 27, 10:12 PM −07:00); the files and the ledger stay UTC. With note (an id, or its last eight characters), one staged note whole: its body, its provenance (author, source, written), labelled staged · not yet Memory. This is not retrieve, which serves Memory only; it is how a note left for later stays within an agent's reach, on every transport. A note Sentinel holds returns its alert and no body.

The first line

magnemo mount writes this block into the file the client reads first (CLAUDE.md for Claude Code, .cursor/rules/magnemo.mdc for Cursor), between <!-- MAGNEMO:BEGIN … --> and <!-- MAGNEMO:END -->; magnemo unmount removes it. Claude Desktop reads no project file first: put the same words where it reads instructions.

This project's Memory is MAGNEMO. At the start of a session call bootpack. Before answering anything about this project, call retrieve. Each time you finish a step or make a decision, stage it right then, unasked — one note per step, after a restart too. Remembering means proposing; the person's keep makes it Memory. Never stop to ask; at the end of your turn say pending's line.

The boot pack carries it in one sentence under its title. mount writes the absolute path of the server it found; doctor checks that path, and checks only MAGNEMO's own entries; any other server is listed and left unchecked.


Cascades — deterministic, zero model calls

stage(note, provenance)
  │
  ├─ validate ──── paperless / malformed ──▶ REFUSED (nothing on disk)
  ├─ write-partition wall ──────────────────▶ DENIED
  ├─ Sentinel: secret ─▶ held, body redacted · S14 contact ─▶ kept as written, `contact` line + ledger · injection ─▶ tainted, ALERT
  ├─ pattern separation: trigram-Jaccard vs in-partition canon + staged queue
  │        ≥ 0.6 → dup_of / dup_sim in frontmatter + `dup-candidate` tag
  ├─ governance.agent_write ─▶ KAIROS salience (consequence·novelty·operator·source) ─▶ _staging/<id>.md
  └─ foresight 'stage' event {id, salience, dup_of, taint}
retrieve(query, scope?, budget?)
  │
  ├─ scope gate ─── outside MAGNEMO_SCOPE ──▶ SCOPE WALL (no receipt, no cost event)
  ├─ Index.search walled to scope  (BM25 × strength × yield × taint-penalty)  ─▶ receipt rid
  ├─ rendition select to fit budget:  snippet ─▶ truncated snippet ─▶ mn:// pointers
  └─ foresight 'retrieval' event {rid, scope, budget, rendition, truncated, candidates, served}
bootpack(scope?, class?)
  │
  ├─ scope gate
  ├─ bootpack.generate:  CHARTER (verbatim) ─▶ GATES (ledger time) ─▶ CANON DIGEST ─▶ OPEN THREADS + queue
  │                      ─▶ LAST HANDOFF (from handoffs.jsonl) ─▶ LEDGER TAIL
  └─ foresight 'bootpack' event {class, scope, bytes}
handoff(usage, trigger, cut?)
  │
  ├─ handoff.record ─▶ _ledger/handoffs.jsonl  (append-only)
  │                 ─▶ governance.agent_write ─▶ _staging/<handoff-note>.md  (KAIROS-scored)
  ├─ foresight 'handoff' event
  └─ next bootpack() — any process, any session — renders it under LAST HANDOFF

Invariants (each has a test in tests/test_mcp.py)

invarianthow it holds
staging is the only agent writethe four verbs and pending leave the canon file set byte-identical; keep moves a note only on the person's yes; stage never waits; promote → unknown tool
provenance mandatory9 refusal shapes, none reach disk
scope wallsMAGNEMO_SCOPE=dev never returns ops-only canon; explicit scope=ops → SCOPE WALL
budgets cap payloads, truncation loggedserved ≤ budget; truncated in both payload and cost event; clamp at 32 000 logged
free tiermcp.py imports stdlib + package only; no network words anywhere in the chain
least privilegeexactly seven names; dispatch gated to declared tools; no eval/exec/shell

Three postures

1. Native. The agent runs with this server mounted and uses the four verbs directly: bootpack on wake, retrieve before acting, stage what it learned, handoff at ~88%. The vault is the agent's memory. (Claude Code via .mcp.json, any MCP client.)

2. Mount-and-govern. The agent already has its own memory (a framework store, a vector DB, a notes folder). Mount this server alongside it and route only the governed moments through the four verbs: candidates worth your review go to stage; decisions the agent must not make alone are retrieved from canon. The existing store keeps scratch; MAGNEMO keeps truth. Nothing in the agent's own memory becomes canon without passing the staging gate.

3. Gateway. One server process, many agents, each with its own MAGNEMO_AGENT / MAGNEMO_SCOPE / MAGNEMO_PARTITIONS — or one process per agent behind a gateway that sets those per connection. Scope walls give a dev agent dev, an ops agent ops, and the shared/ bus to both; receipts, cost events, and handoff telemetry stay attributable per agent. The yes is still the person's: said in the chat (keep, unverified) or typed at the CLI (verified).

In every posture the same two things are true of this server: agents can only stage, and no tool keeps a note on the agent's own authority.

AS IN MAGNEMO-AI/MAGNEMO AT 0.6.11 · README.MD · DOCS/MCP.MD