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.
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:
| Tool | Purpose |
|---|---|
roam_init | Build the index. Run this first. |
roam_reindex | Rebuild the index (incremental by default). |
roam_doctor | Diagnose the install — Python, extras, grammars, schema version, stale index. |
roam_catalog | Machine-readable list of every registered MCP tool plus capability flags. |
roam_expand_toolset | Switch the active preset (core / review / refactor / debug / architecture / full). |
roam_session_metrics | Per-session counters for the current MCP connection. |
roam_evidence_doctor | Validate a ChangeEvidence packet passed in by the caller. |
roam_fetch_handle | Fetch all or part of a large MCP payload by handle (byte slice, section pick, jq projection). |
roam_pr_comment_render | Render 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:
| Tool | Why it's heavy | What 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
| Surface | Use 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.