mecha-graph
A personal knowledge graph that turns your own data — mail, calendar, notes, messages — into context any agent can use. It is mecha's memory, and it is deliberately its own project: github.com/ljchang/mecha-graph, three crates on crates.io, served over MCP to any client, usable without mecha at all.
The deliverable is not a database, it's a context pack: every interface returns a token-bounded, provenance-carrying, freshness-stamped slice.
Data imports as episodes (append-only evidence, idempotent by source id); linkers wire episodes to entities through mentions; and facts — bi-temporal interpreted claims, each with episode provenance — are either asserted directly by high-trust sources or staged as candidates that your review promotes. Episodes are evidence, nodes are things, facts are beliefs, the context pack is the product. The full mental model is in Architecture.
Install
cargo install mecha-graph # the CLI
cargo install mecha-graph-mcp # the MCP server
Embeddings come from a second llama-server on 127.0.0.1:8081, serving
harrier-oss-v1-0.6b — its own port, because one llama-server holds one
model and the chat model's port must not answer embedding requests. The
launcher's source is scripts/llama/mecha-embed-server in a mecha
checkout, and what runs is a copy of it in ~/.local/bin, never the
checkout's own file (a git checkout would otherwise change a running
service). On the machine these docs were written on it runs on demand (the port is held from
boot, the model loads on the first request and stops after ten idle
minutes). On a machine without that socket unit, start it by hand. First
fetch the model — hf download mradermacher/harrier-oss-v1-0.6b-GGUF harrier-oss-v1-0.6b.f16.gguf — since the script looks for it in the
Hugging Face cache and starts with no model if it is missing; then run the
script with MECHA_EMBED_PORT=8081
— it takes no arguments, and otherwise listens on :18081, the port the
on-demand proxy forwards to — or run llama-server yourself with its
flags: -m the model, --alias harrier-oss-v1-0.6b (the name mecha-graph
asks for), --host 127.0.0.1 --port 8081 -ngl 999 -c 32768, and
--embeddings --pooling last --embd-normalize 2. --pooling last is not
optional for this model: the default pooling returns plausible vectors that
retrieve worse, with nothing to say so. The repository has no installer that sets the server up
from nothing yet; scripts/llama/install-embed.sh only moves an existing
always-on one to on demand.
What it costs is under Beside the chat
model.
To point it elsewhere, set [llm] embed_url in mecha-graph's config or
MECHA_GRAPH_EMBED_URL (mecha-graph 0.1.5); everything else is
self-contained. To see it work with no
personal data at all, a checkout's eval/synthetic/run.sh builds a
throwaway graph from a fictional corpus and grades 24 retrieval queries
against it.
Feed it
mecha-graph source add ics --url '<secret-ical-url>' --me you@example.edu
mecha-graph source add mbox --path ~/Takeout/mail.mbox --me you@example.edu --retention capture_delete
mecha-graph source sync # cursored, idempotent — re-runs are no-ops
mecha-graph link --auto
mecha-graph embed
mecha-graph query "what did we discuss about the pilot data?"
Per-source auth and configuration live in Integrations.
The store is SQLCipher-encrypted at ~/.mecha-graph/graph.db, with the key
beside it (mode 0600 — back it up separately); sends nothing anywhere, and
redact is a true delete. The full privacy story is in the
repository README.
Wire it into mecha
[[mcp]]
name = "graph"
command = "mecha-graph-mcp"
# The kg_* tools carry their own namespace; skip the graph__ prefix.
prefix_tools = false
# The graph holds other people's words, so reading it must arm the
# trifecta interlock. No MCP annotation can declare that; config forces it.
[mcp.capabilities]
untrusted_input = true
Why the override matters — and how episodes, corrections, and review move
between the two projects — is the Memory page's
story. Any other MCP client wires the same binary with none of this:
claude mcp add graph -- mecha-graph-mcp.
Where you review what it proposes
The graph stages candidates rather than asserting them, which means there is always a queue with your name on it. Several surfaces open onto the same store, and none of them is the privileged one:
mecha review sample— the command line, and what the others drive underneath./queuesin the TUI — the graph's merge queue in the same list as every other store waiting on you. See the unified queue.- Review → Graph queue in the web surface — the same deck on a phone.
- The graph page itself, which is the interesting one. Opening an entity
shows every fact the graph holds about it, and a fact the graph has served
to a run but nobody has ruled on carries
Confirm/Refuteright there. That is review-on-use: the queue comes to you at the moment you are looking at the thing anyway, rather than waiting for you to visit a queue. A refuted fact stays visible, dimmed and marked — a recorded no, not a weak yes, because "we decided against this" and "we never looked" are opposite findings.
There is a live, clickable copy of both pages in
the web surface — the graph and review tabs.
This is the half of the design that does not live in the graph repository: the graph decides what to propose, and a model never accepts its own candidate — acceptance crosses a human, structurally, which is why the queue exists at all rather than a confidence threshold.
How it improves itself
The graph is designed to get better with minimal oversight: an autonomy ladder for extracted claims, a mechanical error contract for corrections, and adversarial "gossip" sessions that surface gaps and contradictions — the whole design, with its settled decisions and build order, is in Self-improvement.