Components
AsanagiDB-mcp
The MCP (Model Context Protocol) server. Bridges AI tools โ Claude, Gemini, Cursor, any MCP-capable client โ to the AsanagiDB graph store. Runs locally on 127.0.0.1 by default. Supports federated deployment via --central (client) and --public (server) modes, both secured with automatic mTLS.
Modes
Local
Default mode. AI tools on the same machine connect to 127.0.0.1. No certs, no config.
--central
Connect this MCP instance to a remote central server. mTLS certs auto-provisioned via Sigil on first run.
--public
Run as a federation server on 0.0.0.0. Requires mTLS โ refuses to start without certs. Server-to-server only; AI tools never connect here directly.
Quick Start
# local mode โ AI tools point to http://localhost:8080
asanagidb-mcp
# connect to a central (remote) MCP server โ Developer license required
asanagidb-mcp --central tcp://10.0.0.1:8443
# run as a federation server โ mTLS is mandatory
asanagidb-mcp --public --http-port 8443 Flags
--http-port <port> HTTP port for local AI tool connections (default: 8080) --db-name <name> Database name / tenant to connect to --db-path <path> Path to the AsanagiDB Unix domain socket --remote <path> Proxy to a standalone AsanagiDB engine daemon instead of a local database โ UDS path or tcp://host:port (Developer license required for tcp://) --central <tcp://host:port> Connect to a remote central MCP server (Developer license required) --public Enable federation server mode on 0.0.0.0 (mTLS required) --cert-dir <path> Directory for mTLS certs (default: ~/.Asanagi) --sigil-url <url> Sigil endpoint for automatic cert provisioning --rag-folder <path> A folder whose documents assistants may read into memory and search (repeatable). Turns on the rag_* tools. Not with --public --rag-light-folder <path> As --rag-folder, but a lighter reading: summaries, concepts and questions, no facts --rag-memory <words> Memory notes with one of these comma-separated words in their name (decision,design,...) are documents too, read as memory:<name>. Turns on the rag_* tools --workspace <name> The name assistants are told the memory belongs to (default: the database name) --config <file> Read these settings from a JSON file (see below); flags on the command line win Document Memory (RAG)
Give asanagidb-mcp folders to read and an assistant can
read your documents into the memory database, then search them before it answers. The graph keeps each
document's structure: its sections, the concepts they mention, the facts and questions they answer, and how
the concepts relate. It records where each section is in its file, never the text, so the assistant reads
the exact words from your file when it needs them. Memories can point at document concepts
(memory_save with about).
asanagidb-mcp --db-name memory --rag-folder ~/Notes --rag-folder ~/Projects/docs Reads Markdown, plain text, reStructuredText, Org, AsciiDoc and TeX. PDFs are read by AsanagiDB Desktop. Files outside the folders you name are refused, symlinks included. Tools: rag_list_documents, rag_begin_document, rag_read_sections, rag_submit_concepts, rag_search, rag_forget_document, rag_status.
Memory notes can be documents too, with nothing exported to files. With
--rag-memory decision,design,architecture, every note whose
name has one of those words (decision_cache_policy,
rope_design) is read like a file, as
memory:<name>. When a note is saved with new text it lists
as changed, so the assistant reads it again; rag_status counts the
notes waiting to be read.
asanagidb-mcp --db-name memory --rag-folder ~/Notes --rag-memory decision,proposal,design,architecture
The server holds every assistant to the same reading rules: a section must be read with
rag_read_sections before it is reported, a section of 300 characters or more needs 2 to 6
questions, a concept's kind comes from a fixed list (person, place, work, organization, system, event,
era, topic, term, decision), and the reader names its model (extractor). A section that breaks
a rule comes back with the reason, to be fixed and sent again. A document from a folder you no longer
list shows as gone and can still be forgotten.
Config File
Instead of a long command line, put the settings in a JSON file and start the server with
--config. The keys mirror the flags; paths may start with ~/. Flags given on the
command line still win: a single flag replaces the file's value, and a folder or memory flag replaces the
file's list. An unknown key stops the server, so a typo can't silently drop a setting.
{
"db_path": "~/asanagi/memory",
"http_port": 7474,
"workspace": "Work",
"rag_folders": ["~/Documents/Notes", "~/Projects/docs"],
"rag_light_folders": ["~/Documents/Journal"],
"rag_memory": "decision,proposal,design,architecture"
} Keys: db_path, db_name, remote, central, http_port, public, cert_dir, sigil_url, workspace, rag_folders, rag_light_folders, rag_memory (a list, or one comma-separated string).
One Server, Many Assistants
If more than one assistant uses the same database at once — several Claude Code windows, Claude Code
and Gemini, a person and an agent — run one asanagidb-mcp and let every assistant connect to it over
HTTP. By default each session starts its own process over stdio, and all of them open the same
--db-path.
Why
LMDB lets many processes share a database, but a process that dies while it holds the lock can leave it taken, and every other process then waits with no timeout — even for a read. We saw four stdio servers on one data directory where nothing completed for 30 minutes, and reproduced the hang by killing processes at random while four others read and wrote. One server owns the database, so there is no lock to leave behind.
Seen and reproduced on macOS only. Whether Linux or Windows recover from a dead lock holder is not tested, so the advice is the same everywhere. Not proven: that a closing assistant session is what held the lock in the original report.
# one server for every assistant; keep it running with your service manager
asanagidb-mcp --db-path ~/asanagi/data --http-port 7474
# then point each assistant at it (Claude Code CLI)
claude mcp add --scope user --transport http asanagidb http://127.0.0.1:7474 - Quit every assistant session that uses the memory server.
- Remove the old stdio entry for the same database from the
assistant's settings. This is the step people skip: a stdio
asanagidb-mcpstill pointing at the same--db-pathshares the database with the new server, which is the setup that hangs. -
Start the server at login and restart it after a crash — a LaunchAgent with
KeepAliveon macOS, a systemd user unit on Linux (untested), a service wrapper or scheduled task on Windows (untested). - Check the log says it is listening on 127.0.0.1, then start a new session and run a
memory_search.
Do not set ASANAGIDB_MCP_HTTP_PORT for this: with it, each
stdio process would try to open its own listener on the same port. The server binds 127.0.0.1 only (unless
--public), and it has no token check on this path, so
anything on the machine can reach the port.
A Note on --remote
--remote is unrelated
to federation โ it proxies this MCP instance straight to a standalone
AsanagiDB engine daemon
over its own wire protocol, not to another AsanagiDB-mcp instance.
A Unix domain socket connection needs no TLS โ it's local and
filesystem-permission-scoped. A tcp:// connection is plaintext by design: AsanagiDB does not implement
TLS for this link itself. We strongly recommend putting a TLS-terminating
reverse proxy (e.g. Caddy) in front of the engine daemon's TCP port
if it crosses an untrusted network โ but it isn't required. If you're
fine connecting over a trusted network, or just want to use a UDS
path, that's a supported choice too.
Federation Architecture
AI Tool โโMCP (HTTP, plain)โโโบ asanagidb-mcp (local, 127.0.0.1)
โ
--central tcp:// (mTLS)
โ
โผ
asanagidb-mcp --public (remote MCP Server, 0.0.0.0)
AI tools never connect to a --public instance directly. The public port is server-to-server only, always
mTLS.
Trust on this link comes from the mTLS client certificate and its Sigil-issued license binding, not from hostname matching โ federation peers are known by license identity, not by DNS name, so the connection address is not checked against the certificate's subject.