Skip to main content
Glama

Roam Research MCP + CLI

Roam Research MCP + CLI

npm version Project Status: Active License: MIT GitHub

Introduction

I created this project to solve a personal problem: I wanted to manage my Roam Research graph directly from Claude Code (and other LLMs). As I built the Model Context Protocol (MCP) server to give AI agents access to my notes, I realized the underlying tools were powerful enough to stand on their own.

What started as an backend for AI agents evolved into a full-featured Standalone CLI. Now, you can use the same powerful API capabilities directly from your terminal—piping content into Roam, searching your graph, and managing tasks—without needing an LLM at all.

Whether you want to give Claude superpowers over your knowledge base or just want a robust CLI for your own scripts, this project has you covered.

Before and after: copy-pasting notes into Roam by hand, versus Claude and your terminal reading and writing the graph directly — install with npm i -g roam-research-mcp, then roam save "idea" or pipe with echo "Buy milk" | roam save --todo

Related MCP server: Roam Research MCP Server

How this differs from Roam's official MCP server

Roam Research ships its own MCP server and CLI (@roam-research/roam-mcp). It is a good tool, and this project is not trying to replace it. They talk to two different Roam APIs, which is the difference everything else follows from.

This project

Official @roam-research/roam-mcp

Talks to

Roam's backend REST API (graph token + graph name)

Roam Desktop's local HTTP API

Needs Roam running

No — works headless

Yes, the desktop app must be open (it deep-links to launch it)

Where it can run

Anywhere: laptop, server, container, CI

The machine running Roam Desktop

Shared daemon

Yes — roam server runs one HTTP daemon for every client

Per-client stdio

Multi-graph

ROAM_GRAPHS env var, with write_key protection for chosen graphs

~/.roam-tools.json, one token per graph

Web-only graphs

Works

Desktop only

Reach for the official server when you want Roam's own supported path, or you need things only the running app can do: controlling the Desktop UI (open a page, read the current selection, drive the sidebar), semantic/embeddings search, link suggestions, file upload, comments, or invoking tools that Roam extensions register.

Reach for this one when Roam isn't running or isn't installed — a server, a container, a cron job, a CI step. Or when you want the extras this project has grown: a full standalone CLI with stdin piping, a shared HTTP daemon with optional bearer auth, smart page diffing that preserves block UIDs (and therefore your block references), batch operations with UID placeholders for building nested structures in one call, and agent memory tools.

One deliberate omission: there is no page-delete tool here. Roam has no undo that can reverse a bulk API deletion. The official server does offer delete_page; this project takes the more conservative line.

They interoperate

The two servers share conventions on purpose, so running both costs you nothing:

  • [[roam/agent guidelines]] — both read the same page for your conventions. Write them once; both honour them. See Agent guidelines.

  • #.rm-hide / #.rm-private — both withhold tagged blocks from AI-facing content. Tag once, hidden from both. See Hiding content from the AI.

Standalone CLI: roam

The roam CLI lets you interact with your graph directly from the terminal. It supports standard input (stdin) piping for all content creation and retrieval commands, making it perfect for automation workflows.

Quick Examples

# Save a quick thought to your daily page
roam save "Idea: A CLI for Roam would be cool"

# Pipe content from a file to a new page
cat meeting_notes.md | roam save --title "Meeting: Project Alpha"

# Create a TODO item on today's daily page
echo "Buy milk" | roam save --todo

# Prepend to top of page (newest-first ordering)
roam save -p "Changelog" --order first "v2.18.0 release"

# Search your graph and pipe results to another tool
roam search "important" --json | jq .

# Search for pages by namespace prefix
roam search --namespace "Convention"    # Finds all Convention/* pages

# Fetch a page by title
roam get "Roam Research"

# Fetch daily pages using any date format (auto-normalized)
roam get today                          # Today's daily page
roam get 2026-03-21                     # ISO date → "March 21st, 2026"
roam get "03/21/2026"                   # US date → "March 21st, 2026"
roam get "March 21"                     # Named (assumes current year)

# Fetch a block with ancestors (parent chain to page root)
roam get abc123def -a              # Block + children + ancestors
roam get abc123def -a -d 0         # Ancestors only, no children

# Fetch page by UID or Roam URL
roam get page abc123def
roam get page "https://roamresearch.com/#/app/my-graph/page/abc123def"

# Sort and group results
roam get --tag Project --sort created --group-by tag

# Find references (backlinks) to a page
roam refs "Project Alpha"

# Update a block (e.g., toggle TODO status)
roam update ((block-uid)) --todo

# Multi-graph: read from a specific graph
roam get "Page Title" -g work

# Multi-graph: write to a protected graph
roam save "Note" -g work --write-key "$ROAM_SYSTEM_WRITE_KEY"

Available Commands: get, search, save, refs, update, batch, rename, status, server. Run roam <command> --help for details on any command.

Installation

npm install -g roam-research-mcp
# The 'roam' command is now available globally

MCP Server Tools

The MCP server exposes these tools to AI assistants (like Claude), enabling them to read, write, and organize your Roam graph intelligently.

Multi-Graph Support: All tools accept optional graph and write_key parameters. Use graph to target a specific graph from your ROAM_GRAPHS config, and write_key for write operations on protected graphs.

Tool Name

Description

roam_fetch_page_by_title

Fetch page content by title.

roam_fetch_page_full_view

Fetch a page's content plus all linked references with breadcrumb context and children.

roam_fetch_block

Fetch a block by UID with optional children (depth) and/or ancestors (up to page root).

roam_create_page

Create new pages, optionally with mixed text and table content.

roam_update_page_markdown

Update a page using smart diff (preserves block UIDs).

roam_get_subpages

List sub-pages under a namespace prefix (e.g. "Project/") with optional tag filter.

roam_search_by_text

Full-text search across the graph or within specific pages. Supports namespace prefix search for page titles.

roam_search_block_refs

Find blocks that reference a page, tag, or block UID.

roam_search_by_status

Find TODO or DONE items.

roam_search_for_tag

Find blocks containing specific tags (supports exclusion).

roam_search_by_date

Find blocks/pages by creation or modification date.

roam_find_pages_modified_today

List pages modified since midnight.

roam_add_todo

Add TODO items to today's daily page.

roam_create_table

Create properly formatted Roam tables.

roam_create_outline

Create hierarchical outlines.

roam_process_batch_actions

Execute multiple low-level actions (create, move, update, delete) in one batch.

roam_move_block

Move a block to a new parent or position.

roam_remember / roam_recall

specialized tools for AI memory management within Roam.

roam_datomic_query

Execute raw Datalog queries for advanced filtering.

roam_markdown_cheatsheet

Retrieve the Roam-flavored markdown reference.

roam_get_guidelines

Retrieve this graph's user-defined agent conventions.

Structured results from write tools (v3.0.0+)

The ten write tools declare an outputSchema and return structuredContent — a validated object — alongside the usual text. A client can read page_uid, uid_map or success directly instead of hunting for JSON inside a string, which makes chaining calls more reliable:

// roam_process_batch_actions
{ "success": true, "uid_map": { "parent1": "Xk7mN2pQ9" },
  "validation_passed": true, "actions_attempted": 4 }

Three things worth knowing:

  • Nothing was taken away. The text channel is unchanged, so a client that ignores structuredContent behaves exactly as before.

  • Read tools deliberately have neither. They already serialise their whole result into the text channel, so a schema would just double the payload.

  • These fields are additive-only. Some clients validate live responses against a cached tool list, so a field will be added or deprecated — never renamed or removed outside a major version.

Upgrading from 2.x: three write-result fields were renamed — uidpage_uid (roam_create_page), created_uidscreated_blocks (roam_create_outline, roam_import_markdown) and preservedUidspreserved_uids (roam_update_page_markdown). This only affects code that reads those names; if you use the server through an AI assistant, nothing changes. See the changelog for why.


Agent guidelines (per-graph)

roam_get_guidelines reads a page inside the graph[[roam/agent guidelines]] by default — holding your own conventions: how you tag, how you namespace pages, what an agent should never do. Roam's official MCP server reads the same page title, so one page serves both.

This is distinct from CUSTOM_INSTRUCTIONS_PATH, and the two compose:

CUSTOM_INSTRUCTIONS_PATH

[[roam/agent guidelines]]

Lives in

a file on disk

a page in the graph

Scope

server-wide, all graphs

per-graph

To change it

edit the file, restart the server

edit the page

Answers

how to write Roam markdown

how this user wants this graph handled

Just create the page. With no configuration at all, roam_get_guidelines reads [[roam/agent guidelines]] — the same title Roam's own server reads, so writing it once makes both honour it. Creating a page with that exact namespaced title is the opt-in; nothing is read from the graph unless an agent explicitly calls the tool.

If the page doesn't exist, the tool returns exists: false rather than failing, so it is always safe to call.

It also returns the rules that aren't yours to set

Alongside your conventions, every roam_get_guidelines response carries a roamSyntax field: the short list of things that destroy content — roam_update_page_markdown deleting every block your markdown omits, truncated structure previews written back as if they were content, block references retyped as plain text — plus a caution that reads silently exclude #.rm-hide subtrees, and the handful of places Roam's markdown inverts standard markdown.

Two reasons it rides here rather than in the cheatsheet. It reaches every client, including one that never calls roam_markdown_cheatsheet; and it is returned even when a graph has no guidelines page, which is exactly the case where an agent has least context. The layering is deliberate: your conventions win on style, roamSyntax wins on data safety. No convention can make a truncated preview complete.

The full syntax reference — components, queries, embeds, tool selection — stays in roam_markdown_cheatsheet. roamSyntax is ~800 tokens and deliberately capped.

Each graph can point at a different page, or turn it off:

ROAM_GRAPHS='{
  "personal": {"token": "...", "graph": "..."},
  "work":     {"token": "...", "graph": "...", "guidelinesPage": "work/agent rules"},
  "private":  {"token": "...", "graph": "...", "guidelinesPage": false}
}'
ROAM_GUIDELINES_PAGE='team/agent guidelines'   # change the default for every graph

Resolution order is per-graph guidelinesPageROAM_GUIDELINES_PAGEroam/agent guidelines. Above: personal uses the env override, work uses its own page, and private has guidelines off entirely. Only an explicit false disables it — an unset value never does.

Results are cached for 30 seconds — an edit to the page takes effect without a restart. A starter template lives at .roam/agent-guidelines.template.md.

Note that guidelines are read through the normal page path, so blocks tagged #.rm-hide / #.rm-private are withheld from them too — see below.


Hiding content from the AI

Blocks tagged #.rm-hide or #.rm-private — and everything nested under them — are omitted from the content these tools return. Both the hashtag (#.rm-hide, #[[.rm-hide]]) and link ([[.rm-hide]]) forms work. .rm-private is Roam's existing "hidden from other users" tag; .rm-hide hides from the AI specifically.

This follows the same convention as Roam's official MCP server, so a block tagged for one is hidden from the other.

Applied to: roam_fetch_page_by_title, roam_fetch_block, roam_fetch_page_full_view, roam_get_subpages, roam_search_by_text, roam_search_for_tag, roam_search_by_status, roam_search_block_refs, roam_search_hierarchy, roam_search_by_date.

Hidden blocks are also excluded from the page-rewrite diff, which is what stops them being deleted for being absent from markdown the agent could not have written. roam_update_page_markdown (and roam save --update) replaces a page with what you give it, deleting whatever your markdown omits — so its baseline is pruned by this same filter, on the rule that the baseline a diff deletes from must be the same page the caller was allowed to read. It reports preserved_hidden when it protected anything. Content is preserved; exact ordering relative to visible siblings may shift. This was a real data-loss bug before the fix — see the changelog.

This is a convenience filter, not a security guarantee. roam_datomic_query reads the database directly and deliberately does not apply it, so a capable agent can still surface hidden blocks through raw Datalog. Treat these tags as "keep it out of the AI's way," not "keep it secret."

Tag matching is case-insensitive, and only exact tags match — #.rm-hidden and #.rm-highlight are left alone. The set of hidden UIDs is cached for 30 seconds, so a block tagged just now may remain visible for up to that long.


Configuration

Environment Variables

Single Graph Mode

For a single Roam graph, set these in your environment or a .env file:

ROAM_API_TOKEN=your-api-token
ROAM_GRAPH_NAME=your-graph-name

Multi-Graph Mode (v2.0+)

Connect to multiple Roam graphs from a single server instance:

ROAM_GRAPHS='{
  "personal": {"token": "token-1", "graph": "personal-db", "memoriesTag": "#[[Personal Memories]]"},
  "work": {"token": "token-2", "graph": "work-db", "protected": true, "memoriesTag": "#[[Work Memories]]"},
  "research": {"token": "token-3", "graph": "research-db"}
}'
ROAM_DEFAULT_GRAPH=personal
ROAM_SYSTEM_WRITE_KEY=your-secret-key

Graph Configuration Options:

Property

Required

Description

token

Yes

Roam API token for this graph

graph

Yes

Graph name/database identifier

protected

No

If true, writes require ROAM_SYSTEM_WRITE_KEY confirmation — except on the default graph, see below

memoriesTag

No

Tag for roam_remember/roam_recall (overrides global default)

Two kinds of access control (and how they differ)

The server has two independent locks. They're easy to mix up because both are "keys" — here's the plain version (both are optional and off by default):

Bearer tokenHTTP_AUTH_TOKEN

Write keyROAM_SYSTEM_WRITE_KEY

In a phrase

The key to the front door

The latch on a safe inside

Controls

Who can reach the server at all

Whether a write to a protected graph is allowed

Covers

Everything — reads and writes, all graphs

Only writes, and only to graphs marked protected

Protects reading?

Yes

No

When you need it

Only if the server is reachable beyond your own machine (e.g. -H 0.0.0.0)

Whenever you want a guard against accidental edits to important graphs

How it's sent

HTTP header: Authorization: Bearer <token>

A write_key argument on write tools / CLI commands

Think of a house: the bearer token locks the front door (keeps strangers out entirely), and the write key locks a safe inside (even someone already in the house needs it to change what's in the safe). On your own machine bound to 127.0.0.1, the front door faces a wall — you don't need the bearer token there. The write key is still handy locally as an "are you sure?" guard, because Roam has no undo.

So: to mark a graph as needing the write key, set protected: true on it and configure ROAM_SYSTEM_WRITE_KEY; callers then pass a matching write_key for any write to that graph.

⚠️ protected does nothing on your default graph. Writes to whichever graph ROAM_DEFAULT_GRAPH names are always allowed, before protected is ever consulted — the flag guards the graphs you have to ask for by name, on the reasoning that reaching for a non-default graph is the deliberate act worth confirming. If you want a graph write-guarded, it must not be your default.

Optional:

  • ROAM_MEMORIES_TAG: Default tag for roam_remember/roam_recall (fallback when per-graph memoriesTag not set).

  • HTTP_STREAM_PORT: Port for the HTTP Stream transport (defaults to 8088). --server mode only — stdio mode opens no socket, so this is ignored there.

  • HTTP_STREAM_HOST: Host to bind the HTTP transport to (defaults to 127.0.0.1, loopback-only). --server mode only. Set to 0.0.0.0 to expose on the LAN, and set HTTP_AUTH_TOKEN when you do.

  • HTTP_AUTH_TOKEN: Optional bearer token that locks the whole HTTP endpoint. Unset = open (fine for loopback). When set, every MCP request must send Authorization: Bearer <token> (GET /health stays open). Use it whenever you bind beyond 127.0.0.1. Different from ROAM_SYSTEM_WRITE_KEY — see Two kinds of access control.

Running the Server

1. Default Mode (stdio) Best for local integration (e.g., Claude Desktop, IDE extensions). The MCP client launches the process per session and talks to it over stdin/stdout. No port is opened — nothing about MCP over stdio needs one.

Before 3.1.0 this mode also opened an HTTP listener, and bound it to every interface. If you were using that endpoint, run a --server daemon instead; see below.

npx roam-research-mcp

2. Shared Server Mode (--server) Best for a single long-lived, HTTP-only daemon that multiple MCP clients share — instead of each session spawning its own subprocess. This saves memory and gives clients a stable URL.

HTTP_STREAM_PORT=8088 npx roam-research-mcp --server

Or manage it through the roam CLI, which adds start/stop/status/logs:

roam server start            # start the shared daemon in the background
roam server start -H 0.0.0.0 # expose on the LAN (no transport auth!)
roam server status           # is it up? version, graphs, active sessions
roam server logs -f          # follow the log
roam server stop             # stop a CLI-started daemon

roam server status works no matter how the daemon was launched (it probes /health), so it also reports a daemon started by a LaunchAgent/systemd unit. State (pidfile + log) lives in ~/.roam/ (override with ROAM_HOME).

The two modes are mutually exclusive, and each opens exactly one transport: stdio mode speaks stdio and binds nothing, --server speaks HTTP and reads no stdin. In --server mode the server:

  • runs HTTP-only (no stdio transport),

  • binds the exact HTTP_STREAM_PORT on HTTP_STREAM_HOST and exits non-zero if the port is taken (no silent drift — a shared daemon must keep a stable URL),

  • exposes GET /health{"status":"ok", ...} for liveness checks.

Point MCP clients at it with an HTTP transport config:

{
  "mcpServers": {
    "roam-research-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:8088/mcp"
    }
  }
}

Env vars (tokens, graphs) live with the server process, not the client config.

Securing an exposed server (two layers): If you bind beyond loopback (-H 0.0.0.0), add the perimeter lock:

HTTP_AUTH_TOKEN=$(openssl rand -hex 32) roam server start -H 0.0.0.0

Clients then send the token as a header:

{
  "mcpServers": {
    "roam-research-mcp": {
      "type": "http",
      "url": "http://<host>:8088/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

Keep both — they do different jobs (see Two kinds of access control above): the bearer token controls who can connect, the write key only guards writes to protected graphs.

⚠️ The write key is not a substitute for the bearer token. On an exposed server without HTTP_AUTH_TOKEN, anyone on the network can still read every graph (and write non-protected ones). For anything beyond loopback, set HTTP_AUTH_TOKEN.

Keeping it running (macOS LaunchAgent): Create ~/Library/LaunchAgents/com.example.roam-mcp.plist with RunAtLoad + KeepAlive, your env vars under EnvironmentVariables, and --server as the last ProgramArguments entry. Keep StandardOutPath/StandardErrorPath on a local path (e.g. ~/Library/Logs/), then:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.roam-mcp.plist
curl -s http://127.0.0.1:8088/health   # verify

3. Docker

docker run -p 8088:8088 --env-file .env roam-research-mcp --server

Configuring in LLMs

Claude Desktop / Cline:

Add to your MCP settings file (e.g., ~/Library/Application Support/Claude/claude_desktop_config.json):

Pinning the version. npx -y roam-research-mcp fetches the latest release every time your client starts the server, so a new major version arrives without warning. Pin the major to decide for yourself when to move:

args

You get

["-y", "roam-research-mcp"]

Latest, always — including the next major

["-y", "roam-research-mcp@3"]

3.x only; majors need an edit here

["-y", "roam-research-mcp@3.0.0"]

Exactly this build

Pinning the major is the sensible default: you still get fixes and new tools, but a breaking change becomes something you opt into. The examples below stay unpinned to match what most people paste in first.

Single Graph:

{
  "mcpServers": {
    "roam-research": {
      "command": "npx",
      "args": ["-y", "roam-research-mcp"],
      "env": {
        "ROAM_API_TOKEN": "your-token",
        "ROAM_GRAPH_NAME": "your-graph"
      }
    }
  }
}

Multi-Graph:

{
  "mcpServers": {
    "roam-research": {
      "command": "npx",
      "args": ["-y", "roam-research-mcp"],
      "env": {
        "ROAM_GRAPHS": "{\"personal\":{\"token\":\"token-1\",\"graph\":\"personal-db\",\"memoriesTag\":\"#[[Memories]]\"},\"work\":{\"token\":\"token-2\",\"graph\":\"work-db\",\"protected\":true}}",
        "ROAM_DEFAULT_GRAPH": "personal",
        "ROAM_SYSTEM_WRITE_KEY": "your-secret-key"
      }
    }
  }
}

Query Block Parser (v2.11.0+)

A utility for parsing and executing Roam query blocks programmatically. Converts {{[[query]]: ...}} syntax into Datalog queries.

Supported Clauses

Clause

Syntax

Description

Page ref

[[page]]

Blocks referencing a page

Block ref

((uid))

Blocks referencing a block

and

{and: [[a]] [[b]]}

All conditions must match

or

{or: [[a]] [[b]]}

Any condition matches

not

{not: [[tag]]}

Exclude matches

between

{between: [[date1]] [[date2]]}

Date range filter

search

{search: text}

Full-text search

daily notes

{daily notes: }

Daily notes pages only

by

{by: [[User]]}

Created or edited by user

created by

{created by: [[User]]}

Created by user

edited by

{edited by: User}

Edited by user

Relative Dates

The between clause supports relative dates: today, yesterday, last week, last month, this year, 7 days ago, 2 months ago, etc.

Usage

import { QueryExecutor } from 'roam-research-mcp/query';

const executor = new QueryExecutor(graph);

// Execute a query
const results = await executor.execute(
  '{{[[query]]: "My Query" {and: [[Project]] {between: [[last month]] [[today]]}}}}'
);

// Parse without executing (for debugging)
const { name, query } = QueryParser.parseWithName(queryBlock);

Utility Functions

import { isQueryBlock, extractQueryBlocks } from 'roam-research-mcp/query';

// Detect if text is a query block
isQueryBlock('{{[[query]]: [[tag]]}}'); // true

// Extract all query blocks from a string
extractQueryBlocks(pageContent); // ['{{[[query]]: ...}}', ...]

Support

If this project helps you manage your knowledge base or build cool agents, consider buying me a coffee! It helps keep the updates coming.

https://paypal.me/2b3/5


License

MIT License - Created by Ian Shen.

Available Tools

25 tools
roam_add_todoA

Add a list of todo items as individual blocks to today's daily page in Roam. Each item becomes its own actionable block with todo status. NOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use alias syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words).

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
todosYesList of todo items to add
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

Output Schema

ParametersJSON Schema
NameRequiredDescription
successYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnly=false, and the description adds that each item becomes an 'actionable block with todo status', and provides markdown linking rules. This is useful behavioral context beyond what annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main purpose is stated in a single, direct sentence. The markdown note and IMPORTANT prerequisite are structured with labels and are relevant to correct use. It is slightly long, but each part earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so return values don't need to be explained. The description covers the action, the effect on blocks, markdown syntax details, and the required prerequisite call to roam_get_guidelines, making it complete for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes all three parameters with 100% coverage, so the baseline is 3. The description adds valuable markdown syntax guidance for the 'todos' parameter text, such as [[link]] and #[[multiple words]], which increases the score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Add') and resource ('today's daily page'), and clearly states that each item becomes an 'individual block' with todo status. This distinguishes it from sibling tools like roam_create_outline or roam_import_markdown.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states when to use: adding todos to today's daily page. It also gives an explicit prerequisite: call roam_get_guidelines and load the Roam Markdown Cheatsheet before use. It doesn't explicitly mention alternatives or when not to use, so a 4 is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_create_outlineA

Add a structured outline to an existing page or block (by title text or uid), with customizable nesting levels. To create a new page with an outline, use the roam_create_page tool instead. The outline parameter defines new blocks to be created. To nest content under an existing block, provide its UID or exact text in block_text_uid, and ensure the outline array contains only the child blocks with levels relative to that parent. Including the parent block's text in the outline array will create a duplicate block. Best for:

  • Adding supplementary structured content to existing pages

  • Creating temporary or working outlines (meeting notes, brainstorms)

  • Organizing thoughts or research under a specific topic

  • Breaking down subtopics or components of a larger concept Best for simpler, contiguous hierarchical content. For complex nesting (e.g., tables) or granular control over block placement, consider roam_process_batch_actions instead. API Usage Note: This tool performs verification queries after creation. For large outlines (10+ items) or when rate limits are a concern, consider using roam_process_batch_actions instead to minimize API calls.

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
orderNoInsertion position for the first level-1 block relative to existing page/block children. Accepts "first", "last", or a non-negative integer (0-indexed). Default: "last".
outlineYesArray of outline items with block text and explicit nesting level. Must be a valid hierarchy: the first item must be level 1, and subsequent levels cannot increase by more than 1 at a time (e.g., a level 3 cannot follow a level 1).
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
block_text_uidNoThe text content or UID of the block to nest the outline under (UID is preferred for accuracy). If blank, content is nested directly under the page (or the default daily page if page_title_uid is also blank).
page_title_uidNoTitle or UID of the page (UID is preferred for accuracy). Leave blank to use the default daily page.

Output Schema

ParametersJSON Schema
NameRequiredDescription
successYes
page_uidYes
parent_uidYesBlock the outline was nested under
created_blocksYesThe created block tree. Objects, not UID strings.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond the annotations (which are all false) by disclosing that the tool 'performs verification queries after creation' and warns about the risk of duplicate blocks if the parent block's text is included in the outline array. It also clarifies that the outline parameter defines new blocks, which is key behavioral context. However, it does not mention idempotency failure behavior or partial-failure details, so it is not fully exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than strictly necessary but well-structured with a clear opening sentence, bulleted 'Best for' list, and a separate API Usage Note. Each section adds value without redundancy, and the most essential information is front-loaded. It earns a 4 rather than 5 due to its length, though it remains focused.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 parameters, nested outline structure), the description is remarkably complete. It covers purpose, usage alternatives, API rate-limit implications, common use cases, and even a prerequisite instruction (call roam_get_guidelines). The existence of an output schema further reduces the need to describe return values, so there are no significant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides 100% coverage of parameter descriptions, so the baseline is 3. The description adds meaningful semantic nuances beyond the schema, particularly for the `outline` parameter: it explains that levels are relative to the parent block, and warns against including the parent block's text. This extra guidance helps prevent common usage errors.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Add a structured outline to an existing page or block (by title text or uid), with customizable nesting levels.' It distinguishes itself from the sibling tool `roam_create_page` by explicitly noting that tool should be used for creating new pages with outlines. The verb-resource pairing is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool vs alternatives: 'To create a new page with an outline, use the `roam_create_page` tool instead' and 'For complex nesting (e.g., tables) or granular control over block placement, consider `roam_process_batch_actions` instead.' It also includes a 'Best for' list and a clear exclusion criterion, making the decision process straightforward.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_create_pageA

Create a new standalone page in Roam with optional content, including structured outlines and tables, using explicit nesting levels and headings (H1-H3). This is the preferred method for creating a new page with an outline in a single step. Best for:

  • Creating foundational concept pages that other pages will link to/from

  • Establishing new topic areas that need their own namespace

  • Setting up reference materials or documentation

  • Making permanent collections of information

  • Creating pages with mixed text and table content in one call. Efficiency Tip: This tool batches page and content creation efficiently. For adding content to existing pages, use roam_process_batch_actions instead.

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
titleYesTitle of the new page
contentNoInitial content for the page as an array of content items. Each item can be a text block or a table. Text blocks use {text, level, heading?}. Tables use {type: "table", headers, rows}. Items are processed in order.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

Output Schema

ParametersJSON Schema
NameRequiredDescription
successYes
page_uidYesUID of the created page

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate a write operation (readOnlyHint=false) and no idempotency/destructive hints. The description adds context beyond annotations by explaining the tool 'batches page and content creation efficiently' and requiring the user to consult guidelines beforehand. However, it does not disclose edge-case behaviors such as what happens if the page already exists, which would be useful for a creation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear opening sentence, a 'Best for' list, an efficiency tip, and an important prerequisite note. It is slightly longer than necessary (the best-for list has some overlap), but every section earns its place and it is front-loaded with the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (nested content arrays, table support, headings) and the detailed input schema, the description provides sufficient context: it explains the structure of content, highlights the ability to mix text and tables, and gives usage boundaries. It could mention conflict behavior for existing pages, but overall it is quite complete for a creation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% parameter description coverage, so the schema carries the burden. The description restates general capabilities (outlines, tables, headings) but does not add specific parameter-level semantics beyond what the schema already explains. Thus the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Create a new standalone page in Roam with optional content, including structured outlines and tables, using explicit nesting levels and headings (H1-H3).' It also distinguishes itself from siblings by noting it is 'the preferred method for creating a new page with an outline in a single step' and contrasts with roam_process_batch_actions for adding content to existing pages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance through a 'Best for:' list covering foundational pages, new namespaces, reference materials, and permanent collections. It also gives an exclusion: 'For adding content to existing pages, use roam_process_batch_actions instead,' and includes a prerequisite instruction to call roam_get_guidelines and load the Markdown Cheatsheet before using.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_create_tableA

Create a table in Roam with specified headers and rows. This tool abstracts the complex nested structure that Roam tables require, making it much easier to create properly formatted tables.

Why use this tool:

  • Roam tables require precise nested block structures that are error-prone to create manually

  • Automatically handles the {{[[table]]}} container and nested column structure

  • Validates row/column consistency before execution

  • Converts empty cells to spaces (required by Roam)

Example: A table with headers ["", "Column A", "Column B"] and rows [{label: "Row 1", cells: ["A1", "B1"]}] creates a 2x3 table.

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
rowsYesData rows for the table. Each row has a label (first column) and cells (remaining columns).
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
orderNoOptional: Position under the parent. Can be a number (0-based) or "first"/"last". Defaults to "last".last
headersYesColumn headers for the table. The first header is typically empty (for the row label column). Example: ["", "Option A", "Option B"]
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
parent_uidYesThe UID of the parent block or page where the table should be created.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
successYes
uid_mapNoPlaceholder name → generated UID. Present only on success.
table_uidNo
actions_attemptedNo
validation_passedNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate a write operation (readOnlyHint: false) but provide limited safety info. The description adds valuable context: it automatically handles the {{[[table]]}} container, validates row/column consistency, and converts empty cells to spaces. It also mentions the session prerequisite, giving the agent important operational details beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the core action. The 'Why use this tool' bullets are concise and purposeful, the example is helpful, and the IMPORTANT note is relevant. No sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 params), the description provides purpose, rationale, an example, and a prerequisite. The output schema exists, so return-value details are not necessary. It lacks explicit edge-case handling but is complete enough for an agent to use effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters. The description's example adds a concrete illustration of how headers and rows map to a table, but it does not add significant new semantics beyond what the schema provides. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Create a table in Roam with specified headers and rows,' which is a specific verb+resource statement that clearly distinguishes this tool from siblings like roam_create_outline or roam_create_page. It also explains the tool abstracts Roam's complex nested table structure, reinforcing its unique purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Why use this tool' section explicitly states when this tool is beneficial (avoiding error-prone manual creation, handling table containers, validating consistency). It also provides a clear prerequisite: call roam_get_guidelines and load the Markdown Cheatsheet before use. However, it does not explicitly name alternatives or state when not to use it, though the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_datomic_queryA
Read-onlyIdempotent

Execute a custom Datomic query on the Roam graph for advanced data retrieval beyond the available search tools. This provides direct access to Roam's query engine. Note: Roam graph is case-sensitive.

Optimal Use Cases for roam_datomic_query:

  • Advanced Filtering (including Regex): Use for scenarios requiring complex filtering, including regex matching on results post-query, which Datalog does not natively support for all data types. It can fetch broader results for client-side post-processing.

  • Highly Complex Boolean Logic: Ideal for intricate combinations of "AND", "OR", and "NOT" conditions across multiple terms or attributes.

  • Arbitrary Sorting Criteria: The go-to for highly customized sorting needs beyond default options.

  • Proximity Search: For advanced search capabilities involving proximity, which are difficult to implement efficiently with simpler tools.

List of some of Roam's data model Namespaces and Attributes: ancestor (descendants), attrs (lookup), block (children, heading, open, order, page, parents, props, refs, string, text-align, uid), children (view-type), create (email, time), descendant (ancestors), edit (email, seen-by, time), entity (attrs), log (id), node (title), page (uid, title), refs (text). Predicates (clojure.string/includes?, clojure.string/starts-with?, clojure.string/ends-with?, <, >, <=, >=, =, not=, !=). Aggregates (distinct, count, sum, max, min, avg, limit). Tips: Use :block/parents for all ancestor levels, :block/children for direct descendants only; combine clojure.string for complex matching, use distinct to deduplicate, leverage Pull patterns for hierarchies, handle case-sensitivity carefully, and chain ancestry rules for multi-level queries.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
queryYesThe Datomic query to execute (in Datalog syntax). Example: `[:find ?block-string :where [?block :block/string ?block-string] (or [(clojure.string/includes? ?block-string "hypnosis")] [(clojure.string/includes? ?block-string "trance")] [(clojure.string/includes? ?block-string "suggestion")]) :limit 25]`
inputsNoOptional array of input parameters for the query
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
regexFlagsNoOptional: Flags for the regex filter (e.g., "i" for case-insensitive, "g" for global).
regexFilterNoOptional: A regex pattern to filter the results client-side after the Datomic query. Applied to JSON.stringify(result) or specific fields if regexTargetField is provided.
regexTargetFieldNoOptional: An array of field paths (e.g., ["block_string", "page_title"]) within each Datomic result object to apply the regex filter to. If not provided, the regex is applied to the stringified full result.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral context beyond annotations: it notes case-sensitivity, explains that regex filtering is applied client-side after the query, and warns that graph conventions affect results. Annotations already declare readOnly, idempotent, and non-destructive, and the description does not contradict them; it enriches the agent's understanding of side effects and result interpretation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy but well-structured with sections (Optimal Use Cases, data model, predicates, tips) and all content is relevant to using the tool effectively. It front-loads the purpose and uses bold headers for scannability, though a slight trim could make it more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex Datomic query tool, the description covers most essential context: syntax, use cases, data model, predicates, and a required guideline call. However, it does not describe the return format beyond mentioning client-side filtering, and could benefit from noting potential errors or performance implications, so it isn't fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds significant value by providing an example Datalog query, listing predicates and aggregates, and explaining the data model namespaces. This goes beyond the schema's parameter descriptions and helps the agent construct correct queries, especially for the 'query' parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool executes custom Datomic queries on the Roam graph for advanced data retrieval, explicitly distinguishing it from search tools. It further lists specific advanced use cases (regex filtering, complex boolean logic, arbitrary sorting, proximity search), making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description has an 'Optimal Use Cases' section that clearly specifies when to use this tool (advanced filtering, complex boolean logic, etc.), and the opening sentence implies it should be used beyond the available search tools. It also mandates calling roam_get_guidelines before use, but doesn't explicitly name alternative tools for contrast or state when not to use it, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_fetch_blockA
Read-onlyIdempotent

Fetch a block by its UID with optional children (down to a specified depth) and/or ancestors (up to page root). Returns the block's UID, text, order, children array, and optionally an ancestors array with the chain to the page root.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
depthNoOptional: The number of levels deep to fetch children. Defaults to 4. Set to 0 to skip children.
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
block_uidYesThe UID of the block to fetch.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
include_ancestorsNoOptional: Include the ancestor chain from the block up to the page root. Each ancestor includes uid, string/title, and depth. Defaults to false.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only and idempotent, and the description aligns with that by stating it 'fetches' and 'returns' data. It adds valuable behavioral context beyond the annotations: the graph's conventions can change read semantics, and the response includes a specific ancestors array shape when requested.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs with no filler. The first sentence states the core function and return values, and the second conveys an essential prerequisite in an 'IMPORTANT' callout. Every sentence earns its place and the structure is immediately scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by naming the exact return fields. The mandatory prerequisite for roam_get_guidelines is highlighted, and all parameters are covered by the schema. For a read-only fetch tool with clear sibling context, this is fully adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameter descriptions already document depth, graph, block_uid, write_key, and include_ancestors. The description adds minimal extra semantic value beyond restating those concepts in prose (e.g., 'children down to a specified depth' maps to depth), but it does not introduce information absent from the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb and resource: 'Fetch a block by its UID' with optional children and ancestors, which clearly distinguishes it from page-level fetch siblings like roam_fetch_page_by_title and roam_fetch_page_full_view. It also enumerates the return fields, reinforcing what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs the agent to call roam_get_guidelines once per session before using the tool, including for reads, and explains that conventions affect how results are read. It does not explicitly name alternative tools or provide exclusion criteria, but the prerequisite and context are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_fetch_page_by_titleA
Read-onlyIdempotent

Fetch page by title. Returns content in the specified format.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
titleYesTitle of the page. For date pages, use ordinal date formats such as January 2nd, 2025
formatNoFormat output as markdown, JSON, or structure. 'markdown' returns readable string; 'raw' returns full JSON with nested blocks; 'structure' returns a flattened list (uid, order, text, depth, parent_uid) for locating blocks to update. In 'structure', `text` is a PREVIEW cut at 80 characters — an entry marked `truncated: true` is a fragment, and writing it back would replace the block with its own opening. Use it to find the uid, then fetch that block with roam_fetch_block before editing its text.raw
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds behavioral context by warning that graph conventions affect how results are read, which is not captured by annotations or schema. This is useful and complements the structured metadata.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences achieve the core purpose and add a critical usage warning. There is no filler or redundant explanation. The important guideline is highlighted with 'IMPORTANT' and placed prominently, making it effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only fetch tool with rich schema descriptions and annotations, the description is sufficiently complete. It covers the core function, return format note, and the prerequisite guideline call. There is no output schema, but the format parameter description in the schema explains expected outputs. Minor gaps like behavior on missing pages are acceptable for this tool type.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 100% coverage with detailed descriptions for all parameters, including the format enum and its behavior. The description adds no additional parameter-specific meaning beyond what the schema provides, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Fetch' and the resource 'page by title', making the tool's purpose unambiguous. It is specific enough to distinguish from sibling tools like roam_fetch_page_full_view or roam_fetch_block, which operate on different inputs or views.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs the agent to call roam_get_guidelines before every session, even for reads, adding important prerequisite guidance. It does not mention specific alternative tools or exclusion criteria, but the context of use is clear from the verb and resource.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_fetch_page_full_viewA
Read-onlyIdempotent

Fetch a complete page view that mirrors what Roam Research shows in its UI: the page's own content, plus all linked references (backlinks) grouped by source page, each with their ancestor breadcrumb context and children expanded to the specified depth. Use this when you need the full picture of a page — both what is written on it and everything else in the graph that references it.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
titleYesTitle of the page to fetch. For date pages use ordinal format e.g. "January 2nd, 2025".
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
children_depthNoHow many levels deep to expand children of each referring block. Defaults to 4.
max_referencesNoMaximum number of linked references to return. Prevents timeouts on heavily-referenced pages (e.g. TODO, common tags). Defaults to 200.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint. The description adds behavioral context: mirrors Roam UI, groups backlinks by source page, includes breadcrumbs, and mentions max_references to prevent timeouts. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences of purpose and usage, plus one important prerequisite note. Every sentence earns its place, front-loaded with the core purpose. No fluff or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex read tool with no output schema, the description well explains the response composition: page content, grouped backlinks, breadcrumbs, and child expansion depth. It also includes a session-level prerequisite. Minor gap: no explicit mention of pagination beyond max_references, but that is partially covered in schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters are already fully documented. The description's references to 'children expanded to the specified depth' and 'max_references' merely restate what the schema provides without adding new semantic meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with 'Fetch a complete page view' which clearly identifies the verb, resource, and scope. It distinguishes itself from sibling tools by specifying it includes linked references grouped by source page with breadcrumb context, unlike a simple fetch_page_by_title.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit use case: 'Use this when you need the full picture of a page'. Also instructs to call roam_get_guidelines before use, which is a prerequisite. Does not explicitly name alternatives to exclude, but gives clear context for when to choose this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_find_pages_modified_todayA
Read-onlyIdempotent

Find pages that have been modified today (since midnight), with pagination and sorting options.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
limitNoThe maximum number of pages to retrieve (default: 50). Use -1 for no limit, but be aware that very large result sets can impact performance.
offsetNoThe number of pages to skip before returning matches. Useful for pagination. Defaults to 0.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
sort_orderNoSort order for pages based on modification date. "desc" for most recent first, "asc" for oldest first.desc

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (read-only, idempotent), the description adds a behavioral caveat: conventions change how results are read, and it requires calling roam_get_guidelines. This enriches the agent's understanding without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two impactful sentences: the main action and an important prerequisite. The description is front-loaded with the core purpose and wastes no words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the read-only nature, schema coverage, and annotations, the description covers the core function, the required guideline call, and a behavioral caveat. It lacks explicit return format or timezone clarification for 'midnight', but these are minor gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters (limit, offset, sort_order, graph, write_key) are already fully described in the schema. The description only mentions pagination and sorting generically without adding new parameter-specific meaning, keeping the baseline at 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('Find') and the resource ('pages modified today'), with a precise time scope ('since midnight'). It is easily distinguished from sibling tools like roam_search_by_date or roam_fetch_page_by_title.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit context for when to use the tool (for pages modified today) and a critical prerequisite (call roam_get_guidelines once per session). However, it does not mention alternatives or exclusions, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_get_guidelinesA
Read-onlyIdempotent

Retrieve this graph's user-defined agent conventions, read from the [[roam/agent guidelines]] page inside the graph (configurable per graph). These are the user's own rules — how they tag, how they name and namespace pages, what to never do, how they want your voice attributed.

Also returns roamSyntax: the rules whose violation destroys content — whole-page rewrites that delete, truncated previews written back as content, retyped block references, and the syntax that differs from standard markdown. These are returned on every call, including when the graph has no guidelines page, and they hold regardless of what the conventions say.

Call this ONCE per graph per session, before other tools, INCLUDING for reads: conventions change how results should be interpreted and presented, not just how content is written. Returns today's daily note title as orientation.

Distinct from roam_markdown_cheatsheet, which is the complete syntax reference — components, queries, embeds, tool selection. Call that when you need to look something up; this one you need before writing at all. Returns exists:false rather than failing when no page has been created.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=false, idempotentHint=true, destructiveHint=false. The description adds valuable context beyond these: it returns `roamSyntax` on every call, returns `exists:false` instead of failing when no page exists, returns today's daily note title, and explains that conventions affect interpretation/presentation, not just writing. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than the absolute minimum but well-structured: purpose, special return value, usage instruction, sibling differentiation, and existence behavior are each in their own sentence/paragraph. Every sentence earns its place, though it could be tightened slightly without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even without an output schema, the description explains what is returned (user conventions, roamSyntax, daily note title, exists:false), why it must be called before other tools, and the behavior when no guidelines page exists. It fully covers the operational context a read tool with no output schema needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% coverage for both parameters (`graph` and `write_key`) with descriptions. The description adds no new parameter-specific meaning beyond noting the guidelines page is 'configurable per graph', which is already implied by the schema. Baseline 3 is appropriate since the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Retrieve this graph's user-defined agent conventions', and names the source page `[[roam/agent guidelines]]`. It also distinguishes itself from the sibling `roam_markdown_cheatsheet` by stating what each is for, eliminating ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs 'Call this ONCE per graph per session, before other tools, INCLUDING for reads' and contrasts with the alternative: 'Call that when you need to look something up; this one you need before writing at all.' This gives clear when-to-use and when-not-to-use guidance with a direct sibling reference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_get_subpagesA
Read-onlyIdempotent

Fetch all sub-pages (namespace children) of a given page prefix. Matches by page title prefix — pages titled "Prefix/Something" are sub-pages of "Prefix" and appear in the Hierarchy section of that page. This is namespace/title-prefix matching, distinct from roam_search_hierarchy which traverses block parent/child relationships. Optionally filter to only sub-pages containing a specific tag (e.g. filter active projects with filter_tag="active"), and optionally include each sub-page's full block content.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
prefixYesThe namespace prefix to search under, e.g. "Project", "Zettel", "Framework". The trailing "/" is added automatically if omitted.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
filter_tagNoOptional. Only return sub-pages that contain at least one block referencing this tag. Matches both #tag and [[tag]] usage. Example: "active" to find active projects.
include_contentNoIf true, include each sub-page's block content in the output. Defaults to false (list only).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already declaring read-only/idempotent, the description adds meaningful behavioral details: it explains that the trailing slash is added automatically, that filter_tag matches both #tag and [[tag]] usage, and that include_content controls whether full block content is returned. The IMPORTANT note about conventions affecting how results are read adds extra context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences plus a focused IMPORTANT note. It front-loads the core purpose, uses no filler, and each sentence adds a distinct piece of information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's behavior, prerequisites, and optional parameters. Since there is no output schema, it would be helpful to state the exact return shape, but the description implies a list of sub-pages and mentions content inclusion for include_content. Overall it's sufficiently complete for a read-only list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers all 5 parameters with detailed descriptions, so the baseline is 3. The description enhances the meaning of 'prefix' by explaining the namespace/title-prefix matching convention and the hierarchy section, which aids correct parameter use.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Fetch all sub-pages (namespace children) of a given page prefix,' which is a specific verb+resource. It further distinguishes itself from roam_search_hierarchy (block parent/child traversal) and clarifies the title-prefix matching rule.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names an alternative tool: 'distinct from roam_search_hierarchy which traverses block parent/child relationships.' It also mandates a prerequisite: 'call roam_get_guidelines for this graph once per session before using this tool,' including for reads.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_import_markdownA

Import nested markdown content into Roam under a specific block. Can locate the parent block by UID (preferred) or by exact string match within a specific page. If a parent_string is provided and the block does not exist, it will be created. Returns a nested structure of the created blocks. API Usage Note: This tool fetches the full nested structure after import for verification. For large imports or when rate limits are a concern, consider using roam_process_batch_actions with pre-structured actions instead.

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
orderNoOptional: Where to add the content under the parent ("first" or "last"). Defaults to "first".first
contentYesNested markdown content to import
page_uidNoOptional: UID of the page containing the parent block (preferred for accuracy).
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
page_titleNoOptional: Title of the page containing the parent block (used if page_uid is not provided).
parent_uidNoOptional: UID of the parent block to add content under (preferred for accuracy).
parent_stringNoOptional: Exact string content of an existing parent block to add content under (used if parent_uid is not provided; requires page_uid or page_title). If the block does not exist, it will be created.

Output Schema

ParametersJSON Schema
NameRequiredDescription
successYes
page_uidYes
parent_uidYes
created_blocksYesThe created block tree. Objects, not UID strings.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (write, non-destructive), the description discloses two important behaviors: it auto-creates a missing parent block when `parent_string` is used, and it fetches the full nested structure post-import for verification, adding rate-limit context. This is valuable extra transparency, though it does not detail all side effects (e.g., how existing content is affected).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded with the main purpose. It uses a clear structure with an API usage note and an important prerequisite. While slightly longer due to the usage warnings, every sentence serves a purpose and there is no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter tool with a full output schema, the description covers the core behavior, parameter lookup logic, rate-limit implications, and required preconditions. It does not explicitly cover error cases or edge conditions, but the schema and output schema fill many gaps, making it reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaning by explaining the preference order (parent_uid/page_uid over parent_string) and clarifying that `parent_string` will create a new block if it doesn't exist. This goes beyond the schema definitions and helps agents choose the right parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Import nested markdown content into Roam under a specific block' with a specific verb, resource, and location. It distinguishes itself from siblings by detailing how the parent block is located (UID or exact string match) and refers to the alternative tool `roam_process_batch_actions` for large imports.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit usage guidance: UID is preferred over string match, and it names an alternative for large imports or rate-limit concerns. It also instructs to call `roam_get_guidelines` and load the Markdown Cheatsheet before use, covering prerequisites and when-not-to-use scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_markdown_cheatsheetA
Read-onlyIdempotent

Provides the comprehensive Roam syntax reference. Covers: formatting, links & references (page refs, block refs, embeds including embed-children and embed-path), tags, dates, tasks, callouts, attributes, queries (native {{query}} with its clause rules and page-ref inheritance, plus :q Datalog tables with built-in rules), tables, kanban, mermaid diagrams (with theme support), advanced components (dropdowns, tooltips, templates, document mode, word-count), CSS tags (#.rm-E, #.rm-hide, etc.), anti-patterns, tool selection guide, and API efficiency tips.

IMPORTANT: Always load this cheatsheet before creating or updating Roam content. It prevents common syntax errors and guides tool selection.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety. The description adds behavioral context by noting it 'prevents common syntax errors' and 'guides tool selection,' which goes beyond annotations. It doesn't describe the output format, but for a read-only reference the annotations carry the main safety burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but front-loaded with the main purpose and then organized into a categorized list. Each sentence adds value, and the IMPORTANT warnings are clearly highlighted. It is appropriately detailed for a comprehensive reference tool, though slightly verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only reference tool with no output schema, the description is complete: it lists the full scope of content covered, provides usage prerequisites, and includes warnings about guidelines. It explains why to load it and mentions the companion function. No significant information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, as both parameters (graph, write_key) have descriptions in the schema. The tool description itself does not mention parameters, but because the schema fully documents them, the baseline is 3. No additional parameter semantics are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb+resource: 'Provides the comprehensive Roam syntax reference.' It enumerates a detailed list of covered topics (formatting, links, queries, diagrams, etc.), which distinguishes it from sibling tools like roam_create_table or roam_add_todo. The purpose is unmistakable and specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly instructs 'Always load this cheatsheet before creating or updating Roam content' and explains it prevents syntax errors and guides tool selection. It also names a prerequisite: 'call roam_get_guidelines for this graph once per session before using this tool.' This is clear when-to-use guidance with an alternative tool mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_move_blockA
DestructiveIdempotent

Move a block to a new location (different parent or position). This is a convenience wrapper around roam_process_batch_actions for single block moves.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
orderNoPosition under the new parent. Can be a number (0-based index) or "first"/"last". Defaults to "last".last
block_uidYesThe UID of the block to move
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
parent_uidYesThe UID of the new parent block or page

Output Schema

ParametersJSON Schema
NameRequiredDescription
orderYes
successYes
block_uidYes
new_parent_uidYes

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and destructiveHint=true, so the description does not need to restate these. It adds context about being a wrapper around batch actions and the importance of graph-specific guidelines. However, it does not disclose additional behavioral details such as whether the move is atomic, if child blocks are moved recursively, or the exact impact on references. With annotations covering the safety profile, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, each earning its place. The first sentence states the action, the second frames it as a wrapper alternative, and the third provides a critical workflow prerequisite. It is front-loaded and free of fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (5 parameters, 2 required, output schema present), the description covers the essential context: what the tool does, how it relates to sibling tools, and the required pre-use step. The output schema handles return values, and annotations handle safety traits, so the description is complete for an agent to select and invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage for all five parameters, so the description does not need to explain each parameter. It does add a high-level semantic cue ('different parent or position') that maps to parent_uid and order, but this is already explicit in the schema. The description adds marginal value over the schema, matching the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Move a block to a new location' which is a specific verb+resource action, and immediately clarifies the scope: 'different parent or position'. It also distinguishes itself from the sibling tool by explicitly calling itself a 'convenience wrapper around roam_process_batch_actions for single block moves', making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly indicates when to use this tool—for single block moves—by positioning it as a wrapper around the batch action tool, implying batch actions would be used for multiple moves. It also includes an explicit prerequisite: 'call roam_get_guidelines for this graph once per session', with a brief rationale. This is direct usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_process_batch_actionsA
Destructive

RATE LIMIT EFFICIENT: This is the most API-efficient tool for multiple block operations. Combine all create/update/delete operations into a single call whenever possible. For intensive page updates or revisions, prefer this tool over multiple sequential calls.

Executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Actions are executed in the provided order.

UID Placeholders for Nested Blocks: Use {{uid:name}} syntax for parent-child references within the same batch. The server generates proper random UIDs and returns a uid_map showing placeholder→UID mappings. Example: { uid: "{{uid:parent1}}", string: "Parent" } then { location: { "parent-uid": "{{uid:parent1}}" }, string: "Child" }. Response includes { success: true, uid_map: { "parent1": "Xk7mN2pQ9" } }.

For actions on existing blocks, a valid block UID is required. Note: Roam-flavored markdown, including block embedding with ((UID)) syntax, is supported within the string property for create-block and update-block actions. For actions on existing blocks or within a specific page context, it is often necessary to first obtain valid page or block UIDs. Tools like roam_fetch_page_by_title or other search tools can be used to retrieve these UIDs before executing batch actions. For simpler, sequential outlines, roam_create_outline is often more suitable.

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
actionsYesAn array of action objects to execute in order.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent only when success is false.
successYes
uid_mapNoPlaceholder name → generated UID. Present only on success.
actions_attemptedNo
validation_passedNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond the annotations by disclosing non-transactional execution, ordered actions, UID placeholder behavior with uid_map responses, and the requirement for valid block UIDs. It also notes that existing-block actions often need page/block UIDs first. The destructiveHint annotation is consistent with the write operations described; no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with bold section labels and examples. It contains some repetition (e.g., 'For actions on existing blocks' appears twice), but each sentence contributes either usage guidance, parameter enrichment, or prerequisite context. The front-loaded rate-limit note is practical.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and the presence of an output schema (indicated but not shown), the description covers the essentials: what the tool does, when to use it, prerequisites for UIDs, nested-block placeholder mechanics, response shape, and the guideline prerequisite. It could mention failure semantics more explicitly, but the non-transactional note covers the key risk.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema by explaining the {{uid:name}} placeholder syntax with a concrete example, describing the structure of the uid_map response, and noting that Roam-flavored markdown including block embeds is supported in the 'string' property.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb-resource pairing: 'Executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch.' It also brands itself as 'the most API-efficient tool for multiple block operations,' which distinguishes it from siblings like roam_create_outline and roam_move_block.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit usage guidance is provided: 'Combine all create/update/delete operations into a single call whenever possible' and 'For simpler, sequential outlines, roam_create_outline is often more suitable.' It also directs users to call roam_get_guidelines once per session and to use search tools like roam_fetch_page_by_title to obtain UIDs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_recallA
Read-onlyIdempotent

Retrieve all stored memories on page titled ROAM_MEMORIES_TAG, or tagged block content with the same name. Returns a combined, deduplicated list of memories. Optionally filter blocks with a specific tag and sort by creation date.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
sort_byNoSort order for memories based on creation datenewest
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
filter_tagNoInclude only memories with a specific filter tag. For single word tags use format "tag", for multi-word tags use format "tag word" (without brackets)

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the description only needs to add context. It adds that results are deduplicated and that 'conventions change how results are read, not just written,' which is a valuable behavioral caveat. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two paragraphs; the first is a single dense sentence covering core behavior, the second is a necessary warning. It is efficient with no redundant content, though the first sentence is long and complex.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the dual retrieval source, deduplication, optional filtering/sorting, and a per-session prerequisite. It also states the return type ('combined, deduplicated list'). For a simple read-only tool with good annotations, this is adequate, though it could clarify the exact format of the returned list.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with all four parameters described. The description mentions filter_tag and sort_by but does not add new semantic detail beyond the schema, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the primary function: 'Retrieve all stored memories on page titled ROAM_MEMORIES_TAG, or tagged block content with the same name.' It specifies the resource (memories), the source (page or tags), and the output (deduplicated list). This distinguishes it from sibling search tools by focusing on memory recall.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly mandates calling roam_get_guidelines before using this tool, which is a clear prerequisite. However, it does not explicitly contrast with alternative tools like roam_search_for_tag, though the memory-specific scope implies the intended use case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_rememberA

Add a memory or piece of information to remember, stored on the daily page with ROAM_MEMORIES_TAG tag and optional categories (unless include_memories_tag is false). NOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use alias syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words).

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
memoryYesThe memory detail or information to remember. Add tags in `categories`.
headingNoOptional heading text to nest the memory under (e.g., "Memories" or "## LLM Memories"). If the heading does not exist on the daily page, it will be created. Ignored if parent_uid is provided.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
categoriesNoOptional categories to tag the memory with (will be converted to Roam tags). Do not duplicate tags added in `memory` parameter.
parent_uidNoOptional UID of a specific block to nest the memory under. Takes precedence over heading parameter.
include_memories_tagNoWhether to append the ROAM_MEMORIES_TAG tag to the memory block.

Output Schema

ParametersJSON Schema
NameRequiredDescription
successYes
block_uidNoUID of the stored memory block
parent_uidNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false, providing no behavioral safety hints (e.g., readOnlyHint=false implies a write, but no further detail). The description compensates by disclosing that the tool writes to the daily page, applies a tag and optional categories, and includes a markdown syntax warning to avoid formatting errors. It does not mention permission requirements or rate limits, but for a write tool with no other annotation coverage, it adds substantial behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description opens with a clear one-sentence purpose, followed by a detailed markdown note and a prerequisite warning. While the markdown note is verbose, it provides essential usage guidance. The structure is front-loaded and the additional paragraphs earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the core purpose, storage location, tag behavior, and prerequisite calls, making it sufficient for an agent to invoke the tool correctly. It does not mention heading or parent_uid options, but these are fully described in the schema. Given the high schema coverage and output schema, the description is adequately complete, though it could briefly note that headings/parent_uid can organize memories.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters. The description adds value by explaining the storage behavior (daily page + tag), the optionality of categories, and a detailed markdown note relevant to formatting memory content and categories. However, the phrase '(unless include_memories_tag is false)' is ambiguous, potentially implying categories are also omitted when the tag is disabled, which conflicts with the schema's separate handling.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Add a memory or piece of information to remember') and specifies the storage location (daily page with ROAM_MEMORIES_TAG tag). This distinguishes it from siblings like roam_add_todo (adds tasks) and roam_recall (retrieves memories).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for use (storing memories) but does not explicitly state when to use this tool versus alternatives. It includes a prerequisite instruction to call roam_get_guidelines and load the markdown cheatsheet, but lacks exclusionary guidance such as 'use roam_add_todo for tasks' or 'use roam_recall to fetch memories.'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_rename_pageA
DestructiveIdempotent

Rename a page by changing its title. Identifies the page by current title or UID.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
uidNoUID of the page to rename (use this OR old_title, not both)
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
new_titleYesNew title for the page
old_titleNoCurrent title of the page to rename (use this OR uid, not both)
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
successYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this tool destructive and idempotent. The description adds useful context beyond annotations by requiring a call to roam_get_guidelines and noting that conventions affect reads as well as writes. This provides behavioral nuance not captured in the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief (two sentences) and front-loaded with the core purpose. The second sentence conveys a critical prerequisite but is slightly convoluted with 'reads included.' Overall, it is compact and earns its place, though the phrasing could be clearer.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple rename tool with a complete input schema, output schema, and annotations covering safety, the description adds the essential prerequisite and identification method. It does not explain error conditions, but these are not critical for correct tool usage in most contexts.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage for all parameters, including guidance on using old_title or uid. The description adds no additional parameter semantics beyond the phrase 'current title or UID,' which merely mirrors the schema. Baseline 3 is appropriate given high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function with a specific verb and resource: 'Rename a page by changing its title.' It also specifies the identification method ('by current title or UID'), distinguishing it from sibling tools like create_page or update_page_markdown.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage guidance by instructing the agent to call roam_get_guidelines before using this tool, including a rationale about conventions. However, it does not name alternative tools or state when not to use this tool, so it stops short of a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_search_block_refsA
Read-onlyIdempotent

Search for block references within a page or across the entire graph. Can search for references to a specific block, a page title, or find all block references.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
titleNoOptional: Page title to find references to (uses :block/refs for [[page]] and #tag links)
block_uidNoOptional: UID of the block to find references to (searches for ((uid)) patterns in text)
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
page_title_uidNoOptional: Title or UID of the page to search in (UID is preferred for accuracy). If not provided, searches across all pages.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and destructiveHint, but the description adds meaningful context: results must be interpreted based on graph conventions (calling roam_get_guidelines even for reads). This goes beyond the structured annotations by warning that behavior depends on per-graph conventions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs: a focused purpose statement followed by a critical warning. Every sentence is useful, no filler, and the most important usage instruction is front-loaded with 'IMPORTANT.'

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the full schema coverage, read-only annotations, and lack of an output schema, the description sufficiently explains the tool's capability and a key prerequisite. It could mention default behavior when no parameters are provided, but 'find all block references' is already implied, so it is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers all parameters with descriptions, providing a solid baseline. The description adds relationship semantics: block_uid targets a specific block, title targets page references, and page_title_uid scopes the search to a page or graph-wide. This helps agents understand how to combine parameters effectively.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Search for block references within a page or across the entire graph' and lists specific modes (specific block, page title, all references). This makes the tool's purpose unambiguous and distinguishes it from sibling text-search tools like roam_search_by_text, even though no alternatives are named.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description conveys when to use the tool (searching for references) and gives an explicit directive to call roam_get_guidelines first due to convention-dependent behavior. It does not explicitly compare with alternative search tools for when not to use it, but the usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_search_by_dateA
Read-onlyIdempotent

Search for blocks or pages based on creation or modification dates. Not for daily pages with ordinal date titles.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeYesWhether to search by creation date, modification date, or both
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
scopeYesWhether to search blocks, pages
end_dateNoOptional: End date in ISO format (YYYY-MM-DD)
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
start_dateYesStart date in ISO format (YYYY-MM-DD)
include_contentNoWhether to include the content of matching blocks/pages

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare read-only, idempotent, and non-destructive behavior. The description adds valuable context by requiring a call to roam_get_guidelines and warning that conventions change how results are read, going beyond what annotations and schema provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loaded with the core action and followed by a critical exclusion and warning. Every sentence earns its place, and the formatting makes the important prerequisite prominent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 7 parameters, no output schema, and rich annotations, the description plus schema is almost sufficient. It provides a mandatory guidelines call and exclusion, but could benefit from a brief note on result format or edge cases like end_date inclusivity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% coverage for all 7 parameters, so the baseline is 3. The description does not add any parameter-specific details, examples, or additional meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches blocks/pages by creation or modification dates, and includes an explicit exclusion for daily pages with ordinal date titles. It is specific and actionable, but does not explicitly name sibling alternatives to differentiate from.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Not for daily pages with ordinal date titles' (when-not) and instructs to call roam_get_guidelines once per session before using the tool (prerequisite). This provides clear usage context, even though it does not name an alternative tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_search_by_statusA
Read-onlyIdempotent

Search for blocks with a specific status (TODO/DONE) across all pages or within a specific page.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
statusYesStatus to search for (TODO or DONE)
excludeNoOptional: Comma-separated list of terms to filter results by exclusion (matches content or page title)
includeNoOptional: Comma-separated list of terms to filter results by inclusion (matches content or page title)
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
page_title_uidNoOptional: Title or UID of the page to search in (UID is preferred for accuracy). If not provided, searches across all pages.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds a meaningful behavioral nuance: graph conventions can change how results are read, not just written, and guidelines must be fetched once per session. This goes beyond the annotations and aids correct usage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences: the first states the purpose, the second delivers a critical usage prerequisite. It is front-loaded, concise, and every word adds value. No redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity and full schema coverage, the description is complete for selection and invocation. It discloses the prerequisite call, the scope options, and the status filter. It does not describe return format, but search tools without output schema are often self-explanatory. Minor gap: no mention of exclude/include filters beyond the schema, but those are documented there.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% coverage with detailed descriptions for all 6 parameters. The description does not add syntax or format details beyond the schema, so the baseline 3 is appropriate. The scope behavior (all pages vs specific page) is already captured in the page_title_uid parameter description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it searches for blocks by status (TODO/DONE) across all pages or a specific page. The verb 'search' plus resource 'blocks' and filter 'status' makes the purpose specific and distinguishes it from sibling search tools like roam_search_by_text or roam_search_by_date.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides an explicit prerequisite: call roam_get_guidelines before using this tool, even for reads. It also mentions the optional scope (all pages vs a specific page). However, it does not explicitly contrast with alternative search tools or state when-not-to-use, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_search_by_textA
Read-onlyIdempotent

Search for blocks containing specific text across all pages or within a specific page. Use scope: "page_titles" to search for pages by namespace prefix (e.g., "Convention/" finds all pages starting with that prefix). This tool supports pagination via the limit and offset parameters.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe text to search for. When scope is "page_titles", this is the namespace prefix (trailing slash optional).
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
limitNoOptional: The maximum number of results to return. Defaults to 50. Use -1 for no limit, but be aware that very large results sets can impact performance.
scopeNoSearch scope: "blocks" for block content (default), "page_titles" for page title namespace prefix matching.blocks
offsetNoOptional: The number of results to skip before returning matches. Useful for pagination. Defaults to 0.
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
case_sensitiveNoOptional: Whether the search should be case-sensitive. If false, it will search for the provided text, capitalized versions, and first word capitalized versions. Only used when scope is "blocks".
page_title_uidNoOptional: Title or UID of the page to search in (UID is preferred for accuracy). If not provided, searches across all pages. Only used when scope is "blocks".

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool read-only, idempotent, and non-destructive, lowering the bar. The description adds a meaningful behavioral note: graph conventions affect how results are read, not just written, implying results can vary between graphs. It also mentions pagination support, though the schema already documents limit/offset.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact: two sentences covering core functionality and a one-sentence important note. It front-loads the primary purpose, explains the alternate scope, then delivers the essential prerequisite. Every sentence earns its place without fluff or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 8 parameters but only 1 required, full schema coverage, and complete annotations, the description adds the crucial missing context: a session-level prerequisite to call roam_get_guidelines because conventions affect reads. The namespace prefix example clarifies a non-obvious mode. No output schema exists, but the return value for a block/page search tool is self-evident.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for all 8 parameters, so the baseline is 3. The description's mentions of `scope: 'page_titles'`, the namespace prefix example, and pagination via `limit`/`offset` all reinforce but do not add substantive meaning beyond what the parameter descriptions already provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Search for blocks containing specific text across all pages or within a specific page,' a specific verb and resource. It clearly distinguishes the free-text blocks search from the namespace-prefix page_titles mode, and the availability of these two modes helps set it apart from sibling search tools like roam_search_for_tag or roam_search_by_status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: it tells the agent to use scope 'page_titles' for namespace prefix searches and includes an 'IMPORTANT' instruction to call roam_get_guidelines once per session because conventions change how results are read. It lacks explicit exclusions or direct references to sibling alternatives, but the context is strong enough to guide appropriate selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_search_for_tagA
Read-onlyIdempotent

Search for blocks containing a specific tag. Use primary_tag for the tag to find, and optionally page_title_uid to limit search to a specific page. Supports pagination via limit and offset. Use this tool to search for memories tagged with the ROAM_MEMORIES_TAG.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
limitNoOptional: The maximum number of results to return. Defaults to 50. Use -1 for no limit, but be aware that very large results sets can impact performance.
offsetNoOptional: The number of results to skip before returning matches. Useful for pagination. Defaults to 0.
near_tagNoOptional: Another tag to filter results by - will only return blocks where both tags appear
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
primary_tagYesThe main tag to search for (without the [[ ]] brackets)
case_sensitiveNoOptional: Whether the search should be case-sensitive. If false, it will search for the provided tag, capitalized versions, and first word capitalized versions.
page_title_uidNoOptional: Title or UID of the page to search in (UID is preferred for accuracy). Defaults to today's daily page if not provided.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds behavior beyond annotations by mentioning pagination via limit/offset and the important note that conventions change how results are read, requiring a one-time call to roam_get_guidelines. This enriches the agent's understanding of how to invoke and interpret results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs, front-loaded with the primary purpose. The second paragraph is an important, non-obvious prerequisite that earns its place. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description doesn't detail the return structure, but the purpose implies a list of blocks. It covers the key parameters, pagination, page scoping, and a critical guideline call. This is sufficient for a read-only search tool with good annotation coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all 8 parameters are documented. The description briefly references primary_tag, page_title_uid, limit, and offset, but doesn't add meaningful semantics beyond the schema—it mostly repeats the schema's parameter descriptions. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Search for blocks containing a specific tag', which clearly states the verb (search) and resource (blocks with a tag). It also differentiates from sibling search tools by emphasizing tag-based search and gives a concrete use case ('search for memories tagged with the ROAM_MEMORIES_TAG').

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear context with 'Use this tool to search for memories tagged with the ROAM_MEMORIES_TAG' and instructs to call roam_get_guidelines first. It doesn't explicitly name alternatives or when-not cases, but the tag-focused purpose and required preliminary call give sufficient guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_search_hierarchyA
Read-onlyIdempotent

Search for parent or child blocks in the block hierarchy. Can search up or down the hierarchy from a given block.

IMPORTANT: call roam_get_guidelines for this graph once per session before using this tool, reads included — conventions change how results are read, not just written.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
child_uidNoOptional: UID of the block to find parents of
max_depthNoOptional: How many levels deep to search (default: 1)
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.
parent_uidNoOptional: UID of the block to find children of
page_title_uidNoOptional: Title or UID of the page to search in (UID is preferred for accuracy).

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety. The description adds valuable behavioral context: the ability to search both up and down, and the critical caveat that per-graph conventions affect how results are read. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs: the first front-loads the core purpose, the second delivers an essential prerequisite note. No filler words, every sentence earns its place, and the structure is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (6 optional params, no output schema), the description covers the essential behavioral scope and a critical prerequisite. It does not explain edge cases like providing both parent_uid and child_uid, or default behavior when neither is given, but the annotations and schema fill many gaps, making the description reasonably complete for a read-only search tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% coverage with descriptions for all six parameters, so the baseline is 3. The description adds minimal extra meaning beyond the schema, mainly correlating 'from a given block' with parent/child UID parameters. It does not elaborate on parameter interactions (e.g., mutual exclusivity), but the schema already handles the basics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Search for parent or child blocks') on a specific resource ('block hierarchy'), and clarifies the directional capability ('up or down') from a given block. This clearly distinguishes it from sibling search tools like roam_search_by_text or roam_search_by_status, which operate on content or status rather than hierarchy.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes it obvious when to use this tool: when you need to traverse parent/child relationships in the block hierarchy. It also provides a mandatory prerequisite instruction to call roam_get_guidelines once per session, which is concrete usage guidance. However, it does not explicitly mention alternatives or when not to use this tool, so it falls short of the strongest 'when-not' clarity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

roam_update_page_markdownA
DestructiveIdempotent

Update an existing page with new markdown content using smart diff. Preserves block UIDs where possible and generates minimal changes. This is ideal for:

  • Syncing external markdown files to Roam

  • AI-assisted content updates that preserve references

  • Batch content modifications without losing block references

⚠️ This REPLACES the page, it does not append. Any block your markdown does not account for is deleted. Pass the complete intended page, or use roam_process_batch_actions / roam_create_outline to change only part of one. Use dry_run: true to see the actions first.

How it works:

  1. Fetches existing page blocks

  2. Matches new content to existing blocks by text similarity

  3. Generates minimal create/update/move/delete operations

  4. Preserves UIDs for matched blocks (keeping references intact)

#.rm-hide / #.rm-private subtrees are excluded from the diff and left untouched — you cannot see them, so you cannot be asked to account for them. preserved_hidden reports how many, when any.

IMPORTANT: call roam_get_guidelines for this graph once per session, and load the Roam Markdown Cheatsheet, before using this tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
graphNoTarget graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.
titleYesTitle of the page to update
dry_runNoIf true, returns the planned actions without executing them. Useful for previewing changes.
markdownYesNew GFM markdown content for the page
write_keyNoWrite confirmation key. Required for write operations on non-default graphs when write_key is configured.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statsYes
actionsYesRoam batch actions applied (or planned, when dry_run)
successYes
summaryYes
preserved_uidsYesBlocks whose UIDs survived the diff, so refs to them still resolve
preserved_hiddenNoPresent only when non-zero: how many #.rm-hide / #.rm-private blocks were excluded from the diff and left on the page untouched

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description explicitly discloses that 'This REPLACES the page' and any unaccounted block is deleted. It explains the smart diff algorithm step-by-step, mentions hidden subtrees are excluded and left untouched, and that `preserved_hidden` reports the count. It also notes the requirement to call guidelines once per session, offering deep behavioral insight beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Despite being long, the description is well-structured with clear sections: summary, use cases, warning, how-it-works steps, hidden subtree note, and important prerequisite. Every sentence adds critical information, and the formatting (bullets, bold warning, numbered list) makes it scannable. It is appropriately detailed for a complex, destructive tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is exceptionally complete given the tool's complexity. It covers purpose, alternatives, destructive behavior, algorithm steps, hidden content handling, output hints, and required prior steps. Combined with rich schema and annotations, the agent has all necessary context to select and invoke the tool safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds some context around `dry_run` usage and mentions `preserved_hidden` (an output field), but does not provide additional meaning for the parameters beyond what the schema already documents. It reinforces the purpose but does not elevate semantic understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'Updates an existing page with new markdown content using smart diff' and lists specific use cases. It distinguishes itself from siblings by explicitly naming alternatives like `roam_process_batch_actions` and `roam_create_outline` for partial edits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use the tool ('ideal for syncing...', 'AI-assisted content updates...') and when not to, warning that it replaces the whole page and directing to alternatives for partial changes. It also instructs to use `dry_run: true` and to call `roam_get_guidelines` first, covering prerequisites and exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A3.9/5.0
Disambiguation4/5

Each tool has a distinct primary purpose, and descriptions include explicit disambiguation notes (e.g., get_subpages vs search_hierarchy). However, the large number of search/find tools (search_by_text, search_for_tag, search_by_status, search_by_date, find_pages_modified_today) can still cause confusion, so not a perfect 5.

Naming Consistency3/5

All tools use snake_case and the `roam_` prefix, but action verbs are inconsistent: fetch, get, search, find, create, add. Search tools mix preposition patterns (search_by_text, search_for_tag, search_block_refs), and two tools are noun phrases (roam_markdown_cheatsheet, roam_datomic_query).

Tool Count3/5

25 tools is at the high end of the 'feels heavy' range. The complexity of Roam's data model justifies many operations, but some search variants could be consolidated. The count is not extreme, but it is on the boundary.

Completeness4/5

The set covers page/block creation, retrieval, update, batch operations, rich search, memory, table creation, markdown import, and custom Datomic queries. Explicit page/block deletion tools are missing, though batch actions include delete. There is no general 'list all pages' tool, but search_by_text with page_titles scope partially fills this gap.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    A Model Context Protocol server that enables Claude Desktop to read from and write to Roam Research graphs, allowing for retrieving page content, finding references, and adding blocks to existing or daily pages.
    4
    1
  • A
    license
    A
    quality
    Not graded
    maintenance
    Enables AI assistants to interact with Roam Research graphs through comprehensive API access, supporting page/block operations, markdown import, search, memory storage, and complex batch actions for managing knowledge graphs.
    18
    119

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/2b3pro/roam-research-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server