roam-research-mcp 1.6.0 → 2.4.3

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.
@@ -1,11 +1,34 @@
1
1
  // Tool definitions and input schemas for Roam Research MCP server
2
+ /**
3
+ * Multi-graph parameters that are added to all tool schemas
4
+ * These enable targeting specific graphs and providing write confirmation
5
+ */
6
+ const multiGraphParams = {
7
+ graph: {
8
+ type: 'string',
9
+ description: 'Target graph key from ROAM_GRAPHS config. Defaults to ROAM_DEFAULT_GRAPH. Only needed in multi-graph mode.'
10
+ },
11
+ write_key: {
12
+ type: 'string',
13
+ description: 'Write confirmation key. Required for write operations on non-default graphs when write_key is configured.'
14
+ }
15
+ };
16
+ /**
17
+ * Helper to add multi-graph params to a schema's properties
18
+ */
19
+ function withMultiGraphParams(properties) {
20
+ return {
21
+ ...properties,
22
+ ...multiGraphParams
23
+ };
24
+ }
2
25
  export const toolSchemas = {
3
26
  roam_add_todo: {
4
27
  name: 'roam_add_todo',
5
28
  description: '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.\nNOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use [alias]([[link]]) syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words).\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
6
29
  inputSchema: {
7
30
  type: 'object',
8
- properties: {
31
+ properties: withMultiGraphParams({
9
32
  todos: {
10
33
  type: 'array',
11
34
  items: {
@@ -14,7 +37,7 @@ export const toolSchemas = {
14
37
  },
15
38
  description: 'List of todo items to add'
16
39
  }
17
- },
40
+ }),
18
41
  required: ['todos'],
19
42
  },
20
43
  },
@@ -23,7 +46,7 @@ export const toolSchemas = {
23
46
  description: 'Fetch page by title. Returns content in the specified format.',
24
47
  inputSchema: {
25
48
  type: 'object',
26
- properties: {
49
+ properties: withMultiGraphParams({
27
50
  title: {
28
51
  type: 'string',
29
52
  description: 'Title of the page. For date pages, use ordinal date formats such as January 2nd, 2025'
@@ -34,7 +57,7 @@ export const toolSchemas = {
34
57
  default: 'raw',
35
58
  description: "Format output as markdown or JSON. 'markdown' returns as string; 'raw' returns JSON string of the page's blocks"
36
59
  }
37
- },
60
+ }),
38
61
  required: ['title']
39
62
  },
40
63
  },
@@ -43,7 +66,7 @@ export const toolSchemas = {
43
66
  description: '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:\n- Creating foundational concept pages that other pages will link to/from\n- Establishing new topic areas that need their own namespace\n- Setting up reference materials or documentation\n- Making permanent collections of information\n- Creating pages with mixed text and table content in one call.\n**Efficiency Tip:** This tool batches page and content creation efficiently. For adding content to existing pages, use `roam_process_batch_actions` instead.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
44
67
  inputSchema: {
45
68
  type: 'object',
46
- properties: {
69
+ properties: withMultiGraphParams({
47
70
  title: {
48
71
  type: 'string',
49
72
  description: 'Title of the new page',
@@ -104,7 +127,7 @@ export const toolSchemas = {
104
127
  required: ['level']
105
128
  }
106
129
  },
107
- },
130
+ }),
108
131
  required: ['title'],
109
132
  },
110
133
  },
@@ -113,7 +136,7 @@ export const toolSchemas = {
113
136
  description: '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:\n- Adding supplementary structured content to existing pages\n- Creating temporary or working outlines (meeting notes, brainstorms)\n- Organizing thoughts or research under a specific topic\n- Breaking down subtopics or components of a larger concept\nBest for simpler, contiguous hierarchical content. For complex nesting (e.g., tables) or granular control over block placement, consider `roam_process_batch_actions` instead.\n**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.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
114
137
  inputSchema: {
115
138
  type: 'object',
116
- properties: {
139
+ properties: withMultiGraphParams({
117
140
  page_title_uid: {
118
141
  type: 'string',
119
142
  description: 'Title or UID of the page (UID is preferred for accuracy). Leave blank to use the default daily page.'
@@ -153,7 +176,7 @@ export const toolSchemas = {
153
176
  required: ['text', 'level']
154
177
  }
155
178
  }
156
- },
179
+ }),
157
180
  required: ['outline']
158
181
  }
159
182
  },
@@ -162,7 +185,7 @@ export const toolSchemas = {
162
185
  description: '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.\n**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.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
163
186
  inputSchema: {
164
187
  type: 'object',
165
- properties: {
188
+ properties: withMultiGraphParams({
166
189
  content: {
167
190
  type: 'string',
168
191
  description: 'Nested markdown content to import'
@@ -189,7 +212,7 @@ export const toolSchemas = {
189
212
  enum: ['first', 'last'],
190
213
  default: 'first'
191
214
  }
192
- },
215
+ }),
193
216
  required: ['content']
194
217
  }
195
218
  },
@@ -198,7 +221,7 @@ export const toolSchemas = {
198
221
  description: '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. Use this tool to search for memories tagged with the MEMORIES_TAG.',
199
222
  inputSchema: {
200
223
  type: 'object',
201
- properties: {
224
+ properties: withMultiGraphParams({
202
225
  primary_tag: {
203
226
  type: 'string',
204
227
  description: 'The main tag to search for (without the [[ ]] brackets)',
@@ -226,7 +249,7 @@ export const toolSchemas = {
226
249
  description: 'Optional: The number of results to skip before returning matches. Useful for pagination. Defaults to 0.',
227
250
  default: 0
228
251
  }
229
- },
252
+ }),
230
253
  required: ['primary_tag']
231
254
  }
232
255
  },
@@ -235,7 +258,7 @@ export const toolSchemas = {
235
258
  description: 'Search for blocks with a specific status (TODO/DONE) across all pages or within a specific page.',
236
259
  inputSchema: {
237
260
  type: 'object',
238
- properties: {
261
+ properties: withMultiGraphParams({
239
262
  status: {
240
263
  type: 'string',
241
264
  description: 'Status to search for (TODO or DONE)',
@@ -253,7 +276,7 @@ export const toolSchemas = {
253
276
  type: 'string',
254
277
  description: 'Optional: Comma-separated list of terms to filter results by exclusion (matches content or page title)'
255
278
  }
256
- },
279
+ }),
257
280
  required: ['status']
258
281
  }
259
282
  },
@@ -262,7 +285,7 @@ export const toolSchemas = {
262
285
  description: '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.',
263
286
  inputSchema: {
264
287
  type: 'object',
265
- properties: {
288
+ properties: withMultiGraphParams({
266
289
  block_uid: {
267
290
  type: 'string',
268
291
  description: 'Optional: UID of the block to find references to (searches for ((uid)) patterns in text)'
@@ -275,7 +298,7 @@ export const toolSchemas = {
275
298
  type: 'string',
276
299
  description: 'Optional: Title or UID of the page to search in (UID is preferred for accuracy). If not provided, searches across all pages.'
277
300
  }
278
- }
301
+ })
279
302
  }
280
303
  },
281
304
  roam_search_hierarchy: {
@@ -283,7 +306,7 @@ export const toolSchemas = {
283
306
  description: 'Search for parent or child blocks in the block hierarchy. Can search up or down the hierarchy from a given block.',
284
307
  inputSchema: {
285
308
  type: 'object',
286
- properties: {
309
+ properties: withMultiGraphParams({
287
310
  parent_uid: {
288
311
  type: 'string',
289
312
  description: 'Optional: UID of the block to find children of'
@@ -302,7 +325,7 @@ export const toolSchemas = {
302
325
  minimum: 1,
303
326
  maximum: 10
304
327
  }
305
- }
328
+ })
306
329
  // Note: Validation for either parent_uid or child_uid is handled in the server code
307
330
  }
308
331
  },
@@ -311,7 +334,7 @@ export const toolSchemas = {
311
334
  description: 'Find pages that have been modified today (since midnight), with pagination and sorting options.',
312
335
  inputSchema: {
313
336
  type: 'object',
314
- properties: {
337
+ properties: withMultiGraphParams({
315
338
  limit: {
316
339
  type: 'integer',
317
340
  description: 'The maximum number of pages to retrieve (default: 50). Use -1 for no limit, but be aware that very large result sets can impact performance.',
@@ -328,7 +351,7 @@ export const toolSchemas = {
328
351
  enum: ['asc', 'desc'],
329
352
  default: 'desc'
330
353
  }
331
- }
354
+ })
332
355
  }
333
356
  },
334
357
  roam_search_by_text: {
@@ -336,7 +359,7 @@ export const toolSchemas = {
336
359
  description: 'Search for blocks containing specific text across all pages or within a specific page. This tool supports pagination via the `limit` and `offset` parameters.',
337
360
  inputSchema: {
338
361
  type: 'object',
339
- properties: {
362
+ properties: withMultiGraphParams({
340
363
  text: {
341
364
  type: 'string',
342
365
  description: 'The text to search for'
@@ -360,7 +383,7 @@ export const toolSchemas = {
360
383
  description: 'Optional: The number of results to skip before returning matches. Useful for pagination. Defaults to 0.',
361
384
  default: 0
362
385
  }
363
- },
386
+ }),
364
387
  required: ['text']
365
388
  }
366
389
  },
@@ -369,7 +392,7 @@ export const toolSchemas = {
369
392
  description: 'Search for blocks or pages based on creation or modification dates. Not for daily pages with ordinal date titles.',
370
393
  inputSchema: {
371
394
  type: 'object',
372
- properties: {
395
+ properties: withMultiGraphParams({
373
396
  start_date: {
374
397
  type: 'string',
375
398
  description: 'Start date in ISO format (YYYY-MM-DD)',
@@ -393,7 +416,7 @@ export const toolSchemas = {
393
416
  description: 'Whether to include the content of matching blocks/pages',
394
417
  default: true,
395
418
  }
396
- },
419
+ }),
397
420
  required: ['start_date', 'type', 'scope']
398
421
  }
399
422
  },
@@ -402,28 +425,41 @@ export const toolSchemas = {
402
425
  description: 'Provides the content of the Roam Markdown Cheatsheet resource, optionally concatenated with custom instructions if CUSTOM_INSTRUCTIONS_PATH is set.',
403
426
  inputSchema: {
404
427
  type: 'object',
405
- properties: {},
428
+ properties: withMultiGraphParams({}),
406
429
  required: [],
407
430
  },
408
431
  },
409
432
  roam_remember: {
410
433
  name: 'roam_remember',
411
- description: 'Add a memory or piece of information to remember, stored on the daily page with MEMORIES_TAG tag and optional categories. \nNOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use [alias]([[link]]) syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words).\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
434
+ description: 'Add a memory or piece of information to remember, stored on the daily page with MEMORIES_TAG tag and optional categories (unless include_memories_tag is false). \nNOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use [alias]([[link]]) syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words).\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
412
435
  inputSchema: {
413
436
  type: 'object',
414
- properties: {
437
+ properties: withMultiGraphParams({
415
438
  memory: {
416
439
  type: 'string',
417
- description: 'The memory detail or information to remember'
440
+ description: 'The memory detail or information to remember. Add tags in `categories`.'
418
441
  },
419
442
  categories: {
420
443
  type: 'array',
421
444
  items: {
422
445
  type: 'string'
423
446
  },
424
- description: 'Optional categories to tag the memory with (will be converted to Roam tags)'
447
+ description: 'Optional categories to tag the memory with (will be converted to Roam tags). Do not duplicate tags added in `memory` parameter.'
448
+ },
449
+ heading: {
450
+ type: 'string',
451
+ description: 'Optional 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.'
452
+ },
453
+ parent_uid: {
454
+ type: 'string',
455
+ description: 'Optional UID of a specific block to nest the memory under. Takes precedence over heading parameter.'
456
+ },
457
+ include_memories_tag: {
458
+ type: 'boolean',
459
+ description: 'Whether to append the MEMORIES_TAG tag to the memory block.',
460
+ default: true
425
461
  }
426
- },
462
+ }),
427
463
  required: ['memory']
428
464
  }
429
465
  },
@@ -432,7 +468,7 @@ export const toolSchemas = {
432
468
  description: 'Retrieve all stored memories on page titled MEMORIES_TAG, or tagged block content with the same name. Returns a combined, deduplicated list of memories. Optionally filter blcoks with a specific tag and sort by creation date.',
433
469
  inputSchema: {
434
470
  type: 'object',
435
- properties: {
471
+ properties: withMultiGraphParams({
436
472
  sort_by: {
437
473
  type: 'string',
438
474
  description: 'Sort order for memories based on creation date',
@@ -443,7 +479,7 @@ export const toolSchemas = {
443
479
  type: 'string',
444
480
  description: 'Include only memories with a specific filter tag. For single word tags use format "tag", for multi-word tags use format "tag word" (without brackets)'
445
481
  }
446
- }
482
+ })
447
483
  }
448
484
  },
449
485
  roam_datomic_query: {
@@ -451,7 +487,7 @@ export const toolSchemas = {
451
487
  description: '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.\n\n__Optimal Use Cases for `roam_datomic_query`:__\n- __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.\n- __Highly Complex Boolean Logic:__ Ideal for intricate combinations of "AND", "OR", and "NOT" conditions across multiple terms or attributes.\n- __Arbitrary Sorting Criteria:__ The go-to for highly customized sorting needs beyond default options.\n- __Proximity Search:__ For advanced search capabilities involving proximity, which are difficult to implement efficiently with simpler tools.\n\nList 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).\nPredicates (clojure.string/includes?, clojure.string/starts-with?, clojure.string/ends-with?, <, >, <=, >=, =, not=, !=).\nAggregates (distinct, count, sum, max, min, avg, limit).\nTips: 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.',
452
488
  inputSchema: {
453
489
  type: 'object',
454
- properties: {
490
+ properties: withMultiGraphParams({
455
491
  query: {
456
492
  type: 'string',
457
493
  description: 'The 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]`'
@@ -478,7 +514,7 @@ export const toolSchemas = {
478
514
  },
479
515
  description: 'Optional: 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.'
480
516
  }
481
- },
517
+ }),
482
518
  required: ['query']
483
519
  }
484
520
  },
@@ -487,7 +523,7 @@ export const toolSchemas = {
487
523
  description: '**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.\n\nExecutes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Actions are executed in the provided order.\n\n**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" } }`.\n\nFor 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.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
488
524
  inputSchema: {
489
525
  type: 'object',
490
- properties: {
526
+ properties: withMultiGraphParams({
491
527
  actions: {
492
528
  type: 'array',
493
529
  description: 'An array of action objects to execute in order.',
@@ -544,7 +580,7 @@ export const toolSchemas = {
544
580
  required: ['action']
545
581
  }
546
582
  }
547
- },
583
+ }),
548
584
  required: ['actions']
549
585
  }
550
586
  },
@@ -553,7 +589,7 @@ export const toolSchemas = {
553
589
  description: 'Fetch a block by its UID along with its hierarchical children down to a specified depth. Returns a nested object structure containing the block\'s UID, text, order, and an array of its children.',
554
590
  inputSchema: {
555
591
  type: 'object',
556
- properties: {
592
+ properties: withMultiGraphParams({
557
593
  block_uid: {
558
594
  type: 'string',
559
595
  description: 'The UID of the block to fetch.'
@@ -564,7 +600,7 @@ export const toolSchemas = {
564
600
  minimum: 0,
565
601
  maximum: 10
566
602
  }
567
- },
603
+ }),
568
604
  required: ['block_uid']
569
605
  },
570
606
  },
@@ -573,7 +609,7 @@ export const toolSchemas = {
573
609
  description: '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.\n\n**Why use this tool:**\n- Roam tables require precise nested block structures that are error-prone to create manually\n- Automatically handles the {{[[table]]}} container and nested column structure\n- Validates row/column consistency before execution\n- Converts empty cells to spaces (required by Roam)\n\n**Example:** A table with headers ["", "Column A", "Column B"] and rows [{label: "Row 1", cells: ["A1", "B1"]}] creates a 2x3 table.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
574
610
  inputSchema: {
575
611
  type: 'object',
576
- properties: {
612
+ properties: withMultiGraphParams({
577
613
  parent_uid: {
578
614
  type: 'string',
579
615
  description: 'The UID of the parent block or page where the table should be created.'
@@ -612,16 +648,39 @@ export const toolSchemas = {
612
648
  required: ['label', 'cells']
613
649
  }
614
650
  }
615
- },
651
+ }),
616
652
  required: ['parent_uid', 'headers', 'rows']
617
653
  }
618
654
  },
655
+ roam_move_block: {
656
+ name: 'roam_move_block',
657
+ description: '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.',
658
+ inputSchema: {
659
+ type: 'object',
660
+ properties: withMultiGraphParams({
661
+ block_uid: {
662
+ type: 'string',
663
+ description: 'The UID of the block to move'
664
+ },
665
+ parent_uid: {
666
+ type: 'string',
667
+ description: 'The UID of the new parent block or page'
668
+ },
669
+ order: {
670
+ type: ['integer', 'string'],
671
+ description: 'Position under the new parent. Can be a number (0-based index) or "first"/"last". Defaults to "last".',
672
+ default: 'last'
673
+ }
674
+ }),
675
+ required: ['block_uid', 'parent_uid']
676
+ }
677
+ },
619
678
  roam_update_page_markdown: {
620
679
  name: 'roam_update_page_markdown',
621
680
  description: 'Update an existing page with new markdown content using smart diff. Preserves block UIDs where possible and generates minimal changes. This is ideal for:\n- Syncing external markdown files to Roam\n- AI-assisted content updates that preserve references\n- Batch content modifications without losing block references\n\n**How it works:**\n1. Fetches existing page blocks\n2. Matches new content to existing blocks by text similarity\n3. Generates minimal create/update/move/delete operations\n4. Preserves UIDs for matched blocks (keeping references intact)\n\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
622
681
  inputSchema: {
623
682
  type: 'object',
624
- properties: {
683
+ properties: withMultiGraphParams({
625
684
  title: {
626
685
  type: 'string',
627
686
  description: 'Title of the page to update'
@@ -635,8 +694,30 @@ export const toolSchemas = {
635
694
  description: 'If true, returns the planned actions without executing them. Useful for previewing changes.',
636
695
  default: false
637
696
  }
638
- },
697
+ }),
639
698
  required: ['title', 'markdown']
640
699
  }
641
700
  },
701
+ roam_rename_page: {
702
+ name: 'roam_rename_page',
703
+ description: 'Rename a page by changing its title. Identifies the page by current title or UID.',
704
+ inputSchema: {
705
+ type: 'object',
706
+ properties: withMultiGraphParams({
707
+ old_title: {
708
+ type: 'string',
709
+ description: 'Current title of the page to rename (use this OR uid, not both)'
710
+ },
711
+ uid: {
712
+ type: 'string',
713
+ description: 'UID of the page to rename (use this OR old_title, not both)'
714
+ },
715
+ new_title: {
716
+ type: 'string',
717
+ description: 'New title for the page'
718
+ }
719
+ }),
720
+ required: ['new_title']
721
+ }
722
+ },
642
723
  };
@@ -39,6 +39,9 @@ export class ToolHandlers {
39
39
  async fetchBlockWithChildren(block_uid, depth) {
40
40
  return this.blockRetrievalOps.fetchBlockWithChildren(block_uid, depth);
41
41
  }
42
+ async moveBlock(block_uid, parent_uid, order = 'last') {
43
+ return this.blockOps.moveBlock(block_uid, parent_uid, order);
44
+ }
42
45
  // Search Operations
43
46
  async searchByStatus(status, page_title_uid, include, exclude) {
44
47
  return this.searchOps.searchByStatus(status, page_title_uid, include, exclude);
@@ -64,8 +67,8 @@ export class ToolHandlers {
64
67
  return handler.execute();
65
68
  }
66
69
  // Memory Operations
67
- async remember(memory, categories) {
68
- return this.memoryOps.remember(memory, categories);
70
+ async remember(memory, categories, heading, parent_uid, include_memories_tag) {
71
+ return this.memoryOps.remember(memory, categories, heading, parent_uid, include_memories_tag);
69
72
  }
70
73
  async recall(sort_by = 'newest', filter_tag) {
71
74
  return this.memoryOps.recall(sort_by, filter_tag);
@@ -93,6 +96,10 @@ export class ToolHandlers {
93
96
  async updatePageMarkdown(title, markdown, dryRun = false) {
94
97
  return this.pageOps.updatePageMarkdown(title, markdown, dryRun);
95
98
  }
99
+ // Page Rename
100
+ async renamePage(params) {
101
+ return this.pageOps.renamePage(params);
102
+ }
96
103
  async getRoamMarkdownCheatsheet() {
97
104
  if (this.cachedCheatsheet) {
98
105
  return this.cachedCheatsheet;
@@ -17,3 +17,25 @@ export function formatRoamDate(date) {
17
17
  const year = date.getFullYear();
18
18
  return `${month} ${day}${getOrdinalSuffix(day)}, ${year}`;
19
19
  }
20
+ /**
21
+ * Resolve relative date keywords to Roam date format.
22
+ * Returns the original string if not a recognized keyword.
23
+ */
24
+ export function resolveRelativeDate(input) {
25
+ const lower = input.toLowerCase().trim();
26
+ const today = new Date();
27
+ switch (lower) {
28
+ case 'today':
29
+ return formatRoamDate(today);
30
+ case 'yesterday':
31
+ const yesterday = new Date(today);
32
+ yesterday.setDate(today.getDate() - 1);
33
+ return formatRoamDate(yesterday);
34
+ case 'tomorrow':
35
+ const tomorrow = new Date(today);
36
+ tomorrow.setDate(today.getDate() + 1);
37
+ return formatRoamDate(tomorrow);
38
+ default:
39
+ return input;
40
+ }
41
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "roam-research-mcp",
3
- "version": "1.6.0",
4
- "description": "A Model Context Protocol (MCP) server for Roam Research API integration",
3
+ "version": "2.4.3",
4
+ "description": "MCP server and CLI for Roam Research",
5
5
  "private": false,
6
6
  "repository": {
7
7
  "type": "git",
@@ -35,9 +35,11 @@
35
35
  "inspector": "npx @modelcontextprotocol/inspector build/index.js",
36
36
  "start": "node build/index.js",
37
37
  "prepublishOnly": "npm run clean && npm run build",
38
- "release:patch": "npm version patch && git push origin v$(node -p \"require('./package.json').version\")",
39
- "release:minor": "npm version minor && git push origin v$(node -p \"require('./package.json').version\")",
40
- "release:major": "npm version major && git push origin v$(node -p \"require('./package.json').version\")",
38
+ "release": "standard-version",
39
+ "release:patch": "standard-version --release-as patch",
40
+ "release:minor": "standard-version --release-as minor",
41
+ "release:major": "standard-version --release-as major",
42
+ "release:first": "standard-version --first-release",
41
43
  "test": "vitest run",
42
44
  "test:watch": "vitest"
43
45
  },
@@ -49,6 +51,7 @@
49
51
  },
50
52
  "devDependencies": {
51
53
  "@types/node": "^20.11.24",
54
+ "standard-version": "^9.5.0",
52
55
  "ts-node": "^10.9.2",
53
56
  "typescript": "^5.3.3",
54
57
  "vitest": "^3.2.4"