# Run ALF as an MCP server

ALF ships an [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server **inside the `alf` binary**. Point an MCP-capable agent host at it and your agent backs itself up by tool call — while a background **watch loop** keeps its memory synced as it changes, at **zero LLM token cost**. Configure it once; the agent just keeps working.

This page is the overview. For the exhaustive tool schemas, the per-client config fragments, and the sync internals, see the [CLI reference](/docs/cli#alf-mcp-serve).

---

## What MCP mode is

Instead of the agent shelling out to `alf sync`, an MCP host — Claude Code, Claude Desktop, Hermes, ZeroClaw, anything that speaks MCP — spawns `alf mcp serve` and drives ALF over JSON-RPC on stdin/stdout. The host owns the process: it starts the server for the session and terminates it (stdin close → SIGTERM → SIGKILL) when the session ends.

Reach for MCP mode when your agent runs under an MCP host and you want backups to be **hands-free and token-free**. On machines without an MCP host, the same syncs run from the CLI on a schedule (cron) — MCP mode doesn't replace the CLI, it drives the same machinery for you.

> **The protocol owns stdout.** Every tool returns the exact JSON the CLI prints — as typed `structuredContent` and a text block — and all diagnostics go to stderr. One binary interoperates with clients on every protocol revision: it negotiates down to a known revision rather than failing the handshake.

---

## The token-free watch loop

The watch loop is what makes MCP mode free. Once the server is running it watches the agent's memory — a filesystem event plus a bounded polling fingerprint, so editors and database engines that evade inotify are still caught — debounces, and calls the **same sync seam** a tool call would, outside any model turn, so it never spends tokens.

- **Cadence.** Memory and raw changes ride the delta channel: floor **1 min**, ceiling **24 h**. A change to a [tracked file](/docs/cli#alf-add) triggers a full-snapshot rollover on its own knob — floor **15 min**, default **1 h**. Steer both with `alf_watch_set` (values are clamped).
- **Catch-up on start.** On spawn the loop scans against the base snapshot, so anything that changed while no server was alive syncs on the first tick. A crash, a reboot, or a laptop closed for a week all resolve the same way: next session, first tick, one delta.
- **Crash-safe.** The MCP spec sanctions SIGKILL as normal shutdown; state writes are atomic and uploads are sequence-checked server-side, so a killed sync retries cleanly.
- **No daemon.** The loop lives only as long as the host keeps the session alive. Host-independent cadence stays with the CLI + OS cron.

When the loop can't make progress it **parks** and reports a code through `alf_status` — see [Retiring an agent](#decommissioning).

---

## The 13 tools

Every tool maps to the same inner seam its CLI command uses — the server is a fourth *caller* of the sync machinery, never a second implementation. Full input schemas are in the [CLI reference](/docs/cli#alf-mcp-serve).

| Tool | What it does |
|---|---|
| `alf_status` | Config, per-agent service status, the live watch-loop stanza, and last sync outcome — the agent's one monitoring query. |
| `alf_check` | Full pre-flight diagnostics (runs discovery for supported runtimes). |
| `alf_sync` | Incremental sync; registers on the first call. Emits progress. |
| `alf_restore` | Head restore, point-in-time preview, or dry-run listing. Pauses the watch loop. |
| `alf_export_dry_run` | The what-would-sync preview; writes nothing. |
| `alf_track` | Add a file to the include list; idempotent. |
| `alf_configure` | Generic runtime only: validated read-modify-write of `.alf-map.json`. |
| `alf_vault_add` | Encrypt + upsert a credential (returns a fingerprint, never bytes). |
| `alf_vault_list` | Plaintext descriptors only; no key is touched. |
| `alf_vault_delete` | Descriptor-level delete via a discriminated selector. |
| `alf_agents_list` | Mapping rows + per-agent sync state. |
| `alf_watch_set` | Steer the watch loop: cadence knobs and pause/resume. |
| `alf_docs` | Progressive-disclosure docs — instead of twenty more tools. |

**Deliberately not tools.** Destructive or trust-boundary ceremonies an agent must not self-serve stay CLI-only: `alf purge`, `alf sync --force-first-sync`, `alf vault rotate-key`, `alf vault decrypt`, `alf login`, and external-root blessing. Enabling or disabling an agent from inside a session is deferred to v1.2 — until then, run one server per agent or toggle with the CLI.

---

## Set it up per host

Install `alf` (the normal installer), authenticate once, then register the server with your host:

```
alf login --key <your-api-key>
alf mcp serve -r <runtime> [-w <workspace>] [--agent <alias-or-id>]
```

`-r` is `openclaw`, `zeroclaw`, `hermes`, or `generic`. `-w` (workspace) is **required for `generic`**; the supported runtimes resolve it from discovery. Secrets and identity are read from the server's environment **before the model's first turn**, so they never transit model context:

| Variable | Required | Purpose |
|---|---|---|
| `ALF_API_KEY` | yes¹ | Service API key (a key in the config file wins; the env var is the fallback). |
| `ALF_API_URL` | yes¹ | Service base URL. |
| `ALF_AGENT` | **strongly** | Pins the agent. A long-lived server **must** pin explicitly — "sole-enabled" breaks the moment a second agent is enabled. |
| `ALF_HOME` | no | Overrides the `~/.alf` base — a stable anchor when the host rewrites `$HOME`. |

¹ or its config-file equivalent. There is no `ALF_WORKSPACE`; the workspace is pinned by `-w` in the server's `args`.

The per-client fragments — Claude Code (`.mcp.json`), Hermes (`~/.hermes/config.yaml`), ZeroClaw (`mcp_servers`/`mcp_bundles`) — plus the timeout and respawn notes (Claude Desktop needs an app restart after a crash) are in the [CLI reference](/docs/cli#mcp-client-configuration). Each framework guide also shows its own fragment: [OpenClaw](/docs/openclaw-guide#mcp-mode), [ZeroClaw](/docs/zeroclaw-guide#mcp-mode), [Hermes](/docs/hermes-guide#mcp-mode).

---

## Multi-agent & the vault

Environment is **per-server, not per-agent**, so a host that runs several agents declares **one server entry per agent** and pins each one's `ALF_AGENT`. The watch loop then syncs each agent independently.

Credentials go through the vault tools (`alf_vault_add` / `alf_vault_list` / `alf_vault_delete`). On the `generic` runtime — which has no default CLI key path — `alf mcp serve` **auto-generates** the vault key at `~/.alf/vault-keys/<alf-agent-id>.key` on first use, so an agent can start storing secrets without a manual `keygen`. The service only ever sees ciphertext, so **back that key file up offline** — there is no escrow. The supported runtimes keep their per-agent key under `~/.<runtime>/state/<alf-agent-id>/.alf-vault-key` as usual.

---

## Retiring an agent

Retiring an agent is a **deliberate human CLI operation** — never an MCP tool, so an agent can't delete its own cloud history.

**Stop syncing, keep everything.** `alf agents disable <alias-or-id>` marks the agent ineligible for sync; the cloud archive and local state are untouched, and `alf agents enable` brings it back. A running server pinned to a disabled agent **parks** at its next sync — `alf_status` shows park code `watch_parked` (the underlying error is `agent_disabled`).

When the watch loop parks for any reason, `alf_status` reports one of: `sync_first_sync_conflict`, `sync_conflict_unresolved`, `sync_missing_base_unresolved`, `sync_poisoned_base_unresolved`, `restore_incomplete`, `watch_parked`, `auth_failed`, `watch_panicked`, `lock_unavailable`. A successful manual `alf_sync` (or an `alf_watch_set` resume) clears the park — except `restore_incomplete`, which needs its head restore re-run first. Full teardown (`alf purge`) is in the [CLI reference](/docs/cli#decommissioning-an-agent).
