roam-research-mcp 1.4.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +360 -31
  2. package/build/Roam_Markdown_Cheatsheet.md +30 -12
  3. package/build/cli/batch/resolver.js +138 -0
  4. package/build/cli/batch/translator.js +363 -0
  5. package/build/cli/batch/types.js +4 -0
  6. package/build/cli/commands/batch.js +352 -0
  7. package/build/cli/commands/get.js +161 -0
  8. package/build/cli/commands/refs.js +135 -0
  9. package/build/cli/commands/rename.js +58 -0
  10. package/build/cli/commands/save.js +498 -0
  11. package/build/cli/commands/search.js +240 -0
  12. package/build/cli/commands/status.js +91 -0
  13. package/build/cli/commands/update.js +151 -0
  14. package/build/cli/roam.js +35 -0
  15. package/build/cli/utils/graph.js +56 -0
  16. package/build/cli/utils/output.js +122 -0
  17. package/build/config/environment.js +70 -34
  18. package/build/config/graph-registry.js +221 -0
  19. package/build/config/graph-registry.test.js +30 -0
  20. package/build/search/block-ref-search.js +34 -7
  21. package/build/search/status-search.js +5 -4
  22. package/build/server/roam-server.js +98 -53
  23. package/build/shared/validation.js +10 -5
  24. package/build/tools/helpers/refs.js +50 -31
  25. package/build/tools/operations/blocks.js +38 -1
  26. package/build/tools/operations/memory.js +51 -5
  27. package/build/tools/operations/pages.js +186 -111
  28. package/build/tools/operations/search/index.js +5 -1
  29. package/build/tools/operations/todos.js +1 -1
  30. package/build/tools/schemas.js +121 -41
  31. package/build/tools/tool-handlers.js +9 -2
  32. package/build/utils/helpers.js +22 -0
  33. package/package.json +11 -7
  34. package/build/cli/import-markdown.js +0 -98
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
- ![](./roam-research-mcp-image.jpeg)
1
+ ![Roam Research MCP + CLI](./roam-research-mcp-header.png)
2
2
 
3
- # Roam Research MCP Server
3
+ # Roam Research MCP + CLI
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/roam-research-mcp.svg)](https://badge.fury.io/js/roam-research-mcp)
6
- [![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
6
+ [![Project Status: Active](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
8
  [![GitHub](https://img.shields.io/github/license/2b3pro/roam-research-mcp)](https://github.com/2b3pro/roam-research-mcp/blob/main/LICENSE)
9
9
 
10
- A Model Context Protocol (MCP) server that provides comprehensive access to Roam Research's API functionality. This server enables AI assistants like Claude to interact with your Roam Research graph through a standardized interface. It supports standard input/output (stdio) and HTTP Stream communication. (A WORK-IN-PROGRESS, personal project not officially endorsed by Roam Research)
10
+ A Model Context Protocol (MCP) server and standalone CLI that provides comprehensive access to Roam Research's API functionality. The MCP server enables AI assistants like Claude to interact with your Roam Research graph through a standardized interface, while the CLI (`roam`) lets you fetch, search, and import content directly from the command line. Supports multi-graph configurations, write protection, standard input/output (stdio) and HTTP Stream communication. (Personal project, not officially endorsed by Roam Research)
11
11
 
12
12
  <a href="https://glama.ai/mcp/servers/fzfznyaflu"><img width="380" height="200" src="https://glama.ai/mcp/servers/fzfznyaflu/badge" alt="Roam Research MCP server" /></a>
13
13
  <a href="https://mseep.ai/app/2b3pro-roam-research-mcp"><img width="380" height="200" src="https://mseep.net/pr/2b3pro-roam-research-mcp-badge.png" alt="MseeP.ai Security Assessment Badge" /></a>
@@ -83,56 +83,323 @@ Alternatively, if you have a `.env` file in the project root (which is copied in
83
83
  docker run -p 3000:3000 -p 8088:8088 --env-file .env roam-research-mcp
84
84
  ```
85
85
 
86
- ## Standalone CLI: roam-import
86
+ ## Standalone CLI: `roam`
87
87
 
88
- A standalone command-line tool for importing markdown content directly into Roam Research, without running the MCP server.
88
+ A standalone command-line tool for interacting with Roam Research directly, without running the MCP server. Provides eight subcommands: `get`, `search`, `save`, `refs`, `update`, `batch`, `rename`, and `status`.
89
89
 
90
- ### Usage
90
+ ### Installation
91
+
92
+ After building the project, make the command globally available:
93
+
94
+ ```bash
95
+ npm link
96
+ ```
97
+
98
+ Or run directly without linking:
99
+
100
+ ```bash
101
+ node build/cli/roam.js <command> [options]
102
+ ```
103
+
104
+ ### Requirements
105
+
106
+ Same environment variables as the MCP server:
107
+ - `ROAM_API_TOKEN`: Your Roam Research API token
108
+ - `ROAM_GRAPH_NAME`: Your Roam graph name
109
+
110
+ Configure via `.env` file in the project root or set as environment variables.
111
+
112
+ ---
113
+
114
+ ### `roam get` - Fetch pages, blocks, or TODOs
115
+
116
+ Fetch content from Roam and output as markdown or JSON.
117
+
118
+ ```bash
119
+ # Fetch a page by title
120
+ roam get "Daily Notes"
121
+
122
+ # Fetch a block by UID
123
+ roam get "((AbCdEfGhI))"
124
+ roam get AbCdEfGhI
125
+
126
+ # Output as JSON
127
+ roam get "Daily Notes" --json
128
+
129
+ # Control child depth (default: 4)
130
+ roam get "Daily Notes" --depth 2
131
+
132
+ # Flatten hierarchy
133
+ roam get "Daily Notes" --flat
134
+
135
+ # Fetch TODO items
136
+ roam get --todo
137
+
138
+ # Fetch DONE items
139
+ roam get --done
140
+
141
+ # Filter TODOs by page
142
+ roam get --todo -p "January 2nd, 2026"
143
+
144
+ # Include/exclude filter
145
+ roam get --todo -i "urgent,important" -e "someday"
146
+
147
+ # Debug mode
148
+ roam get "Daily Notes" --debug
149
+ ```
150
+
151
+ **Options:**
152
+ - `--json` - Output as JSON instead of markdown
153
+ - `--depth <n>` - Child levels to fetch (default: 4)
154
+ - `--refs <n>` - Block ref expansion depth (default: 1)
155
+ - `--flat` - Flatten hierarchy to single-level list
156
+ - `--todo` - Fetch TODO items
157
+ - `--done` - Fetch DONE items
158
+ - `-p, --page <title>` - Filter TODOs/DONEs by page title
159
+ - `-i, --include <terms>` - Include only items containing these terms (comma-separated)
160
+ - `-e, --exclude <terms>` - Exclude items containing these terms (comma-separated)
161
+ - `--debug` - Show query metadata
162
+
163
+ ---
164
+
165
+ ### `roam search` - Search content
166
+
167
+ Search for blocks containing text or tags.
91
168
 
92
169
  ```bash
93
- # From a file
94
- cat document.md | roam-import "Meeting Notes"
170
+ # Full-text search
171
+ roam search "keyword"
172
+
173
+ # Multiple terms (AND logic)
174
+ roam search "term1" "term2"
175
+
176
+ # Tag-only search
177
+ roam search --tag "[[Project]]"
178
+ roam search --tag "#TODO"
179
+
180
+ # Text + tag filter
181
+ roam search "meeting" --tag "[[Work]]"
182
+
183
+ # Scope to a specific page
184
+ roam search "task" --page "Daily Notes"
185
+
186
+ # Case-insensitive search
187
+ roam search "keyword" -i
188
+
189
+ # Limit results (default: 20)
190
+ roam search "keyword" -n 50
191
+
192
+ # Output as JSON
193
+ roam search "keyword" --json
194
+ ```
195
+
196
+ **Options:**
197
+ - `--tag <tag>` - Filter by tag (e.g., `#TODO` or `[[Project]]`)
198
+ - `--page <title>` - Scope search to a specific page
199
+ - `-i, --case-insensitive` - Case-insensitive search
200
+ - `-n, --limit <n>` - Limit number of results (default: 20)
201
+ - `--json` - Output as JSON
202
+ - `--debug` - Show query metadata
203
+
204
+ ---
205
+
206
+ ### `roam save` - Import markdown or create TODOs
95
207
 
96
- # From clipboard (macOS)
97
- pbpaste | roam-import "Ideas"
208
+ Import markdown content to Roam, creating or updating pages, or add TODO items.
209
+
210
+ ```bash
211
+ # From a file (title derived from filename)
212
+ roam save document.md
213
+
214
+ # With explicit title
215
+ roam save document.md --title "Meeting Notes"
216
+
217
+ # Update existing page with smart diff (preserves block UIDs)
218
+ roam save document.md --update
219
+
220
+ # From stdin (requires --title)
221
+ cat notes.md | roam save --title "Quick Notes"
222
+ pbpaste | roam save --title "Clipboard Content"
98
223
 
99
224
  # From here-doc
100
- roam-import "Quick Note" << EOF
225
+ roam save --title "Quick Note" << EOF
101
226
  # Heading
102
227
  - Item 1
103
228
  - Item 2
104
229
  - Nested item
105
230
  EOF
231
+
232
+ # Create a TODO item on today's daily page
233
+ roam save --todo "Buy groceries"
234
+
235
+ # Create multiple TODOs from stdin (newline-separated)
236
+ echo -e "Task 1\nTask 2\nTask 3" | roam save --todo
237
+
238
+ # Pipe TODO list from file
239
+ cat todos.txt | roam save --todo
106
240
  ```
107
241
 
108
- ### Features
242
+ **Options:**
243
+ - `--title <title>` - Page title (defaults to filename without `.md`)
244
+ - `--update` - Update existing page using smart diff (preserves block UIDs)
245
+ - `-t, --todo [text]` - Add a TODO item to today's daily page (text or stdin)
246
+ - `--debug` - Show debug information
109
247
 
110
- - Reads markdown from stdin
248
+ **Features:**
111
249
  - Creates a new page with the specified title (or appends to existing page)
112
250
  - Automatically links the new page from today's daily page
113
- - Converts standard markdown to Roam-flavored markdown (bold, italic, highlights, tasks, code blocks)
251
+ - Converts standard markdown to Roam-flavored markdown
252
+ - Smart diff mode (`--update`) preserves block UIDs for existing content
253
+ - TODO mode creates `{{[[TODO]]}}` items on the daily page
114
254
 
115
- ### Installation
255
+ ---
116
256
 
117
- After building the project, make the command globally available:
257
+ ### `roam refs` - Find references
258
+
259
+ Find blocks that reference a page or block (backlinks).
118
260
 
119
261
  ```bash
120
- npm link
262
+ # Find references to a page
263
+ roam refs "Project Alpha"
264
+ roam refs "December 30th, 2025"
265
+
266
+ # Find references to a tag
267
+ roam refs "#TODO"
268
+ roam refs "[[Meeting Notes]]"
269
+
270
+ # Find references to a block
271
+ roam refs "((AbCdEfGhI))"
272
+
273
+ # Limit results
274
+ roam refs "My Page" -n 100
275
+
276
+ # Output as JSON (for LLM/programmatic use)
277
+ roam refs "My Page" --json
278
+
279
+ # Raw output (for piping)
280
+ roam refs "My Page" --raw
121
281
  ```
122
282
 
123
- Or run directly without linking:
283
+ **Options:**
284
+ - `-n, --limit <n>` - Limit number of results (default: 50)
285
+ - `--json` - Output as JSON array
286
+ - `--raw` - Output raw UID + content lines (no grouping)
287
+ - `--debug` - Show query metadata
288
+
289
+ **Output Formats:**
290
+
291
+ Default output groups results by page:
292
+ ```
293
+ [[Reading List: Inbox]]
294
+ tiTqNBvYA Date Captured:: [[December 30th, 2025]]
295
+
296
+ [[Week 53, 2025]]
297
+ g0ur1z7Bs [Sun 28]([[December 28th, 2025]]) | [Mon 29](...
298
+ ```
299
+
300
+ JSON output for programmatic use:
301
+ ```json
302
+ [
303
+ {"uid": "tiTqNBvYA", "content": "Date Captured:: [[December 30th, 2025]]", "page": "Reading List: Inbox"}
304
+ ]
305
+ ```
306
+
307
+ ---
308
+
309
+ ### `roam batch` - Execute multiple operations in one API call
310
+
311
+ Execute multiple operations in a single batch API call to reduce rate limiting issues.
124
312
 
125
313
  ```bash
126
- cat document.md | node build/cli/import-markdown.js "Page Title"
314
+ # From a JSON file
315
+ roam batch commands.json
316
+
317
+ # From stdin
318
+ cat commands.json | roam batch
319
+
320
+ # Dry run (validate without executing)
321
+ roam batch --dry-run commands.json
322
+
323
+ # With debug output
324
+ roam batch --debug commands.json
127
325
  ```
128
326
 
129
- ### Requirements
327
+ **Command Format:**
130
328
 
131
- Same environment variables as the MCP server:
132
- - `ROAM_API_TOKEN`: Your Roam Research API token
133
- - `ROAM_GRAPH_NAME`: Your Roam graph name
329
+ Input is a JSON array of command objects:
134
330
 
135
- Configure via `.env` file in the project root or set as environment variables.
331
+ ```json
332
+ [
333
+ { "command": "create", "params": { "text": "Parent block", "parent": "pageUid", "as": "p1" } },
334
+ { "command": "create", "params": { "text": "Child block", "parent": "{{p1}}" } },
335
+ { "command": "todo", "params": { "text": "Task item" } },
336
+ { "command": "codeblock", "params": { "parent": "{{p1}}", "language": "ts", "code": "const x = 1;" } }
337
+ ]
338
+ ```
339
+
340
+ **Supported Commands:**
341
+
342
+ | Command | Description |
343
+ |---------|-------------|
344
+ | `create` | Create a block |
345
+ | `update` | Update block content |
346
+ | `delete` | Delete a block |
347
+ | `move` | Move block to new location |
348
+ | `todo` | Create TODO item |
349
+ | `table` | Create table structure |
350
+ | `outline` | Create nested outline |
351
+ | `remember` | Create tagged memory |
352
+ | `page` | Create page with content |
353
+ | `codeblock` | Create code block |
354
+
355
+ **Features:**
356
+
357
+ - Placeholder references (`{{name}}`) for cross-command dependencies
358
+ - Automatic page title → UID resolution
359
+ - Daily page auto-resolution for `todo` and `remember`
360
+ - Level-based hierarchy for `outline` command
361
+ - `--dry-run` mode for validation
362
+
363
+ **Options:**
364
+ - `--dry-run` - Validate and show planned actions without executing
365
+ - `--debug` - Show debug information
366
+ - `-g, --graph <name>` - Target graph (multi-graph mode)
367
+ - `--write-key <key>` - Write confirmation key
368
+
369
+ See [docs/batch-cli-spec.md](docs/batch-cli-spec.md) for full specification.
370
+
371
+ ---
372
+
373
+ ### `roam status` - Show available graphs
374
+
375
+ Display configured graphs and their connection status.
376
+
377
+ ```bash
378
+ # Show available graphs
379
+ roam status
380
+
381
+ # Test connectivity to all graphs
382
+ roam status --ping
383
+
384
+ # Output as JSON
385
+ roam status --json
386
+ ```
387
+
388
+ **Example Output:**
389
+
390
+ ```
391
+ Roam Research MCP v2.4.0
392
+
393
+ Graphs:
394
+ • personal (default) ✓ connected
395
+ • work [protected] ✓ connected
396
+
397
+ Write-protected graphs require --write-key flag for modifications.
398
+ ```
399
+
400
+ **Options:**
401
+ - `--ping` - Test connection to each graph
402
+ - `--json` - Output as JSON for scripting
136
403
 
137
404
  ---
138
405
 
@@ -162,24 +429,25 @@ The server provides powerful tools for interacting with Roam Research:
162
429
 
163
430
  1. `roam_fetch_page_by_title`: Fetch page content by title. Returns content in the specified format.
164
431
  2. `roam_fetch_block_with_children`: Fetch a block by its UID along with its hierarchical children down to a specified depth. Automatically handles `((UID))` formatting.
165
- 3. `roam_create_page`: Create new pages with optional content and headings. **Now supports mixed content types** - content array can include both text blocks and tables in a single call using `{type: "table", headers, rows}` format. Creates a block on the daily page linking to the newly created page.
432
+ 3. `roam_create_page`: Create new pages with optional content and headings. **Now supports mixed content types** - content array can include both text blocks and tables in a single call using `{type: "table", headers, rows}` format. Automatically adds a "Processed: [[date]]" block at the end of the page linking to today's daily page.
166
433
  4. `roam_create_table`: Create a properly formatted Roam table with specified headers and rows. Abstracts Roam's complex nested table structure, validates row/column consistency, and handles empty cells automatically.
167
434
  5. `roam_import_markdown`: Import nested markdown content under a specific block. (Internally uses `roam_process_batch_actions`.)
168
435
  6. `roam_add_todo`: Add a list of todo items to today's daily page. (Internally uses `roam_process_batch_actions`.)
169
436
  7. `roam_create_outline`: Add a structured outline to an existing page or block, with support for `children_view_type`. Best for simpler, sequential outlines. For complex nesting (e.g., tables), consider `roam_process_batch_actions`. If `page_title_uid` and `block_text_uid` are both blank, content defaults to the daily page. (Internally uses `roam_process_batch_actions`.)
170
- 8. `roam_search_block_refs`: Search for block references within a page or across the entire graph.
437
+ 8. `roam_search_block_refs`: Search for block references within a page or across the entire graph. Now supports `title` parameter to find blocks referencing a page title using `:block/refs` (captures `[[page]]` and `#tag` links semantically).
171
438
  9. `roam_search_hierarchy`: Search for parent or child blocks in the block hierarchy.
172
439
  10. `roam_find_pages_modified_today`: Find pages that have been modified today (since midnight), with pagination and sorting options.
173
440
  11. `roam_search_by_text`: Search for blocks containing specific text across all pages or within a specific page. This tool supports pagination via the `limit` and `offset` parameters.
174
441
  12. `roam_search_by_status`: Search for blocks with a specific status (TODO/DONE) across all pages or within a specific page.
175
442
  13. `roam_search_by_date`: Search for blocks or pages based on creation or modification dates.
176
443
  14. `roam_search_for_tag`: Search for blocks containing a specific tag and optionally filter by blocks that also contain another tag nearby or exclude blocks with a specific tag. This tool supports pagination via the `limit` and `offset` parameters.
177
- 15. `roam_remember`: Add a memory or piece of information to remember. (Internally uses `roam_process_batch_actions`.)
444
+ 15. `roam_remember`: Add a memory or piece of information to remember. Supports optional `heading` parameter to nest under a specific heading on the daily page (created if missing), or `parent_uid` to nest under a specific block. (Internally uses `roam_process_batch_actions`.)
178
445
  16. `roam_recall`: Retrieve all stored memories.
179
446
  17. `roam_datomic_query`: Execute a custom Datomic query on the Roam graph for advanced data retrieval beyond the available search tools. Now supports client-side regex filtering for enhanced post-query processing. Optimal for complex filtering (including regex), highly complex boolean logic, arbitrary sorting criteria, and proximity search.
180
447
  18. `roam_markdown_cheatsheet`: Provides the content of the Roam Markdown Cheatsheet resource, optionally concatenated with custom instructions if `CUSTOM_INSTRUCTIONS_PATH` environment variable is set.
181
448
  19. `roam_process_batch_actions`: Execute a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Provides granular control for complex nesting like tables. **Now includes pre-validation** that catches errors before API execution, with structured error responses and automatic rate limit retry with exponential backoff. (Note: For actions on existing blocks or within a specific page context, it is often necessary to first obtain valid page or block UIDs using tools like `roam_fetch_page_by_title`.)
182
449
  20. `roam_update_page_markdown`: Update an existing page with new markdown content using smart diff. **Preserves block UIDs** where possible, keeping references intact across the graph. Uses three-phase matching (exact text → normalized → position fallback) to generate minimal operations. Supports `dry_run` mode to preview changes. Ideal for syncing external markdown files, AI-assisted content updates, and batch modifications without losing block references.
450
+ 21. `roam_move_block`: Move a block to a new location (different parent or position). Convenience wrapper around `roam_process_batch_actions` for single block moves. Parameters: `block_uid` (required), `parent_uid` (required), `order` (optional, defaults to "last").
183
451
 
184
452
  **Deprecated Tools**:
185
453
  The following tools have been deprecated as of `v0.36.2` in favor of the more powerful and flexible `roam_process_batch_actions`:
@@ -320,9 +588,13 @@ The tool will match existing blocks by content, update changed text, add new blo
320
588
  - Create a new token
321
589
 
322
590
  2. Configure the environment variables:
323
- You have two options for configuring the required environment variables:
324
591
 
325
- Option 1: Using a .env file (Recommended for development)
592
+ ### Single Graph Mode (Default)
593
+
594
+ For most users with one Roam graph, use the simple configuration:
595
+
596
+ **Option 1: Using a .env file (Recommended for development)**
597
+
326
598
  Create a `.env` file in the roam-research directory:
327
599
 
328
600
  ```
@@ -333,7 +605,8 @@ The tool will match existing blocks by content, update changed text, add new blo
333
605
  HTTP_STREAM_PORT=8088 # Or your desired port for HTTP Stream communication
334
606
  ```
335
607
 
336
- Option 2: Using MCP settings (Alternative method)
608
+ **Option 2: Using MCP settings (Alternative method)**
609
+
337
610
  Add the configuration to your MCP settings file. Note that you may need to update the `args` to `["/path/to/roam-research-mcp/build/index.js"]` if you are running the server directly.
338
611
 
339
612
  - For Cline (`~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`):
@@ -359,6 +632,62 @@ The tool will match existing blocks by content, update changed text, add new blo
359
632
 
360
633
  Note: The server will first try to load from .env file, then fall back to environment variables from MCP settings.
361
634
 
635
+ ---
636
+
637
+ ### Multi-Graph Mode (v2.0.0+)
638
+
639
+ For users with multiple Roam graphs, you can configure a single MCP server instance to connect to all of them. This is more token-efficient than running multiple server instances.
640
+
641
+ **Configuration:**
642
+
643
+ ```json
644
+ ROAM_GRAPHS="{\"personal\":{\"token\":\"roam-graph-token-xxx\",\"graph\":\"my-personal-graph\"},\"work\":{\"token\":\"roam-graph-token-yyy\",\"graph\":\"company-graph\",\"write_key\":\"confirm-work-write\"}}"
645
+ ROAM_DEFAULT_GRAPH=personal
646
+ ```
647
+
648
+ | Field | Required | Description |
649
+ |-------|----------|-------------|
650
+ | `token` | Yes | Roam API token for this graph |
651
+ | `graph` | Yes | Roam graph name |
652
+ | `write_key` | No | Required confirmation string for writes to non-default graphs |
653
+
654
+ **Usage in Tools:**
655
+
656
+ All tools accept optional `graph` and `write_key` parameters:
657
+
658
+ ```json
659
+ {
660
+ "title": "My Page",
661
+ "graph": "work",
662
+ "write_key": "confirm-work-write"
663
+ }
664
+ ```
665
+
666
+ - **Read operations**: Can target any graph using the `graph` parameter
667
+ - **Write operations on default graph**: Work without additional parameters
668
+ - **Write operations on non-default graphs**: Require the `write_key` if configured
669
+
670
+ **CLI Usage:**
671
+
672
+ All CLI commands support the `-g, --graph` flag:
673
+
674
+ ```bash
675
+ # Read from work graph
676
+ roam get "Meeting Notes" -g work
677
+
678
+ # Write to work graph (requires --write-key if configured)
679
+ roam save notes.md -g work --write-key "confirm-work-write"
680
+ ```
681
+
682
+ **Safety Model:**
683
+
684
+ The `write_key` serves as a confirmation gate (not a secret) to prevent accidental writes to non-default graphs. When a write is attempted without the required key, the error message reveals the expected key:
685
+
686
+ ```
687
+ Write to "work" graph requires write_key confirmation.
688
+ Provide write_key: "confirm-work-write" to proceed.
689
+ ```
690
+
362
691
  3. Build the server (make sure you're in the root directory of the MCP):
363
692
 
364
693
  Note: Customize 'Roam_Markdown_Cheatsheet.md' with any notes and preferences specific to your graph BEFORE building.
@@ -1,4 +1,4 @@
1
- # Roam Markdown Cheatsheet — Generic Foundation v2.0.0
1
+ # Roam Markdown Cheatsheet — Generic Foundation v2.0.1
2
2
 
3
3
  > ⚠️ **MODEL DIRECTIVE**: Always consult this cheatsheet BEFORE making any Roam tool calls. Syntax errors in Roam are unforgiving.
4
4
 
@@ -36,6 +36,8 @@
36
36
 
37
37
  ⚠️ **CRITICAL**: Never concatenate multi-word tags. `#knowledgemanagement` ≠ `#[[knowledge management]]`
38
38
 
39
+ ⚠️ **CRITICAL**: Never use `#` to mean "number" (e.g., `#1`, `#2`). In Roam, `#` **always** creates a hashtag. Write `Step 1`, `No. 1`, or just spell out the number instead.
40
+
39
41
  ### Dates
40
42
  - **Always use ordinal format**: `[[January 1st, 2025]]`, `[[December 23rd, 2024]]`
41
43
  - Ordinals: 1st, 2nd, 3rd, 4th–20th, 21st, 22nd, 23rd, 24th–30th, 31st
@@ -72,7 +74,7 @@ Source:: https://example.com
72
74
  | `Note:: Some observation` | Just write the text, or use `#note` | One-off labels don't need attribute syntax |
73
75
  | `Summary:: The main point` | `**Summary:** The main point` | Section headers are formatting, not metadata |
74
76
  | `Definition:: Some text` | `Term:: Definition` | Only use for actual definitions you want to query |
75
- | `Implementation Tier 3 (Societal Restructuring):: Some text` | `** Implementation Tier 3 (Societal Restructuring)**: Some text` | Label is specific to current concept |
77
+ | `Implementation Tier 3 (Societal Restructuring):: Some text` | `**Implementation Tier 3 (Societal Restructuring):** Some text` | Label is specific to current concept |
76
78
 
77
79
  ⚠️ **The Test**: Ask yourself: "Will I ever query for all blocks with this attribute across my graph?" If no, use **bold formatting** (`**Label:**`) instead of `::` syntax.
78
80
 
@@ -174,6 +176,7 @@ Tables use nested indentation. Each column header/cell nests ONE LEVEL DEEPER th
174
176
  |----------|-----------|-----|
175
177
  | `Step 1:: Do this` | `**Step 1:** Do this` | `::` creates queryable attributes; use bold for page-specific labels |
176
178
  | `#multiplewords` | `#[[multiple words]]` | Concatenated tags create dead references |
179
+ | `#1`, `#2`, `#3` | `Step 1`, `No. 1`, or spell out | `#` always creates hashtags, never means "number" |
177
180
  | `[[january 1, 2025]]` | `[[January 1st, 2025]]` | Must use ordinal format with proper capitalization |
178
181
  | `[text](((block-uid)))` | `[text](<((block-uid))>)` | Block ref links need angle bracket wrapper |
179
182
  | `{{embed: ((uid))}}` | `{{[[embed]]: ((uid))}}` | Embed requires double brackets around keyword |
@@ -198,9 +201,17 @@ CREATING CONTENT IN ROAM:
198
201
  │ └─ Complex/nested markdown → roam_import_markdown
199
202
  │ (for deeply nested content, tables, etc.)
200
203
 
204
+ ├─ Replacing/revising ENTIRE page content?
205
+ │ └─ roam_update_page_markdown
206
+ │ (fetches page internally, computes smart diff, preserves UIDs)
207
+
201
208
  ├─ Need to CREATE, UPDATE, MOVE, or DELETE individual blocks?
202
209
  │ └─ roam_process_batch_actions
203
- │ (fine-grained control, temporary UIDs for parent refs)
210
+ │ (fine-grained control, UID placeholders for parent refs)
211
+
212
+ ├─ Creating a TABLE?
213
+ │ └─ roam_create_table
214
+ │ (handles complex nested structure automatically)
204
215
 
205
216
  ├─ Adding a memory/note to remember?
206
217
  │ └─ roam_remember (auto-tags with MEMORIES_TAG)
@@ -210,9 +221,11 @@ CREATING CONTENT IN ROAM:
210
221
 
211
222
  └─ SEARCHING/READING:
212
223
  ├─ Find by tag → roam_search_for_tag
213
- ├─ Find by text → roam_search_by_text
224
+ ├─ Find by text → roam_search_by_text
214
225
  ├─ Find by date range → roam_search_by_date
215
226
  ├─ Find by status → roam_search_by_status
227
+ ├─ Find block/page references → roam_search_block_refs
228
+ ├─ Find pages modified today → roam_find_pages_modified_today
216
229
  ├─ Get page content → roam_fetch_page_by_title
217
230
  ├─ Get block + children → roam_fetch_block_with_children
218
231
  ├─ Recall memories → roam_recall
@@ -226,18 +239,18 @@ CREATING CONTENT IN ROAM:
226
239
  The Roam API has rate limits. Follow these guidelines to minimize API calls:
227
240
 
228
241
  ### Tool Efficiency Ranking (Best to Worst)
229
- 1. **`roam_process_batch_actions`** - Single API call for multiple operations (MOST EFFICIENT)
230
- 2. **`roam_create_page`** - Batches content with page creation
231
- 3. **`roam_create_outline` / `roam_import_markdown`** - Include verification queries (use for smaller operations)
232
- 4. **Multiple sequential tool calls** - Each call = multiple API requests (AVOID)
242
+ 1. **`roam_update_page_markdown`** - Single call: fetches, diffs, and updates (MOST EFFICIENT for revisions)
243
+ 2. **`roam_process_batch_actions`** - Single API call for multiple operations
244
+ 3. **`roam_create_page`** - Batches content with page creation
245
+ 4. **`roam_create_outline` / `roam_import_markdown`** - Include verification queries (use for smaller operations)
246
+ 5. **Multiple sequential tool calls** - Each call = multiple API requests (AVOID)
233
247
 
234
248
  ### Best Practices for Intensive Operations
235
249
 
236
250
  #### When Updating/Revising a Page:
237
- 1. Fetch the page content ONCE at the start
238
- 2. Plan ALL changes needed (creates, updates, deletes)
239
- 3. Execute ALL changes in a SINGLE `roam_process_batch_actions` call
240
- 4. Do NOT fetch-modify-fetch-modify in a loop
251
+ 1. **Preferred**: Use `roam_update_page_markdown` it fetches, diffs, and updates in one call
252
+ 2. **Alternative** (for fine-grained control): Fetch once with `roam_fetch_page_by_title`, then execute ALL changes in a SINGLE `roam_process_batch_actions` call
253
+ 3. Do NOT fetch-modify-fetch-modify in a loop
241
254
 
242
255
  #### When Creating Large Content:
243
256
  - For 10+ blocks: Use `roam_process_batch_actions` with nested structure
@@ -285,6 +298,11 @@ When using `roam_process_batch_actions` to create nested blocks, use **placehold
285
298
 
286
299
  **Do this:**
287
300
  ```
301
+ 1. roam_update_page_markdown → single call handles fetch, diff, and updates
302
+ ```
303
+
304
+ **Alternative** (when you need fine-grained control):
305
+ ```
288
306
  1. roam_fetch_page_by_title → get page UID and content
289
307
  2. roam_process_batch_actions → ALL creates/updates in one call
290
308
  ```