trackmcp
Back to directory

Local-first MCP memory server for AI agents, with source citations and OKF/Markdown knowledge bases.

13 stars GoOthers Updated Sep 2, 2026
ai-meclaude-codedeveloper-toolsfts5gogolangknowledge-basemcpmcp-serverokfpersonal-knowledge-managementragsemantic-searchsingle-binarysource-citationssqlite

Documentation

mnemos

CI
Go Report Card
Latest release
Go version
License: MIT
OKF BundleDex

Give your AI agent a memory it can cite.

> Local memory for AI agents. Source citations included.

Claude Code is powerful, but it forgets your project context:

  • it forgets why you rejected an architecture,
  • it misses your ADRs,
  • it invents answers instead of reading your docs,
  • it can't reliably cite where a claim came from.

mnemos fixes that by giving it a local, cited memory of:

  • your ADRs and design docs
  • your notes and runbooks
  • your source code
  • your OKF knowledge base

No vector database. No Ollama. No Python or Node service. Just one cgo-free Go binary

that indexes your files — any plain-Markdown folder works as-is — and serves them over

MCP, so Claude can **search, read, and cite your own

knowledge** instead of guessing, with every answer landing on the exact `file#section`

and line range.

Try it in 60 seconds

bash
# 1. install — one cgo-free binary into $GOBIN (requires Go 1.25+)
git clone https://github.com/arhuman/mnemos.git && cd mnemos
make install

# 2. index a project
cd ~/work/myproject
mnemos init                                 # creates ./.mnemos/ (mnemos.toml, kb, db, models)
mnemos ingest docs --collection myproject   # index a directory
mnemos search "why did we choose this architecture"

> Prefer `make build` (→ `./bin/mnemos`) to keep it off your `$PATH`. The default build

> is pure Go / cgo-free (`CGO_ENABLED=0`).

`search` prints citations you can open:

text
1. security/scim.md#Provisioning
   lines 42-88
   score 12.7

Then wire it into Claude Code (note the absolute `--config` path):

bash
claude mcp add mnemos -- mnemos serve --config /abs/path/to/myproject/.mnemos/mnemos.toml

Now Claude answers from your project instead of guessing, and shows its source:

> You: How do I recover lost commits?

>

> Claude: Per `recovery/reflog.md`, the reflog records where `HEAD` and each branch

> tip has pointed — even after a hard reset — so you can check out the lost commit's

> hash. *(recovery/reflog.md — "Reflog: recover lost commits")*

That's the whole loop — index → ask → cited answer. Everything below is depth:

why it's built this way, how it works, and the full

capabilities.

⚠️ One gotcha: a document's identity is its path relative to where you ran ingest

A document's URI is its path relative to the scan root you ingested (`docs` above), not

your working directory. Ingesting two directories that each contain (say) `index.md`

resolves both to the same URI: the second ingest silently overwrites the first. To

index several trees cleanly, ingest from one common root (`mnemos ingest .`). Details in

docs/paths-and-indexing.md.

Why mnemos

  • Truly local-first: runs entirely on your machine. No network, no telemetry, no data leaves your project.
  • Zero dependencies: one self-contained, cgo-free Go binary. No Python, Docker, Qdrant, or Ollama.
  • Any MCP client: built for Claude Code, works with anything that speaks MCP.
  • Cited answers: every result links back to the exact `file#section` and line range, so claims are verifiable.
  • Fast search by default: SQLite FTS5 / bm25 out of the box; optional local semantic + hybrid search behind a build tag.
  • Read-write memory: the agent can capture durable notes (`remember`); you can manage the tree (`forget`, `move`, `list`).
  • Safe by default: read-only unless you opt in; writes are path-confined and content is secret-scanned.

How it works

text
your files  →  mnemos index (SQLite/FTS5)  →  Claude Code memory  →  cited answers

Once wired in, Claude can answer from your project instead of hand-waving, and

point back to the source:

  • *"Why did we choose this architecture?"*
  • *"Where is the ADR about the rule engine?"*
  • *"Summarize what we know about SCIM provisioning."*
  • *"What changed in this project's memory recently?"*

Under the hood, the binary embeds an MCP server, an indexing pipeline, a SQLite

store, full-text search, an incremental file watcher, and an admin CLI. See

docs/architecture.md.

Does it actually retrieve?

A cited hit, out of the box (default lexical build, on a shipped example bundle):

text
$ mnemos ingest examples/git-recipes/bundle --collection git
$ mnemos search "recover lost commits" --limit 1
1. recovery/reflog.md#Gotcha
   lines 24-28
   score 7.8

Every result is a real `file#section` and line range you can open — that is the whole

point.

Retrieval quality, measured. `mnemos eval` auto-derives held-out query→source pairs

from an OKF bundle (it strips each example block from its own document, then checks

whether retrieval still finds the right document) and reports doc-level metrics. On the

shipped `examples/git-recipes` bundle (6 recipes, keyword-style queries):

RetrieverHit@1Recall@12MRR@12
Lexical, default (FTS5 / bm25)0.830.830.83
Semantic + hybrid (`--semantic`)1.001.001.00

All three are fractions in `[0,1]` (×100 for a percentage); higher is better. The

`@K` is the retrieval depth — top‑1 for Hit, top‑12 for the rest:

  • Hit@1 — share of queries whose #1 result is the correct document (`0.83` = 5/6).
  • Recall@12 — share where the correct document appears anywhere in the top 12.
  • MRR@12 — mean reciprocal rank: average of `1/(rank of the first correct doc)` over the top 12 (`1.0` = always ranked first).

The default lexical build already nails keyword retrieval. The optional embed build (see

Semantic search) earns its keep on harder,

natural-language-over-structured-data queries: on the `examples/onpage-seo` bundle, whose

held-out answers are JSON-LD / sitemap-XML blocks that share *no* keywords with their

prose, lexical scores `0.00` while `--semantic` recovers Hit@1 `0.57` / Recall@12 `0.86`.

Reproduce (N is 6 and 7 respectively — smoke signals, not benchmarks):

bash
mnemos eval examples/git-recipes/bundle              # lexical → 0.83
make build-embed && mnemos models install all-MiniLM-L6-v2
mnemos eval examples/git-recipes/bundle --semantic   # hybrid  → 1.00
mnemos eval examples/onpage-seo/bundle --semantic    # the hard case → 0.57

Connect Claude Code

The 60-second path above used `claude mcp add` with an absolute `--config` path:

bash
claude mcp add mnemos -- mnemos serve --config /abs/path/to/project/.mnemos/mnemos.toml

To share it with the repo, commit it via `.mcp.json` instead:

json
{ "mcpServers": { "mnemos": { "command": "mnemos", "args": ["serve", "--config", "/abs/path/to/project/.mnemos/mnemos.toml"] } } }

Verify with `claude mcp list` (should show `mnemos ✓ connected`) and `/mcp` inside

a session. Claude then calls the tools automatically; see Capabilities.

Why the --config path must be absolute

Claude Code does not guarantee the working directory it spawns the server in, so

anchoring to the config file is what makes retrieval reliable. `mnemos serve`

resolves a relative `[storage].path` against the config file's directory, so an

absolute `--config` is all you need: the database, capture directory, and tree

root all anchor next to that file regardless of where Claude Code launches the

server. A bare `mnemos serve` only finds your data when the server's working

directory happens to be the project root, which Claude Code does not promise; when

the database can't be found, `serve` fails with a clear error instead of silently

returning empty results.

One command wires it in: Claude Code reports mnemos ✓ connected.

Semantic search: the question says "disappeared" — a word that appears nowhere in the notes — yet Claude finds and cites recovery/reflog.md.

> This clip uses the optional semantic build (`make install-embed` + `mnemos models install all-MiniLM-L6-v2` + `use_vectors = true`; see Semantic search). The default `make install` binary is lexical-only, so it won't answer a keyword-free question like this — search by keyword instead (e.g. `mnemos search "recover lost commits"`, which hits the same doc).

Make Claude use memory automatically (optional skill)

MCP tools are *passive*: they're available, but Claude still has to decide to call

`mnemos.search` before answering or `mnemos.remember` when you say something worth

keeping, and models often don't. The bundled `mnemos-okf` skill closes that

gap by encoding *when* to reach for memory: recall before answering from

assumption, capture durable facts, and drive the OKF tools.

It's optional and Claude Code-specific: the server works with any MCP client

without it. Install it user-wide (all projects):

bash
make install-skill        # copies skills/mnemos-okf -> ~/.claude/skills/ and merges its hooks

Or place it manually, e.g. project-level for this repo only:

bash
mkdir -p .claude/skills && cp -r skills/mnemos-okf .claude/skills/mnemos-okf

Capture is deliberately conservative (durable facts only, secret-scanned) and stays

gated behind `allow_write`/`allow_delete`: the skill never grants access the config

hasn't opted into. See `skills/mnemos-okf/SKILL.md`.

The memory loop

mnemos is local project memory for coding agents: cited recall, durable project state, knowledge consolidation.

text
prompt
  -> recall (search first, cite)
  -> act
  -> capture durable facts to the inbox
  -> update project/task state
  -> consolidate raw captures into canonical docs
  -> cite everything

The bundled `mnemos-okf` skill encodes this as six modes: RECALL, CAPTURE, OKF, RESTORE, TASK, and CONSOLIDATE. Tasks are `Task` documents grouped by `mnemos task list`. Consolidation never overwrites silently: conflicts are surfaced and passes are journaled.

The reference layout is in `examples/project-memory/bundle/`, a fictional project with status, constraints, decisions, tasks (state/history split), and a consolidation journal. Ingest it to see `mnemos task list` in action:

code
mnemos add examples/project-memory/bundle --into aurora --collection aurora
mnemos task list
code
in_progress (1)
  aurora/tasks/rate-limit-ingest.md  Rate-limit the ingest endpoint
todo (1)
  aurora/tasks/csv-export.md  Add CSV export
done (1)
  aurora/tasks/fix-auth-timeout.md  Fix auth token timeout

Automation with hooks

The skill is advisory: the model decides when to fire each mode. Claude Code hooks make the memory loop deterministic. `make install-skill` (or `make install-hooks` on its own) merges `skills/mnemos-okf/hooks/settings.example.json` into your `~/.claude/settings.json` idempotently, keeping a `.bak`; pass `SKIP_HOOKS=1` to opt out, or merge the file by hand for a project-level `.claude/settings.json`. Two hooks are activated:

HookMatcherEffect
`SessionStart``startup\resume\compact`Injects the working set at session start: `mnemos task list` plus recent decisions (`mnemos ls decisions`). The `compact` matcher re-injects it after context compaction.
`UserPromptSubmit`recall cue phrasesWhen the prompt matches "as we decided", "what was", "remember when", and similar cues, injects the top 3 `mnemos search` hits. Requires `jq`. Silent no-op when no cue matches.

PreCompact and Stop persistence (session summaries, capture flush) stays in the skill because those hook events cannot inject context into the model.

Capabilities

Claude reaches your memory through MCP tools (and you through the matching CLI

commands). Note the spelling: `mnemos.search` is the MCP tool Claude calls;

`mnemos search` is the CLI command you run.

Query (read-only, no gate)

  • `mnemos.search`: ranked, filtered retrieval with citations.
  • `mnemos.read`: read a precise chunk (by `chunk_id`) or a whole document (by `uri`). Pass `follow_links: true` to also attach the document's 1-hop link neighbors.
  • `mnemos.context`: top-k results as LLM-ready context blocks (`uri:start-end` → content). Pass `follow_links: true` to attach each block document's 1-hop link neighbors.
  • `mnemos.related`: the link-graph neighbors of a document, its outbound links and inbound backlinks (1 hop, document-level). Dangling outbound targets are returned with `resolved: false`. Filter with `direction` (outbound/inbound/both) and `limit`.
  • `mnemos.list`: walk the OKF tree on disk and annotate each file with index metadata (title, type, tags, collection) plus an `indexed` flag, so both stored and not-yet-indexed files are visible. Filter by `path`, `collection`, `type`, or indexed state.

Write (requires `allow_write = true`)

  • `mnemos.remember`: write a note into memory. Pass an optional `path` (e.g. `"adr/0003-rule-engine.md"`) to place it at an explicit location in the OKF tree instead of auto-naming under `[capture].dir`. Content is secret-scanned before it is written and indexed.
  • `mnemos.okfy`: convert an existing `.txt`/`.md` file in the tree into an OKF document (frontmatter + body) at `out` (defaults to the source path with a `.md` extension) and index it, leaving the source intact. The source body is secret-scanned first.

`mnemos edit ` is the human counterpart: a terminal editor for one document, gated by the same `allow_write` flag, with no MCP tool of its own. See Edit documents interactively.

Manage (requires `allow_delete = true`)

  • `mnemos.forget`: remove a file from the OKF tree and de-index it; idempotent.
  • `mnemos.move`: move a file or directory within the tree and re-index it under the new path. A directory moves its whole subtree, preserving each document's collection. Inbound markdown links to the old paths are not rewritten in V0 (logged as a warning).

Keep memory fresh

Run a watcher to reindex on change (incremental; removes deleted files):

bash
mnemos watch . --collection myproject

Enable write-back in `.mnemos/mnemos.toml` so Claude can capture and manage notes:

toml
[mcp]
allow_write = true     # gates mnemos.remember and mnemos.okfy
allow_delete = true    # gates mnemos.forget and mnemos.move

If a watcher is running over the tree, `forget`/`move` operations are also seen by

the watcher (redundant but idempotent); the tools update the index directly and

work without a watcher. Set `[capture] defer_to_watcher = true` when a watcher

covers `capture_dir` to avoid double indexation of remembered notes.

Edit documents interactively

`mnemos edit ` opens a terminal editor over one OKF document at a time,

split into three panes:

  • NAV: the document's outbound links, inbound backlinks, and (once an

embed build has computed embeddings for the corpus) semantically similar

documents; otherwise that section shows an unavailable hint instead of

results.

  • METADATA: frontmatter fields, typed per the document's OKF `type`. A

known enum (a task's `status` or `priority`) cycles with the arrow keys,

`tags` is retyped as a whole list, unknown fields fall back to free text,

and index-owned fields like `type` are read-only.

  • CONTENT: the body, handed to `$EDITOR` for editing and reloaded on exit.
bash
mnemos edit tasks/ship.md

Keys: `tab` focus, `↑↓` move, `enter` open/edit, `←→` cycle an enum, `e`

`$EDITOR`, `m` move/rename, `s` save, `b`/backspace back, `q` quit. Saving

writes the file first and then reindexes just that document, so an edit is

never lost even if reindexing fails; frontmatter writes preserve the rest of

the file (comments, key order, unrelated fields) instead of rewriting it.

Navigating to another document while the current one is unsaved saves it first.

`m` moves or renames the open document. It prompts with the current uri:

edit it freely, or press `tab` for a fuzzy-filtered picker of the directories

that already hold documents (`enter` relocates the filename under the picked

one, `esc` returns to the prompt). Committing renames the file on disk,

reindexes it under the new uri, and reopens the editor there; inbound links

still pointing at the old path are reported, not rewritten. Like `mnemos mv`,

it needs `[mcp].allow_delete = true` since the old index entries are deleted.

It requires a uri: bare `mnemos edit` errors, there is no tree-browsing picker

yet. It is gated the same way as `mnemos.remember`/`mnemos.okfy`:

toml
[mcp]
allow_write = true   # also gates mnemos edit

There is no matching MCP tool: `mnemos edit` is CLI-only, for a human at the

keyboard.

Semantic search (optional)

The default binary is lexical only (FTS5 / bm25) and stays small and cgo-free.

Local semantic + hybrid retrieval is fully implemented but compiled behind the

`embed` build tag, so the ONNX/tokenizer dependencies never enter the default

binary. To enable it:

bash
make build-embed                       # or: make install-embed  (still cgo-free, CGO_ENABLED=0)
mnemos models install all-MiniLM-L6-v2 # downloads the embedding model into ~/.mnemos/models
mnemos reindex --embeddings            # compute vectors for already-indexed chunks
mnemos search "why did we choose this architecture" --semantic

`--semantic` fuses bm25 with vector similarity, so natural-language queries that the

lexical index misses still resolve. Without the embed build (or an installed model)

the flag is rejected with a clear message; plain `mnemos search` always works.

How it works under the hood (model, pure-Go ONNX inference, RRF fusion):

docs/architecture.md.

OKF support

mnemos natively understands OKF

(Open Knowledge Format) bundles, and any Markdown vault with YAML frontmatter and

cross-links, with no special mode:

  • frontmatter `tags`/`type` become fuzzy ranking signals in FTS,
  • markdown links are captured as edges (stored, not yet traversed),
  • `index.md` files are treated as structure only (kept out of FTS and the link graph).

OKF bundles double as the corpus for `mnemos eval`, which auto-derives held-out

query→source pairs and reports Hit@1 / Recall@12 / MRR@12 against a committed

baseline. See docs/architecture.md.

Reference

Security

  • No network, no telemetry; the MCP server is stdio-only.
  • Shipped binaries carry SBOMs (generated with syft) and are signed with cosign (keyless OIDC).
  • Read-only by default. Write-back is opt-in (`allow_write = true`). Destructive operations (forget, move) require a separate opt-in (`allow_delete = true`).
  • All caller-supplied paths are validated by a confinement guard before any disk operation: `..` traversal, absolute paths outside the tree root, symlink escapes, access to `.mnemos/`, and `[security].exclude` globs are all rejected.
  • Captured content is secret-scanned before it is written or indexed.
  • Path/secret exclusion patterns keep `.env`, keys, and secret dirs out of the index.

See SECURITY.md for the full policy.

Development

bash
make build      # cgo-free binary -> bin/
make test       # go test -race ./...
make audit      # golangci-lint (incl. govet + staticcheck) + govulncheck + race tests
make tools      # install pinned dev tools (golangci-lint, govulncheck)
make help       # list all targets

Architecture, design principles, and the retrieval-evaluation methodology live in

docs/architecture.md; design decisions are recorded as

ADRs. Contributions welcome; see CONTRIBUTING.md.

License

mnemos is licensed under the MIT License: this covers mnemos's own code

and content. The repository also vendors third-party material that is not

covered by the MIT License and remains under its own terms; see

THIRD-PARTY-NOTICES.md (notably the example OKF bundle in

`examples/onpage-seo/bundle/`).

Frequently asked questions

What is mnemos?

mnemos is Local-first MCP memory server for AI agents, with source citations and OKF/Markdown knowledge bases.

How do I install mnemos?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is mnemos open source?

Yes — it is hosted on GitHub at https://github.com/arhuman/mnemos and has 13 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP