roam-research-mcp 0.24.2 → 0.24.5
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.
|
@@ -17,7 +17,7 @@ export class RoamServer {
|
|
|
17
17
|
this.toolHandlers = new ToolHandlers(this.graph);
|
|
18
18
|
this.server = new Server({
|
|
19
19
|
name: 'roam-research',
|
|
20
|
-
version: '0.24.
|
|
20
|
+
version: '0.24.5',
|
|
21
21
|
}, {
|
|
22
22
|
capabilities: {
|
|
23
23
|
tools: {
|
|
@@ -36,7 +36,7 @@ export class RoamServer {
|
|
|
36
36
|
roam_find_pages_modified_today: {},
|
|
37
37
|
roam_search_by_text: {},
|
|
38
38
|
roam_update_block: {},
|
|
39
|
-
|
|
39
|
+
roam_update_multiple_blocks: {},
|
|
40
40
|
roam_search_by_date: {},
|
|
41
41
|
roam_datomic_query: {}
|
|
42
42
|
},
|
|
@@ -137,7 +137,8 @@ export class RoamServer {
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
case 'roam_find_pages_modified_today': {
|
|
140
|
-
const
|
|
140
|
+
const { max_num_pages } = request.params.arguments;
|
|
141
|
+
const result = await this.toolHandlers.findPagesModifiedToday(max_num_pages || 50);
|
|
141
142
|
return {
|
|
142
143
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
143
144
|
};
|
|
@@ -179,7 +180,7 @@ export class RoamServer {
|
|
|
179
180
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
180
181
|
};
|
|
181
182
|
}
|
|
182
|
-
case '
|
|
183
|
+
case 'roam_update_multiple_blocks': {
|
|
183
184
|
const { updates } = request.params.arguments;
|
|
184
185
|
const result = await this.toolHandlers.updateBlocks(updates);
|
|
185
186
|
return {
|
|
@@ -159,6 +159,10 @@ export class OutlineOperations {
|
|
|
159
159
|
return createAndVerifyBlock(content, parentUid, maxRetries, initialDelay, true);
|
|
160
160
|
}
|
|
161
161
|
};
|
|
162
|
+
// Helper function to check if string is a valid Roam UID (9 characters)
|
|
163
|
+
const isValidUid = (str) => {
|
|
164
|
+
return typeof str === 'string' && str.length === 9;
|
|
165
|
+
};
|
|
162
166
|
// Get or create the parent block
|
|
163
167
|
let targetParentUid;
|
|
164
168
|
if (!block_text_uid) {
|
|
@@ -166,12 +170,28 @@ export class OutlineOperations {
|
|
|
166
170
|
}
|
|
167
171
|
else {
|
|
168
172
|
try {
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
if (isValidUid(block_text_uid)) {
|
|
174
|
+
// First try to find block by UID
|
|
175
|
+
const uidQuery = `[:find ?uid
|
|
176
|
+
:where [?e :block/uid "${block_text_uid}"]
|
|
177
|
+
[?e :block/uid ?uid]]`;
|
|
178
|
+
const uidResult = await q(this.graph, uidQuery, []);
|
|
179
|
+
if (uidResult && uidResult.length > 0) {
|
|
180
|
+
// Use existing block if found
|
|
181
|
+
targetParentUid = uidResult[0][0];
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
throw new McpError(ErrorCode.InvalidRequest, `Block with UID "${block_text_uid}" not found`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Create header block and get its UID if not a valid UID
|
|
189
|
+
targetParentUid = await createAndVerifyBlock(block_text_uid, targetPageUid);
|
|
190
|
+
}
|
|
171
191
|
}
|
|
172
192
|
catch (error) {
|
|
173
193
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
174
|
-
throw new McpError(ErrorCode.InternalError, `Failed to create
|
|
194
|
+
throw new McpError(ErrorCode.InternalError, `Failed to ${isValidUid(block_text_uid) ? 'find' : 'create'} block "${block_text_uid}": ${errorMessage}`);
|
|
175
195
|
}
|
|
176
196
|
}
|
|
177
197
|
// Initialize result variable
|
|
@@ -8,7 +8,7 @@ export class PageOperations {
|
|
|
8
8
|
constructor(graph) {
|
|
9
9
|
this.graph = graph;
|
|
10
10
|
}
|
|
11
|
-
async findPagesModifiedToday(
|
|
11
|
+
async findPagesModifiedToday(max_num_pages = 50) {
|
|
12
12
|
// Define ancestor rule for traversing block hierarchy
|
|
13
13
|
const ancestorRule = `[
|
|
14
14
|
[ (ancestor ?b ?a)
|
|
@@ -29,7 +29,7 @@ export class PageOperations {
|
|
|
29
29
|
(ancestor ?block ?page)
|
|
30
30
|
[?block :edit/time ?time]
|
|
31
31
|
[(> ?time ?start_of_day)]]
|
|
32
|
-
:limit ${
|
|
32
|
+
:limit ${max_num_pages}`, [startOfDay.getTime(), ancestorRule]);
|
|
33
33
|
if (!results || results.length === 0) {
|
|
34
34
|
return {
|
|
35
35
|
success: true,
|
package/build/tools/schemas.js
CHANGED
|
@@ -20,13 +20,13 @@ export const toolSchemas = {
|
|
|
20
20
|
},
|
|
21
21
|
roam_fetch_page_by_title: {
|
|
22
22
|
name: 'roam_fetch_page_by_title',
|
|
23
|
-
description: 'Retrieve complete page contents by exact title, including all nested blocks and resolved block references. Use for reading and analyzing existing Roam pages.',
|
|
23
|
+
description: 'Retrieve complete page contents by exact title, including all nested blocks and resolved block references. Use for accessing daily pages, reading and analyzing existing Roam pages.',
|
|
24
24
|
inputSchema: {
|
|
25
25
|
type: 'object',
|
|
26
26
|
properties: {
|
|
27
27
|
title: {
|
|
28
28
|
type: 'string',
|
|
29
|
-
description: 'Title of the page
|
|
29
|
+
description: 'Title of the page. For date pages, use ordinal date formats such as January 2nd, 2025',
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
32
|
required: ['title'],
|
|
@@ -249,13 +249,12 @@ export const toolSchemas = {
|
|
|
249
249
|
inputSchema: {
|
|
250
250
|
type: 'object',
|
|
251
251
|
properties: {
|
|
252
|
-
|
|
252
|
+
max_num_pages: {
|
|
253
253
|
type: 'integer',
|
|
254
|
-
description: '
|
|
255
|
-
default:
|
|
254
|
+
description: 'Max number of pages to retrieve (default: 50)',
|
|
255
|
+
default: 50
|
|
256
256
|
},
|
|
257
|
-
}
|
|
258
|
-
required: ['num_pages']
|
|
257
|
+
}
|
|
259
258
|
}
|
|
260
259
|
},
|
|
261
260
|
roam_search_by_text: {
|
|
@@ -278,7 +277,7 @@ export const toolSchemas = {
|
|
|
278
277
|
},
|
|
279
278
|
roam_update_block: {
|
|
280
279
|
name: 'roam_update_block',
|
|
281
|
-
description: 'Update
|
|
280
|
+
description: 'Update a single block identified by its UID. Use this for individual block updates when you need to either replace the entire content or apply a transform pattern to modify specific parts of the content.\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).',
|
|
282
281
|
inputSchema: {
|
|
283
282
|
type: 'object',
|
|
284
283
|
properties: {
|
|
@@ -318,9 +317,9 @@ export const toolSchemas = {
|
|
|
318
317
|
]
|
|
319
318
|
}
|
|
320
319
|
},
|
|
321
|
-
|
|
322
|
-
name: '
|
|
323
|
-
description: '
|
|
320
|
+
roam_update_multiple_blocks: {
|
|
321
|
+
name: 'roam_update_multiple_blocks',
|
|
322
|
+
description: 'Efficiently update multiple blocks in a single batch operation. Use this when you need to update several blocks at once to avoid making multiple separate API calls. Each block in the batch can independently either have its content replaced or transformed using a pattern.\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).',
|
|
324
323
|
inputSchema: {
|
|
325
324
|
type: 'object',
|
|
326
325
|
properties: {
|
|
@@ -372,7 +371,7 @@ export const toolSchemas = {
|
|
|
372
371
|
},
|
|
373
372
|
roam_search_by_date: {
|
|
374
373
|
name: 'roam_search_by_date',
|
|
375
|
-
description: 'Search for blocks or pages based on creation or modification dates',
|
|
374
|
+
description: 'Search for blocks or pages based on creation or modification dates. Not for daily pages with ordinal date titles.',
|
|
376
375
|
inputSchema: {
|
|
377
376
|
type: 'object',
|
|
378
377
|
properties: {
|
|
@@ -23,8 +23,8 @@ export class ToolHandlers {
|
|
|
23
23
|
this.outlineOps = new OutlineOperations(graph);
|
|
24
24
|
}
|
|
25
25
|
// Page Operations
|
|
26
|
-
async findPagesModifiedToday(
|
|
27
|
-
return this.pageOps.findPagesModifiedToday(
|
|
26
|
+
async findPagesModifiedToday(max_num_pages = 50) {
|
|
27
|
+
return this.pageOps.findPagesModifiedToday(max_num_pages);
|
|
28
28
|
}
|
|
29
29
|
async createPage(title, content) {
|
|
30
30
|
return this.pageOps.createPage(title, content);
|