Reference

Using Roam via MCP

How to call Roam from Claude Code, Cursor, Codex, Gemini CLI, Amp, VS Code, and any other Model Context Protocol client. Covers first-run setup, the cold-start envelope your agent will see on a fresh repo, the tools that work without an index, the canonical agent flow, slow-tool patterns, and the failure modes that have tripped up real users.

MCP setup itself (per-platform commands and config snippets) lives in Integration Tutorials. This page assumes the server is already wired up and focuses on what your agent should actually do with it.

First-run setup

Run roam init in your project root before the first MCP call. It builds .roam/index.db — the local SQLite graph Roam queries on every subsequent tool call. Initial indexing typically takes 30 to 120 seconds on a medium repo and is a one-time cost; later runs are incremental.

cd /path/to/repo
roam init             # creates .roam/index.db + fitness rules + CI workflow
roam health           # verify the index is healthy (0-100 score)

Why this is a manual step: indexing can take long enough to exceed an MCP call timeout, and forcing an automatic build on first use hides that cost from the agent. We surface the cost explicitly so the agent (or the human driving it) can budget for it. See the next section for what your agent receives when it skips this step.

The cold-start envelope

When an MCP tool that needs an index is called on a project where .roam/index.db does not exist, Roam does not hang or auto-build. It returns a structured envelope the agent can read and act on:

{
  "command": "roam_health",
  "status": "index_not_built",
  "summary": {
    "verdict": "Index not built. Run `roam init` in a terminal first, then retry MCP tools.",
    "level": "blocker",
    "partial_success": false
  },
  "next_command": "roam init",
  "expected_duration_seconds": 60,
  "retry_after_seconds": 60,
  "agent_contract": {
    "facts": [
      "0 of 8 evidence questions answered without indexed symbols",
      "1 prerequisite command unmet -- run roam init"
    ],
    "next_commands": [
      "roam init",
      "# then retry the MCP tool that returned this envelope"
    ]
  },
  "_meta": {
    "guard": "w296_cold_start",
    "tool": "roam_health"
  }
}

Wire your agent prompt to recognise status == "index_not_built" and either run roam init itself (if the agent has shell access) or ask the human to. The next_command field is copy-paste executable; the retry_after_seconds field is a hint for how long to wait before retrying the original tool call.

To bypass the guard for tests or scripts, set ROAM_MCP_DISABLE_COLD_START_GUARD=1 in the server environment. Production agent setups should leave it on.

Tools that don't need an index

Nine MCP tools are exempt from the cold-start guard because they either create the index, diagnose the install, or operate on caller-supplied data:

ToolPurpose
roam_initBuild the index. Run this first.
roam_reindexRebuild the index (incremental by default).
roam_doctorDiagnose the install — Python, extras, grammars, schema version, stale index.
roam_catalogMachine-readable list of every registered MCP tool plus capability flags.
roam_expand_toolsetSwitch the active preset (core / review / refactor / debug / architecture / full).
roam_session_metricsPer-session counters for the current MCP connection.
roam_evidence_doctorValidate a ChangeEvidence packet passed in by the caller.
roam_fetch_handleFetch all or part of a large MCP payload by handle (byte slice, section pick, jq projection).
roam_pr_comment_renderRender a markdown PR comment from a roam_pr_analyze envelope.

Everything else is gated by the cold-start guard. Adding a new exemption is a deliberate source-code change pinned by a drift test.

Typical agent flow

The canonical sequence for an agent given a free-form change request looks like this. Every call is a single MCP tool invocation; no shell-out, no subprocess fan-out.

# 1. Verify the index exists (or create it).
roam_doctor()
roam_init()                                   # if cold-start envelope returned

# 2. Orient before touching code.
roam_health()                                 # 0-100 score + top issues
roam_understand()                             # one-screen codebase briefing

# 3. Find the relevant symbol or files for the task.
roam_retrieve(task="where does login validate sessions", budget=4000)
roam_context(symbol="auth_login")             # files + line ranges to read

# 4. Gate before editing.
roam_preflight(symbol="auth_login")           # blast radius + tests + fitness
roam_impact(symbol="auth_login")              # what breaks if this changes

# 5. Make the edit (out-of-band, in the editor / via the agent's edit tool).

# 6. Verify the patch.
roam_diff()                                   # blast radius of uncommitted changes
roam_critique(diff_text="")     # clones-not-edited + blast radius

# 7. Optional: package the proof.
roam_pr_analyze(diff_text="")   # INTENTIONAL / SAFE / REVIEW / BLOCK

Steps 1 and 2 are once-per-session; steps 3 through 7 repeat per task. The Agent Contract documents the five discipline rules behind this sequence (context before edit, impact before delete, critique before merge, simulate before refactor, math before optimise).

Tools that take longer than expected

A handful of tools produce envelopes large enough to push past a default MCP call budget. Reach for the handle pattern or a narrower scope when invoking these:

ToolWhy it's heavyWhat to do
roam_capsule_export Exports the entire sanitised structural graph; can exceed 1M tokens on large repos. Write to file via the CLI (roam capsule --out capsule.json) and reference the path, or scope with --include.
roam_orchestrate / roam_partition Multi-agent partitioning emits one entry per cluster; thousands of entries on large repos. Use --n-agents to bound output, or call roam_fleet_plan which emits a compact .roam-fleet.json instead.
roam_fingerprint Per-symbol topology fingerprints across the whole graph. Pass --top N or restrict to a subgraph.
roam_verify_imports Cross-language import resolution over every file. Scope to changed files with --changed.
Any tool returning more than 20K tokens The payload may be truncated by the client. The tool returns a handle field; call roam_fetch_handle(handle, section=...) to page through the payload.

roam_explore is the recommended browse-style entry point because it auto-applies the handle pattern: large envelopes are split, you get a small summary plus a handle, and you fetch detail by section.

Troubleshooting

Tool hangs or times out

Check that .roam/index.db exists in the working directory the MCP server was launched from. If it does not, the cold-start guard should have returned an index_not_built envelope rather than hanging — if you see a real hang, run roam doctor to confirm the install, then roam init to build the index. Cloud-sync filesystems (OneDrive, Dropbox, iCloud) sometimes lock the SQLite file; see Troubleshooting #2.

USAGE_ERROR on roam_doctor

Known issue: roam_doctor emits a non-zero exit even on advisory failures (missing optional extras), which the MCP wrapper currently surfaces as USAGE_ERROR. The underlying diagnostics are still present in the envelope. Read summary.verdict and checks[] rather than the top-level status.

Empty result from roam_dead_code or roam_smells

Empty is a valid signal — the project may genuinely have no unreferenced exports or no flagged smells. Check the JSON envelope: summary.verdict will say "0 findings" (good) rather than failing silently. If you expected findings and got none, run the CLI equivalent with --debug to confirm detector coverage.

Tool not found

The default preset is core (57 tools plus the roam_expand_toolset meta-tool). Tools outside that preset are loaded on demand: roam_expand_toolset(preset="full") exposes all 224 tools. You can also set ROAM_MCP_PRESET=full in the server env to start with the full set.

Server returns stale data after a git pull

Run roam reindex (or set ROAM_MCP_WATCH=1 in the server env to enable reactive incremental reindexing on file changes). The watcher emits notifications/resources/updated so subscribing clients see fresh data without polling.

When to use MCP vs the CLI directly

SurfaceUse it when
MCP An AI coding agent (Claude Code, Cursor, Codex, Gemini CLI, Amp, custom) is driving the workflow. The agent gets structured envelopes, schema-versioned output, and shared session memory across calls.
CLI A human is exploring interactively, or a CI pipeline / git hook / script is invoking Roam. CLI output supports --json, --sarif, and VERDICT:-first text; subprocess invocation is the right shape for non-agent automation.

Both surfaces share the same underlying engine — every MCP tool is a wrapper around a CLI command. Choose by the caller, not the capability.

See it run

The 5-minute canonical demo — install → health → preflight → critique → signed ChangeEvidence packet, end to end. The agent flow above in one sitting.