roam-research-mcp 2.4.0 → 2.13.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.
- package/README.md +175 -667
- package/build/Roam_Markdown_Cheatsheet.md +138 -289
- package/build/cache/page-uid-cache.js +40 -2
- package/build/cli/batch/translator.js +1 -1
- package/build/cli/commands/batch.js +3 -8
- package/build/cli/commands/get.js +478 -60
- package/build/cli/commands/refs.js +51 -31
- package/build/cli/commands/save.js +61 -10
- package/build/cli/commands/search.js +63 -58
- package/build/cli/commands/status.js +3 -4
- package/build/cli/commands/update.js +71 -28
- package/build/cli/utils/graph.js +6 -2
- package/build/cli/utils/input.js +10 -0
- package/build/cli/utils/output.js +28 -5
- package/build/cli/utils/sort-group.js +110 -0
- package/build/config/graph-registry.js +31 -13
- package/build/config/graph-registry.test.js +42 -5
- package/build/markdown-utils.js +114 -4
- package/build/markdown-utils.test.js +125 -0
- package/build/query/generator.js +330 -0
- package/build/query/index.js +149 -0
- package/build/query/parser.js +319 -0
- package/build/query/parser.test.js +389 -0
- package/build/query/types.js +4 -0
- package/build/search/ancestor-rule.js +14 -0
- package/build/search/block-ref-search.js +1 -5
- package/build/search/hierarchy-search.js +5 -12
- package/build/search/index.js +1 -0
- package/build/search/status-search.js +10 -9
- package/build/search/tag-search.js +8 -24
- package/build/search/text-search.js +70 -27
- package/build/search/types.js +13 -0
- package/build/search/utils.js +71 -2
- package/build/server/roam-server.js +4 -3
- package/build/shared/index.js +2 -0
- package/build/shared/page-validator.js +233 -0
- package/build/shared/page-validator.test.js +128 -0
- package/build/shared/staged-batch.js +144 -0
- package/build/tools/helpers/batch-utils.js +57 -0
- package/build/tools/helpers/page-resolution.js +136 -0
- package/build/tools/helpers/refs.js +68 -0
- package/build/tools/operations/batch.js +75 -3
- package/build/tools/operations/block-retrieval.js +15 -4
- package/build/tools/operations/block-retrieval.test.js +87 -0
- package/build/tools/operations/blocks.js +1 -288
- package/build/tools/operations/memory.js +32 -90
- package/build/tools/operations/outline.js +38 -156
- package/build/tools/operations/pages.js +169 -122
- package/build/tools/operations/todos.js +5 -37
- package/build/tools/schemas.js +20 -9
- package/build/tools/tool-handlers.js +4 -4
- package/build/utils/helpers.js +27 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,765 +7,273 @@
|
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
[](https://github.com/2b3pro/roam-research-mcp/blob/main/LICENSE)
|
|
9
9
|
|
|
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
|
-
|
|
12
10
|
<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
11
|
<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>
|
|
14
12
|
|
|
15
|
-
##
|
|
13
|
+
## Introduction
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
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)](https://modelcontextprotocol.io/) server to give AI agents access to my notes, I realized the underlying tools were powerful enough to stand on their own.
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
2. **HTTP Stream:** Provides network-based communication, suitable for web-based clients, remote applications, or scenarios requiring real-time updates over HTTP. The HTTP Stream endpoint runs on port `8088` by default.
|
|
17
|
+
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.
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
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.
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
## Standalone CLI: `roam`
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
npm install -g roam-research-mcp
|
|
28
|
-
roam-research-mcp
|
|
29
|
-
```
|
|
23
|
+
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.
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
### Quick Examples
|
|
32
26
|
|
|
33
27
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
npm install
|
|
37
|
-
npm run build
|
|
38
|
-
npm start
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Running with HTTP Stream
|
|
28
|
+
# Save a quick thought to your daily page
|
|
29
|
+
roam save "Idea: A CLI for Roam would be cool"
|
|
42
30
|
|
|
43
|
-
|
|
31
|
+
# Pipe content from a file to a new page
|
|
32
|
+
cat meeting_notes.md | roam save --title "Meeting: Project Alpha"
|
|
44
33
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
HTTP_STREAM_PORT=9000 npm start
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Or, if using a `.env` file, add `HTTP_STREAM_PORT=9000` to it.
|
|
34
|
+
# Create a TODO item on today's daily page
|
|
35
|
+
echo "Buy milk" | roam save --todo
|
|
53
36
|
|
|
54
|
-
|
|
37
|
+
# Search your graph and pipe results to another tool
|
|
38
|
+
roam search "important" --json | jq .
|
|
55
39
|
|
|
56
|
-
|
|
40
|
+
# Search for pages by namespace prefix
|
|
41
|
+
roam search --namespace "Convention" # Finds all Convention/* pages
|
|
57
42
|
|
|
58
|
-
|
|
43
|
+
# Fetch a page by title
|
|
44
|
+
roam get "Roam Research"
|
|
59
45
|
|
|
60
|
-
|
|
46
|
+
# Fetch page by UID or Roam URL
|
|
47
|
+
roam get page abc123def
|
|
48
|
+
roam get page "https://roamresearch.com/#/app/my-graph/page/abc123def"
|
|
61
49
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
```
|
|
50
|
+
# Sort and group results
|
|
51
|
+
roam get --tag Project --sort created --group-by tag
|
|
65
52
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
To run the Docker container and map the necessary ports, you must also provide the required environment variables. Use the `-e` flag to pass `ROAM_API_TOKEN`, `ROAM_GRAPH_NAME`, and optionally `MEMORIES_TAG` and `HTTP_STREAM_PORT`:
|
|
53
|
+
# Find references (backlinks) to a page
|
|
54
|
+
roam refs "Project Alpha"
|
|
69
55
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
-e ROAM_API_TOKEN="your-api-token" \
|
|
73
|
-
-e ROAM_GRAPH_NAME="your-graph-name" \
|
|
74
|
-
-e MEMORIES_TAG="#[[LLM/Memories]]" \
|
|
75
|
-
-e CUSTOM_INSTRUCTIONS_PATH="/path/to/your/custom_instructions_file.md" \
|
|
76
|
-
-e HTTP_STREAM_PORT="8088" \
|
|
77
|
-
roam-research-mcp
|
|
78
|
-
```
|
|
56
|
+
# Update a block (e.g., toggle TODO status)
|
|
57
|
+
roam update ((block-uid)) --todo
|
|
79
58
|
|
|
80
|
-
|
|
59
|
+
# Multi-graph: read from a specific graph
|
|
60
|
+
roam get "Page Title" -g work
|
|
81
61
|
|
|
82
|
-
|
|
83
|
-
|
|
62
|
+
# Multi-graph: write to a protected graph
|
|
63
|
+
roam save "Note" -g work --write-key "$ROAM_SYSTEM_WRITE_KEY"
|
|
84
64
|
```
|
|
85
65
|
|
|
86
|
-
|
|
87
|
-
|
|
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`.
|
|
66
|
+
**Available Commands:** `get`, `search`, `save`, `refs`, `update`, `batch`, `rename`, `status`.
|
|
67
|
+
Run `roam <command> --help` for details on any command.
|
|
89
68
|
|
|
90
69
|
### Installation
|
|
91
70
|
|
|
92
|
-
After building the project, make the command globally available:
|
|
93
|
-
|
|
94
71
|
```bash
|
|
95
|
-
npm
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Or run directly without linking:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
node build/cli/roam.js <command> [options]
|
|
72
|
+
npm install -g roam-research-mcp
|
|
73
|
+
# The 'roam' command is now available globally
|
|
102
74
|
```
|
|
103
75
|
|
|
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
76
|
---
|
|
113
77
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
78
|
+
## MCP Server Tools
|
|
79
|
+
|
|
80
|
+
The MCP server exposes these tools to AI assistants (like Claude), enabling them to read, write, and organize your Roam graph intelligently.
|
|
81
|
+
|
|
82
|
+
> **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.
|
|
83
|
+
|
|
84
|
+
| Tool Name | Description |
|
|
85
|
+
| :--- | :--- |
|
|
86
|
+
| `roam_fetch_page_by_title` | Fetch page content by title. |
|
|
87
|
+
| `roam_fetch_block_with_children` | Fetch a block and its nested children by UID (resolves refs). |
|
|
88
|
+
| `roam_create_page` | Create new pages, optionally with mixed text and table content. |
|
|
89
|
+
| `roam_update_page_markdown` | Update a page using smart diff (preserves block UIDs). |
|
|
90
|
+
| `roam_search_by_text` | Full-text search across the graph or within specific pages. Supports namespace prefix search for page titles. |
|
|
91
|
+
| `roam_search_block_refs` | Find blocks that reference a page, tag, or block UID. |
|
|
92
|
+
| `roam_search_by_status` | Find TODO or DONE items. |
|
|
93
|
+
| `roam_search_for_tag` | Find blocks containing specific tags (supports exclusion). |
|
|
94
|
+
| `roam_search_by_date` | Find blocks/pages by creation or modification date. |
|
|
95
|
+
| `roam_find_pages_modified_today` | List pages modified since midnight. |
|
|
96
|
+
| `roam_add_todo` | Add TODO items to today's daily page. |
|
|
97
|
+
| `roam_create_table` | Create properly formatted Roam tables. |
|
|
98
|
+
| `roam_create_outline` | Create hierarchical outlines. |
|
|
99
|
+
| `roam_process_batch_actions` | Execute multiple low-level actions (create, move, update, delete) in one batch. |
|
|
100
|
+
| `roam_move_block` | Move a block to a new parent or position. |
|
|
101
|
+
| `roam_remember` / `roam_recall` | specialized tools for AI memory management within Roam. |
|
|
102
|
+
| `roam_datomic_query` | Execute raw Datalog queries for advanced filtering. |
|
|
103
|
+
| `roam_markdown_cheatsheet` | Retrieve the Roam-flavored markdown reference. |
|
|
162
104
|
|
|
163
105
|
---
|
|
164
106
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
Search for blocks containing text or tags.
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
# Full-text search
|
|
171
|
-
roam search "keyword"
|
|
172
|
-
|
|
173
|
-
# Multiple terms (AND logic)
|
|
174
|
-
roam search "term1" "term2"
|
|
107
|
+
## Configuration
|
|
175
108
|
|
|
176
|
-
|
|
177
|
-
roam search --tag "[[Project]]"
|
|
178
|
-
roam search --tag "#TODO"
|
|
109
|
+
### Environment Variables
|
|
179
110
|
|
|
180
|
-
|
|
181
|
-
roam search "meeting" --tag "[[Work]]"
|
|
111
|
+
#### Single Graph Mode
|
|
182
112
|
|
|
183
|
-
|
|
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
|
|
207
|
-
|
|
208
|
-
Import markdown content to Roam, creating or updating pages, or add TODO items.
|
|
113
|
+
For a single Roam graph, set these in your environment or a `.env` file:
|
|
209
114
|
|
|
210
115
|
```bash
|
|
211
|
-
|
|
212
|
-
|
|
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"
|
|
223
|
-
|
|
224
|
-
# From here-doc
|
|
225
|
-
roam save --title "Quick Note" << EOF
|
|
226
|
-
# Heading
|
|
227
|
-
- Item 1
|
|
228
|
-
- Item 2
|
|
229
|
-
- Nested item
|
|
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
|
|
116
|
+
ROAM_API_TOKEN=your-api-token
|
|
117
|
+
ROAM_GRAPH_NAME=your-graph-name
|
|
240
118
|
```
|
|
241
119
|
|
|
242
|
-
|
|
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
|
|
247
|
-
|
|
248
|
-
**Features:**
|
|
249
|
-
- Creates a new page with the specified title (or appends to existing page)
|
|
250
|
-
- Automatically links the new page from today's daily page
|
|
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
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
### `roam refs` - Find references
|
|
120
|
+
#### Multi-Graph Mode (v2.0+)
|
|
258
121
|
|
|
259
|
-
|
|
122
|
+
Connect to multiple Roam graphs from a single server instance:
|
|
260
123
|
|
|
261
124
|
```bash
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
|
125
|
+
ROAM_GRAPHS='{
|
|
126
|
+
"personal": {"token": "token-1", "graph": "personal-db", "memoriesTag": "#[[Personal Memories]]"},
|
|
127
|
+
"work": {"token": "token-2", "graph": "work-db", "protected": true, "memoriesTag": "#[[Work Memories]]"},
|
|
128
|
+
"research": {"token": "token-3", "graph": "research-db"}
|
|
129
|
+
}'
|
|
130
|
+
ROAM_DEFAULT_GRAPH=personal
|
|
131
|
+
ROAM_SYSTEM_WRITE_KEY=your-secret-key
|
|
281
132
|
```
|
|
282
133
|
|
|
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:**
|
|
134
|
+
**Graph Configuration Options:**
|
|
290
135
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
g0ur1z7Bs [Sun 28]([[December 28th, 2025]]) | [Mon 29](...
|
|
298
|
-
```
|
|
136
|
+
| Property | Required | Description |
|
|
137
|
+
|----------|----------|-------------|
|
|
138
|
+
| `token` | Yes | Roam API token for this graph |
|
|
139
|
+
| `graph` | Yes | Graph name/database identifier |
|
|
140
|
+
| `protected` | No | If `true`, writes require `ROAM_SYSTEM_WRITE_KEY` confirmation |
|
|
141
|
+
| `memoriesTag` | No | Tag for `roam_remember`/`roam_recall` (overrides global default) |
|
|
299
142
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
[
|
|
303
|
-
{"uid": "tiTqNBvYA", "content": "Date Captured:: [[December 30th, 2025]]", "page": "Reading List: Inbox"}
|
|
304
|
-
]
|
|
305
|
-
```
|
|
143
|
+
**Write Protection:**
|
|
144
|
+
Protected graphs require the `write_key` parameter matching `ROAM_SYSTEM_WRITE_KEY` for any write operation. This prevents accidental writes to sensitive graphs.
|
|
306
145
|
|
|
307
|
-
|
|
146
|
+
*Optional:*
|
|
147
|
+
- `ROAM_MEMORIES_TAG`: Default tag for `roam_remember`/`roam_recall` (fallback when per-graph `memoriesTag` not set).
|
|
148
|
+
- `HTTP_STREAM_PORT`: To enable HTTP Stream (defaults to 8088).
|
|
308
149
|
|
|
309
|
-
###
|
|
150
|
+
### Running the Server
|
|
310
151
|
|
|
311
|
-
|
|
152
|
+
**1. Stdio Mode (Default)**
|
|
153
|
+
Best for local integration (e.g., Claude Desktop, IDE extensions).
|
|
312
154
|
|
|
313
155
|
```bash
|
|
314
|
-
|
|
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
|
|
156
|
+
npx roam-research-mcp
|
|
325
157
|
```
|
|
326
158
|
|
|
327
|
-
**
|
|
328
|
-
|
|
329
|
-
Input is a JSON array of command objects:
|
|
330
|
-
|
|
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.
|
|
159
|
+
**2. HTTP Stream Mode**
|
|
160
|
+
Best for remote access or web clients.
|
|
376
161
|
|
|
377
162
|
```bash
|
|
378
|
-
|
|
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
|
-
|
|
163
|
+
HTTP_STREAM_PORT=8088 npx roam-research-mcp
|
|
390
164
|
```
|
|
391
|
-
Roam Research MCP v2.4.0
|
|
392
165
|
|
|
393
|
-
|
|
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
|
|
403
|
-
|
|
404
|
-
---
|
|
405
|
-
|
|
406
|
-
## To Test
|
|
407
|
-
|
|
408
|
-
Run [MCP Inspector](https://github.com/modelcontextprotocol/inspector) after build using the provided npm script:
|
|
166
|
+
**3. Docker**
|
|
409
167
|
|
|
410
168
|
```bash
|
|
411
|
-
|
|
169
|
+
docker run -p 3000:3000 -p 8088:8088 --env-file .env roam-research-mcp
|
|
412
170
|
```
|
|
413
171
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
The server provides powerful tools for interacting with Roam Research:
|
|
417
|
-
|
|
418
|
-
- Environment variable handling with .env support
|
|
419
|
-
- Comprehensive input validation
|
|
420
|
-
- Case-insensitive page title matching
|
|
421
|
-
- Recursive block reference resolution
|
|
422
|
-
- Markdown parsing and conversion
|
|
423
|
-
- Daily page integration
|
|
424
|
-
- Detailed debug logging
|
|
425
|
-
- Efficient batch operations
|
|
426
|
-
- Hierarchical outline creation
|
|
427
|
-
- Enhanced documentation for Roam Tables in `Roam_Markdown_Cheatsheet.md` for clearer guidance on nesting.
|
|
428
|
-
- Custom instruction appended to the cheat sheet about your specific Roam notes.
|
|
429
|
-
|
|
430
|
-
1. `roam_fetch_page_by_title`: Fetch page content by title. Returns content in the specified format.
|
|
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.
|
|
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.
|
|
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.
|
|
434
|
-
5. `roam_import_markdown`: Import nested markdown content under a specific block. (Internally uses `roam_process_batch_actions`.)
|
|
435
|
-
6. `roam_add_todo`: Add a list of todo items to today's daily page. (Internally uses `roam_process_batch_actions`.)
|
|
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`.)
|
|
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).
|
|
438
|
-
9. `roam_search_hierarchy`: Search for parent or child blocks in the block hierarchy.
|
|
439
|
-
10. `roam_find_pages_modified_today`: Find pages that have been modified today (since midnight), with pagination and sorting options.
|
|
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.
|
|
441
|
-
12. `roam_search_by_status`: Search for blocks with a specific status (TODO/DONE) across all pages or within a specific page.
|
|
442
|
-
13. `roam_search_by_date`: Search for blocks or pages based on creation or modification dates.
|
|
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.
|
|
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`.)
|
|
445
|
-
16. `roam_recall`: Retrieve all stored memories.
|
|
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.
|
|
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.
|
|
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`.)
|
|
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").
|
|
451
|
-
|
|
452
|
-
**Deprecated Tools**:
|
|
453
|
-
The following tools have been deprecated as of `v0.36.2` in favor of the more powerful and flexible `roam_process_batch_actions`:
|
|
454
|
-
|
|
455
|
-
- `roam_create_block`: Use `roam_process_batch_actions` with the `create-block` action.
|
|
456
|
-
- `roam_update_block`: Use `roam_process_batch_actions` with the `update-block` action.
|
|
457
|
-
- `roam_update_multiple_blocks`: Use `roam_process_batch_actions` with multiple `update-block` actions.
|
|
458
|
-
|
|
459
|
-
---
|
|
460
|
-
|
|
461
|
-
### Tool Usage Guidelines and Best Practices
|
|
172
|
+
### Configuring in LLMs
|
|
462
173
|
|
|
463
|
-
**
|
|
464
|
-
✅ Before attempting any Roam operations, **it is highly recommended** to load the `Roam Markdown Cheatsheet` resource into your context. This ensures you have immediate access to the correct Roam-flavored Markdown syntax, including details for tables, block references, and other special formatting. Example prompt: "Read the Roam cheatsheet first. Then, … <rest of your instructions>"
|
|
174
|
+
**Claude Desktop / Cline:**
|
|
465
175
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
**Identifying Pages and Blocks for Manipulation:**
|
|
469
|
-
To ensure accurate operations, always strive to identify target pages and blocks using their Unique Identifiers (UIDs) whenever possible. While some tools accept case-sensitive text titles or content, UIDs provide unambiguous references, reducing the risk of errors due to ambiguity or changes in text.
|
|
470
|
-
|
|
471
|
-
- **For Pages:** Use `roam_fetch_page_by_title` to retrieve a page's UID if you only have its title. Example: "Read the page titled 'Trip to Las Vegas'"
|
|
472
|
-
- **For Blocks:** If you need to manipulate an existing block, first use search tools like `roam_search_by_text`, `roam_search_for_tag`, or `roam_fetch_page_by_title` (with raw format) to find the block and obtain its UID. If the block exists on a page that has already been read, then a search isn't necessary.
|
|
473
|
-
|
|
474
|
-
**Case-Sensitivity:**
|
|
475
|
-
Be aware that text-based inputs (e.g., page titles, block content for search) are generally case-sensitive in Roam. Always match the exact casing of the text as it appears in your graph.
|
|
476
|
-
|
|
477
|
-
**Iterative Refinement and Verification:**
|
|
478
|
-
For complex operations, especially those involving nested structures or multiple changes, it is often beneficial to break down the task into smaller, verifiable steps. After each significant tool call, consider fetching the affected content to verify the changes before proceeding.
|
|
479
|
-
|
|
480
|
-
**Understanding Tool Nuances:**
|
|
481
|
-
Familiarize yourself with the specific behaviors and limitations of each tool. For instance, `roam_create_outline` is best for sequential outlines, while `roam_process_batch_actions` offers granular control for complex structures like tables. Refer to the individual tool descriptions for detailed usage notes.
|
|
482
|
-
|
|
483
|
-
When making changes to your Roam graph, precision in your requests is crucial for achieving desired outcomes.
|
|
484
|
-
|
|
485
|
-
**Specificity in Requests:**
|
|
486
|
-
Some tools allow for identifying blocks or pages by their text content (e.g., `parent_string`, `title`). While convenient, using **Unique Identifiers (UIDs)** is always preferred for accuracy and reliability. Text-based matching can be prone to errors if there are multiple blocks with similar content or if the content changes. Tools are designed to work best when provided with explicit UIDs where available.
|
|
487
|
-
|
|
488
|
-
**Example of Specificity:**
|
|
489
|
-
Instead of:
|
|
490
|
-
`"parent_string": "My project notes"`
|
|
491
|
-
|
|
492
|
-
Prefer:
|
|
493
|
-
`"parent_uid": "((some-unique-uid))"`
|
|
494
|
-
|
|
495
|
-
**Caveat Regarding Heading Formatting:**
|
|
496
|
-
Please note that while the `roam_process_batch_actions` tool can set block headings (H1, H2, H3), directly **removing** an existing heading (i.e., reverting a heading block to a plain text block) through this tool is not currently supported by the Roam API. The `heading` attribute persists its value once set, and attempting to remove it by setting `heading` to `0`, `null`, or omitting the property will not unset the heading.
|
|
497
|
-
|
|
498
|
-
---
|
|
176
|
+
Add to your MCP settings file (e.g., `~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
499
177
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
"
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
178
|
+
*Single Graph:*
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"mcpServers": {
|
|
182
|
+
"roam-research": {
|
|
183
|
+
"command": "npx",
|
|
184
|
+
"args": ["-y", "roam-research-mcp"],
|
|
185
|
+
"env": {
|
|
186
|
+
"ROAM_API_TOKEN": "your-token",
|
|
187
|
+
"ROAM_GRAPH_NAME": "your-graph"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
*Multi-Graph:*
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"mcpServers": {
|
|
198
|
+
"roam-research": {
|
|
199
|
+
"command": "npx",
|
|
200
|
+
"args": ["-y", "roam-research-mcp"],
|
|
201
|
+
"env": {
|
|
202
|
+
"ROAM_GRAPHS": "{\"personal\":{\"token\":\"token-1\",\"graph\":\"personal-db\",\"memoriesTag\":\"#[[Memories]]\"},\"work\":{\"token\":\"token-2\",\"graph\":\"work-db\",\"protected\":true}}",
|
|
203
|
+
"ROAM_DEFAULT_GRAPH": "personal",
|
|
204
|
+
"ROAM_SYSTEM_WRITE_KEY": "your-secret-key"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
522
209
|
```
|
|
523
210
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
This example shows how to mark existing to-do items as `DONE` and add a new one, all within a single batch.
|
|
211
|
+
## Query Block Parser (v2.11.0+)
|
|
527
212
|
|
|
528
|
-
|
|
529
|
-
"Mark 'Finish report' and 'Review presentation' as done on today's daily page, and add a new todo 'Prepare for meeting'."
|
|
530
|
-
```
|
|
213
|
+
A utility for parsing and executing Roam query blocks programmatically. Converts `{{[[query]]: ...}}` syntax into Datalog queries.
|
|
531
214
|
|
|
532
|
-
###
|
|
215
|
+
### Supported Clauses
|
|
533
216
|
|
|
534
|
-
|
|
217
|
+
| Clause | Syntax | Description |
|
|
218
|
+
|--------|--------|-------------|
|
|
219
|
+
| Page ref | `[[page]]` | Blocks referencing a page |
|
|
220
|
+
| Block ref | `((uid))` | Blocks referencing a block |
|
|
221
|
+
| `and` | `{and: [[a]] [[b]]}` | All conditions must match |
|
|
222
|
+
| `or` | `{or: [[a]] [[b]]}` | Any condition matches |
|
|
223
|
+
| `not` | `{not: [[tag]]}` | Exclude matches |
|
|
224
|
+
| `between` | `{between: [[date1]] [[date2]]}` | Date range filter |
|
|
225
|
+
| `search` | `{search: text}` | Full-text search |
|
|
226
|
+
| `daily notes` | `{daily notes: }` | Daily notes pages only |
|
|
227
|
+
| `by` | `{by: [[User]]}` | Created or edited by user |
|
|
228
|
+
| `created by` | `{created by: [[User]]}` | Created by user |
|
|
229
|
+
| `edited by` | `{edited by: User}` | Edited by user |
|
|
535
230
|
|
|
536
|
-
|
|
537
|
-
"Move the block 'Important note about client feedback' (from page 'Meeting Notes 2025-06-30') under the 'Action Items' section on the 'Project Alpha Planning' page, and change its content to 'Client feedback reviewed and incorporated'."
|
|
538
|
-
```
|
|
231
|
+
### Relative Dates
|
|
539
232
|
|
|
540
|
-
|
|
233
|
+
The `between` clause supports relative dates: `today`, `yesterday`, `last week`, `last month`, `this year`, `7 days ago`, `2 months ago`, etc.
|
|
541
234
|
|
|
542
|
-
|
|
235
|
+
### Usage
|
|
543
236
|
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
```
|
|
237
|
+
```typescript
|
|
238
|
+
import { QueryExecutor } from 'roam-research-mcp/query';
|
|
547
239
|
|
|
548
|
-
|
|
240
|
+
const executor = new QueryExecutor(graph);
|
|
549
241
|
|
|
550
|
-
|
|
242
|
+
// Execute a query
|
|
243
|
+
const results = await executor.execute(
|
|
244
|
+
'{{[[query]]: "My Query" {and: [[Project]] {between: [[last month]] [[today]]}}}}'
|
|
245
|
+
);
|
|
551
246
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
- A heading 'Overview'
|
|
555
|
-
- An introduction paragraph explaining the comparison
|
|
556
|
-
- A comparison table with columns: Feature, Plan A, Plan B
|
|
557
|
-
- Rows: Price ($10, $20), Storage (10GB, 50GB), Support (Email, 24/7)
|
|
558
|
-
- A conclusion section"
|
|
247
|
+
// Parse without executing (for debugging)
|
|
248
|
+
const { name, query } = QueryParser.parseWithName(queryBlock);
|
|
559
249
|
```
|
|
560
250
|
|
|
561
|
-
###
|
|
251
|
+
### Utility Functions
|
|
562
252
|
|
|
563
|
-
|
|
253
|
+
```typescript
|
|
254
|
+
import { isQueryBlock, extractQueryBlocks } from 'roam-research-mcp/query';
|
|
564
255
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
- Overview (keep existing UID)
|
|
568
|
-
- Updated Goals section
|
|
569
|
-
- Revised Scope with new details
|
|
570
|
-
- Team Members
|
|
571
|
-
- John Doe (Senior Dev)
|
|
572
|
-
- Jane Smith (PM)
|
|
573
|
-
- New hire: Bob Wilson
|
|
574
|
-
- Updated Timeline
|
|
575
|
-
- Remove the old 'Deadlines' section"
|
|
576
|
-
```
|
|
256
|
+
// Detect if text is a query block
|
|
257
|
+
isQueryBlock('{{[[query]]: [[tag]]}}'); // true
|
|
577
258
|
|
|
578
|
-
|
|
259
|
+
// Extract all query blocks from a string
|
|
260
|
+
extractQueryBlocks(pageContent); // ['{{[[query]]: ...}}', ...]
|
|
261
|
+
```
|
|
579
262
|
|
|
580
263
|
---
|
|
581
264
|
|
|
582
|
-
##
|
|
583
|
-
|
|
584
|
-
1. Create a [Roam Research API token](https://x.com/RoamResearch/status/1789358175474327881):
|
|
585
|
-
|
|
586
|
-
- Go to your graph settings
|
|
587
|
-
- Navigate to the "API tokens" section (Settings > "Graph" tab > "API Tokens" section and click on the "+ New API Token" button)
|
|
588
|
-
- Create a new token
|
|
589
|
-
|
|
590
|
-
2. Configure the environment variables:
|
|
591
|
-
|
|
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)**
|
|
265
|
+
## Support
|
|
597
266
|
|
|
598
|
-
|
|
267
|
+
If this project helps you manage your knowledge base or build cool agents, consider buying me a coffee! It helps keep the updates coming.
|
|
599
268
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
MEMORIES_TAG='#[[LLM/Memories]]'
|
|
604
|
-
CUSTOM_INSTRUCTIONS_PATH='/path/to/your/custom_instructions_file.md'
|
|
605
|
-
HTTP_STREAM_PORT=8088 # Or your desired port for HTTP Stream communication
|
|
606
|
-
```
|
|
269
|
+
<a href="https://paypal.me/2b3/5">
|
|
270
|
+
<img src="https://img.shields.io/badge/Donate-PayPal-blue.svg" alt="Donate with PayPal" />
|
|
271
|
+
</a>
|
|
607
272
|
|
|
608
|
-
|
|
609
|
-
|
|
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.
|
|
611
|
-
|
|
612
|
-
- For Cline (`~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`):
|
|
613
|
-
- For Claude desktop app (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
614
|
-
|
|
615
|
-
```json
|
|
616
|
-
{
|
|
617
|
-
"mcpServers": {
|
|
618
|
-
"roam-research": {
|
|
619
|
-
"command": "node",
|
|
620
|
-
"args": ["/path/to/roam-research-mcp/build/index.js"],
|
|
621
|
-
"env": {
|
|
622
|
-
"ROAM_API_TOKEN": "your-api-token",
|
|
623
|
-
"ROAM_GRAPH_NAME": "your-graph-name",
|
|
624
|
-
"MEMORIES_TAG": "#[[LLM/Memories]]",
|
|
625
|
-
"CUSTOM_INSTRUCTIONS_PATH": "/path/to/your/custom_instructions_file.md",
|
|
626
|
-
"HTTP_STREAM_PORT": "8088"
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
Note: The server will first try to load from .env file, then fall back to environment variables from MCP settings.
|
|
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
|
-
|
|
691
|
-
3. Build the server (make sure you're in the root directory of the MCP):
|
|
692
|
-
|
|
693
|
-
Note: Customize 'Roam_Markdown_Cheatsheet.md' with any notes and preferences specific to your graph BEFORE building.
|
|
694
|
-
|
|
695
|
-
```bash
|
|
696
|
-
cd roam-research-mcp
|
|
697
|
-
npm install
|
|
698
|
-
npm run build
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
## Error Handling
|
|
702
|
-
|
|
703
|
-
The server provides comprehensive error handling for common scenarios:
|
|
704
|
-
|
|
705
|
-
- Configuration errors:
|
|
706
|
-
- Missing API token or graph name
|
|
707
|
-
- Invalid environment variables
|
|
708
|
-
- API errors:
|
|
709
|
-
- Authentication failures
|
|
710
|
-
- Invalid requests
|
|
711
|
-
- Failed operations
|
|
712
|
-
- Tool-specific errors:
|
|
713
|
-
- Page not found (with case-insensitive search)
|
|
714
|
-
- Block not found by string match
|
|
715
|
-
- Invalid markdown format
|
|
716
|
-
- Missing required parameters
|
|
717
|
-
- Invalid outline structure or content
|
|
718
|
-
|
|
719
|
-
Each error response includes:
|
|
720
|
-
|
|
721
|
-
- Standard MCP error code
|
|
722
|
-
- Detailed error message
|
|
723
|
-
- Suggestions for resolution when applicable
|
|
273
|
+
**[https://paypal.me/2b3/5](https://paypal.me/2b3/5)**
|
|
724
274
|
|
|
725
275
|
---
|
|
726
276
|
|
|
727
|
-
## Development
|
|
728
|
-
|
|
729
|
-
### Building
|
|
730
|
-
|
|
731
|
-
To build the server:
|
|
732
|
-
|
|
733
|
-
```bash
|
|
734
|
-
npm install
|
|
735
|
-
npm run build
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
This will:
|
|
739
|
-
|
|
740
|
-
1. Install all required dependencies
|
|
741
|
-
2. Compile TypeScript to JavaScript
|
|
742
|
-
3. Make the output file executable
|
|
743
|
-
|
|
744
|
-
You can also use `npm run watch` during development to automatically recompile when files change.
|
|
745
|
-
|
|
746
|
-
### Testing with MCP Inspector
|
|
747
|
-
|
|
748
|
-
The MCP Inspector is a tool that helps test and debug MCP servers. To test the server:
|
|
749
|
-
|
|
750
|
-
```bash
|
|
751
|
-
# Inspect with npx:
|
|
752
|
-
npx @modelcontextprotocol/inspector node build/index.js
|
|
753
|
-
```
|
|
754
|
-
|
|
755
|
-
This will:
|
|
756
|
-
|
|
757
|
-
1. Start the server in inspector mode
|
|
758
|
-
2. Provide an interactive interface to:
|
|
759
|
-
- List available tools and resources
|
|
760
|
-
- Execute tools with custom parameters
|
|
761
|
-
- View tool responses and error handling
|
|
762
|
-
|
|
763
277
|
## License
|
|
764
278
|
|
|
765
|
-
MIT License
|
|
766
|
-
|
|
767
|
-
---
|
|
768
|
-
|
|
769
|
-
## About the Author
|
|
770
|
-
|
|
771
|
-
This project is maintained by [Ian Shen](https://github.com/2b3pro).
|
|
279
|
+
MIT License - Created by [Ian Shen](https://github.com/2b3pro).
|