Skip to main content
Glama

Montauk

Relationship memory for personal agents. An MCP server giving a personal-assistant agent durable, private, human-readable memory of the people in one human user's life.

The canonical database is a directory of Markdown person files (data/people/*.md). SQLite and a semantic vector index are derived, fully disposable acceleration layers that can be deleted and rebuilt at any time without data loss. See montauk_phase1_build_spec.md for the full Phase 1 specification this implementation follows.

Quick start (local, stdio)

uv sync
uv run montauk init --data-dir ~/.local/share/montauk
uv run montauk agents create --name my-agent --role read_write --data-dir ~/.local/share/montauk
# prints a token once -- save it
export MONTAUK_AGENT_TOKEN=<the token printed above>
uv run montauk serve --config ~/.local/share/montauk/config.yaml

serve reads MONTAUK_AGENT_TOKEN once at startup to resolve the single stdio client's identity (there is exactly one client on stdio, so there's no per-request header to read). Point an MCP-compatible agent host at that serve command as a local stdio server. Try it against the bundled Simpsons fixture instead of an empty repo by pointing --data-dir at examples/simpsons/.

Related MCP server: mcp-ltm

Setting up your private data repository

montauk init scaffolds a deployment: it creates the data directory (people/, archive/), writes a starter config.yaml, and initialises a local git repository for the canonical Markdown -- on branch main, with an initial commit, and a .gitignore that excludes the derived indexes (index/), agent credentials (auth/), and logs.

uv run montauk init --data-dir ~/.local/share/montauk

Choose a data directory outside this source checkout -- ~/.local/share/montauk for a personal deployment, /var/lib/montauk for a system service. Never put it inside a synced folder (Dropbox/iCloud/Drive): sync races corrupt the git repo and it copies plaintext personal data to a third party.

This data repository holds real personal information, so keep it private and separate from the Montauk source code. Montauk deliberately never adds a git remote and never pushes (spec §29) -- that is yours to wire up:

cd ~/.local/share/montauk
# create an EMPTY private repo on your git host first (no README / license / .gitignore)
git remote add origin git@github.com:<you>/<your-data-repo>.git
git push -u origin main

While montauk serve runs it makes at most one local commit per day, when a person file has changed. Pushing those commits to your remote is up to you -- e.g. a cron entry:

15 3 * * *  cd ~/.local/share/montauk && git push -q origin main

montauk init is idempotent and never clobbers an existing config.yaml, so it is safe to re-run.

Configuration

Non-secret settings live in a YAML config file; copy config/config.example.yaml and adjust data_dir, transport mode, git snapshot time, and search/embedding settings. Validate a config without starting the server:

uv run montauk config-check --config config.yaml

Secrets are never read from config files -- agent credentials live in <data_dir>/auth/credentials.sqlite, managed only via montauk agents .... See .env.example for the one environment variable the stdio transport reads (MONTAUK_AGENT_TOKEN).

Admin CLI

montauk init --data-dir PATH              # scaffold a new deployment + private data repo
montauk validate                          # scan + validate; exit 1 if unhealthy
montauk status                            # health summary
montauk rebuild-index                     # rebuild the derived SQLite index from Markdown
montauk rebuild-vectors                   # rebuild the derived semantic index from Markdown
montauk git-snapshot                      # commit data/people + data/archive now, if changed
montauk agents list
montauk agents create --name X --role read_only|read_write
montauk agents revoke <agent-id>
montauk config-check --config config.yaml
montauk serve                             # the only long-running command

Every command accepts --data-dir PATH for quick/direct use, or --config PATH to load a full YAML config (data-dir overrides the config's data_dir if both are given). Person content is never edited through this CLI -- only through MCP tools or by hand-editing the Markdown directly (changes take effect after the next server restart or rebuild-index).

Remote (authenticated HTTPS) deployment

Set transport.mode: remote in the config. Montauk refuses to start a remote transport bound to 0.0.0.0/:: unless auth is configured (it is, by default) -- put a TLS-terminating reverse proxy in front for real internet-facing deployments; Montauk itself only speaks plain HTTP. Each remote agent authenticates with Authorization: Bearer <token> from montauk agents create.

Docker

docker build -t montauk-mcp .
docker volume create montauk-data
docker run --rm -v montauk-data:/data montauk-mcp agents create --name my-agent --role read_write --data-dir /data
docker run --rm -i -v montauk-data:/data -e MONTAUK_AGENT_TOKEN=<token> montauk-mcp serve --data-dir /data

The image pre-downloads the default embedding model at build time, so a fresh container needs no network access on first run. Persistent data (/data) is a volume, never baked into the image.

Bind mounts and file ownership: the container runs as a non-root user (uid 1000). A Docker named volume (as above) works out of the box -- Docker initializes it from the image's /data ownership on first use. A host bind mount (-v /path/on/host:/data) does not: the host directory's existing ownership wins, so if it isn't already owned by uid 1000, montauk won't be able to write to it. Either chown -R 1000:1000 the host directory first, or run the container with --user "$(id -u):$(id -g)" to match your host user instead.

Development

uv sync
uv run pytest

examples/simpsons/ is a synthetic fixture (recognizable fictional characters, not real people) used by the test suite and handy for manual exploration -- it includes a duplicate-name collision, a missing-birth-year birthday, a person with a contact cadence but no recorded interactions, an archived person, and one deliberately malformed file, exercising the corresponding edge cases end to end.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    A local-first shared memory layer for MCP-aware agents like Claude, Codex, and Hermes, enabling persistent memory across chats and clients via Markdown files and SQLite FTS.
    6
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides persistent long-term memory for AI assistants with tag-based retrieval, wiki-style linking, and source references, storing memories as markdown files with SQLite index.
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides AI agents with persistent, long-term memory via OKF-formatted markdown and SQLite indexing, enabling stateful storage, retrieval, and search across sessions.
    6
    212
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to maintain a persistent, queryable memory stored as user-owned Markdown files, with dual-channel retrieval (FTS5 and optional semantic search) and an audited write pipeline.
    11
    MIT