roam-research-mcp 1.0.0 → 1.3.2
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 +84 -17
- package/build/Roam_Markdown_Cheatsheet.md +519 -175
- package/build/cache/page-uid-cache.js +55 -0
- package/build/cli/import-markdown.js +98 -0
- package/build/config/environment.js +4 -2
- package/build/markdown-utils.js +51 -5
- package/build/server/roam-server.js +69 -10
- package/build/shared/errors.js +84 -0
- package/build/shared/index.js +5 -0
- package/build/shared/validation.js +268 -0
- package/build/tools/operations/batch.js +165 -3
- package/build/tools/operations/memory.js +29 -19
- package/build/tools/operations/outline.js +110 -70
- package/build/tools/operations/pages.js +159 -60
- package/build/tools/operations/table.js +142 -0
- package/build/tools/schemas.js +87 -9
- package/build/tools/tool-handlers.js +8 -2
- package/package.json +4 -3
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { BatchOperations } from './batch.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates table input before building actions.
|
|
4
|
+
*/
|
|
5
|
+
export function validateTableInput(input) {
|
|
6
|
+
const errors = [];
|
|
7
|
+
if (!input.parent_uid) {
|
|
8
|
+
errors.push({ field: 'parent_uid', message: 'parent_uid is required' });
|
|
9
|
+
}
|
|
10
|
+
if (!input.headers || !Array.isArray(input.headers)) {
|
|
11
|
+
errors.push({ field: 'headers', message: 'headers must be an array' });
|
|
12
|
+
}
|
|
13
|
+
else if (input.headers.length === 0) {
|
|
14
|
+
errors.push({ field: 'headers', message: 'At least one header is required' });
|
|
15
|
+
}
|
|
16
|
+
if (!input.rows || !Array.isArray(input.rows)) {
|
|
17
|
+
errors.push({ field: 'rows', message: 'rows must be an array' });
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
const expectedCells = (input.headers?.length || 1) - 1;
|
|
21
|
+
for (let i = 0; i < input.rows.length; i++) {
|
|
22
|
+
const row = input.rows[i];
|
|
23
|
+
if (!row.label && row.label !== '') {
|
|
24
|
+
errors.push({
|
|
25
|
+
field: `rows[${i}].label`,
|
|
26
|
+
message: 'Row label is required (use empty string for blank)'
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (!Array.isArray(row.cells)) {
|
|
30
|
+
errors.push({
|
|
31
|
+
field: `rows[${i}].cells`,
|
|
32
|
+
message: 'Row cells must be an array'
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else if (row.cells.length !== expectedCells) {
|
|
36
|
+
errors.push({
|
|
37
|
+
field: `rows[${i}].cells`,
|
|
38
|
+
message: `Expected ${expectedCells} cells, got ${row.cells.length}`
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { valid: errors.length === 0, errors };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Builds batch actions for creating a Roam table structure.
|
|
47
|
+
*
|
|
48
|
+
* Roam tables have a specific nested structure:
|
|
49
|
+
* - The table container block contains {{[[table]]}}
|
|
50
|
+
* - Header row is nested deeply (each column nested under the previous)
|
|
51
|
+
* - Data rows follow the same nesting pattern
|
|
52
|
+
*/
|
|
53
|
+
export function buildTableActions(input) {
|
|
54
|
+
const actions = [];
|
|
55
|
+
// Create table container
|
|
56
|
+
actions.push({
|
|
57
|
+
action: 'create-block',
|
|
58
|
+
uid: '{{uid:table}}',
|
|
59
|
+
string: '{{[[table]]}}',
|
|
60
|
+
location: { 'parent-uid': input.parent_uid, order: input.order ?? 'last' }
|
|
61
|
+
});
|
|
62
|
+
// Create header row with nested structure
|
|
63
|
+
// In Roam tables, each column is nested under the previous column
|
|
64
|
+
let headerParent = '{{uid:table}}';
|
|
65
|
+
for (let i = 0; i < input.headers.length; i++) {
|
|
66
|
+
const uid = `{{uid:header_${i}}}`;
|
|
67
|
+
const headerText = input.headers[i] || ' '; // Convert empty to space
|
|
68
|
+
actions.push({
|
|
69
|
+
action: 'create-block',
|
|
70
|
+
uid,
|
|
71
|
+
string: headerText,
|
|
72
|
+
location: { 'parent-uid': headerParent, order: 0 }
|
|
73
|
+
});
|
|
74
|
+
headerParent = uid;
|
|
75
|
+
}
|
|
76
|
+
// Create data rows
|
|
77
|
+
// Each row starts as a child of the table, with cells nested under each other
|
|
78
|
+
for (let rowIdx = 0; rowIdx < input.rows.length; rowIdx++) {
|
|
79
|
+
const row = input.rows[rowIdx];
|
|
80
|
+
// Row label (first column) - child of table at position rowIdx + 1 (after header)
|
|
81
|
+
const labelUid = `{{uid:row_${rowIdx}_label}}`;
|
|
82
|
+
const labelText = row.label || ' '; // Convert empty to space
|
|
83
|
+
actions.push({
|
|
84
|
+
action: 'create-block',
|
|
85
|
+
uid: labelUid,
|
|
86
|
+
string: labelText,
|
|
87
|
+
location: { 'parent-uid': '{{uid:table}}', order: rowIdx + 1 }
|
|
88
|
+
});
|
|
89
|
+
// Row cells - each cell is nested under the previous
|
|
90
|
+
let cellParent = labelUid;
|
|
91
|
+
for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx++) {
|
|
92
|
+
const cellUid = `{{uid:row_${rowIdx}_cell_${cellIdx}}}`;
|
|
93
|
+
const cellText = row.cells[cellIdx] || ' '; // Convert empty to space
|
|
94
|
+
actions.push({
|
|
95
|
+
action: 'create-block',
|
|
96
|
+
uid: cellUid,
|
|
97
|
+
string: cellText,
|
|
98
|
+
location: { 'parent-uid': cellParent, order: 0 }
|
|
99
|
+
});
|
|
100
|
+
cellParent = cellUid;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return actions;
|
|
104
|
+
}
|
|
105
|
+
export class TableOperations {
|
|
106
|
+
constructor(graph) {
|
|
107
|
+
this.batchOps = new BatchOperations(graph);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Creates a table in Roam with the specified headers and rows.
|
|
111
|
+
*
|
|
112
|
+
* @param input Table configuration including parent_uid, headers, and rows
|
|
113
|
+
* @returns Result including success status and table block UID
|
|
114
|
+
*/
|
|
115
|
+
async createTable(input) {
|
|
116
|
+
// Validate input
|
|
117
|
+
const validation = validateTableInput(input);
|
|
118
|
+
if (!validation.valid) {
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
error: {
|
|
122
|
+
code: 'VALIDATION_ERROR',
|
|
123
|
+
message: validation.errors.map(e => `[${e.field}] ${e.message}`).join('; ')
|
|
124
|
+
},
|
|
125
|
+
validation_passed: false,
|
|
126
|
+
actions_attempted: 0
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Build table actions
|
|
130
|
+
const actions = buildTableActions(input);
|
|
131
|
+
// Execute batch
|
|
132
|
+
const result = await this.batchOps.processBatch(actions);
|
|
133
|
+
// Add table_uid if successful
|
|
134
|
+
if (result.success && result.uid_map) {
|
|
135
|
+
return {
|
|
136
|
+
...result,
|
|
137
|
+
table_uid: result.uid_map['table']
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
}
|
package/build/tools/schemas.js
CHANGED
|
@@ -40,7 +40,7 @@ export const toolSchemas = {
|
|
|
40
40
|
},
|
|
41
41
|
roam_create_page: {
|
|
42
42
|
name: 'roam_create_page',
|
|
43
|
-
description: 'Create a new standalone page in Roam with optional content, including structured outlines, 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.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
|
|
43
|
+
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
44
|
inputSchema: {
|
|
45
45
|
type: 'object',
|
|
46
46
|
properties: {
|
|
@@ -50,28 +50,58 @@ export const toolSchemas = {
|
|
|
50
50
|
},
|
|
51
51
|
content: {
|
|
52
52
|
type: 'array',
|
|
53
|
-
description: 'Initial content for the page as an array of
|
|
53
|
+
description: 'Initial content for the page as an array of content items. Each item can be a text block or a table. Text blocks use {text, level, heading?}. Tables use {type: "table", headers, rows}. Items are processed in order.',
|
|
54
54
|
items: {
|
|
55
55
|
type: 'object',
|
|
56
56
|
properties: {
|
|
57
|
+
type: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
enum: ['text', 'table'],
|
|
60
|
+
description: 'Content type: "text" for regular blocks (default), "table" for tables',
|
|
61
|
+
default: 'text'
|
|
62
|
+
},
|
|
57
63
|
text: {
|
|
58
64
|
type: 'string',
|
|
59
|
-
description: 'Content of the block'
|
|
65
|
+
description: 'Content of the block (for type: "text")'
|
|
60
66
|
},
|
|
61
67
|
level: {
|
|
62
68
|
type: 'integer',
|
|
63
|
-
description: 'Indentation level (1-10, where 1 is top level)',
|
|
69
|
+
description: 'Indentation level (1-10, where 1 is top level). For tables, this should always be 1.',
|
|
64
70
|
minimum: 1,
|
|
65
71
|
maximum: 10
|
|
66
72
|
},
|
|
67
73
|
heading: {
|
|
68
74
|
type: 'integer',
|
|
69
|
-
description: 'Optional: Heading formatting for this block (1-3)',
|
|
75
|
+
description: 'Optional: Heading formatting for this block (1-3). Only for type: "text".',
|
|
70
76
|
minimum: 1,
|
|
71
77
|
maximum: 3
|
|
78
|
+
},
|
|
79
|
+
headers: {
|
|
80
|
+
type: 'array',
|
|
81
|
+
description: 'Column headers for the table (for type: "table"). First header is typically empty for row labels.',
|
|
82
|
+
items: { type: 'string' }
|
|
83
|
+
},
|
|
84
|
+
rows: {
|
|
85
|
+
type: 'array',
|
|
86
|
+
description: 'Data rows for the table (for type: "table"). Each row has a label and cells.',
|
|
87
|
+
items: {
|
|
88
|
+
type: 'object',
|
|
89
|
+
properties: {
|
|
90
|
+
label: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description: 'The row label (first column content). Use empty string for blank.'
|
|
93
|
+
},
|
|
94
|
+
cells: {
|
|
95
|
+
type: 'array',
|
|
96
|
+
description: 'Cell values for this row. Must have exactly (headers.length - 1) items.',
|
|
97
|
+
items: { type: 'string' }
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
required: ['label', 'cells']
|
|
101
|
+
}
|
|
72
102
|
}
|
|
73
103
|
},
|
|
74
|
-
required: ['
|
|
104
|
+
required: ['level']
|
|
75
105
|
}
|
|
76
106
|
},
|
|
77
107
|
},
|
|
@@ -80,7 +110,7 @@ export const toolSchemas = {
|
|
|
80
110
|
},
|
|
81
111
|
roam_create_outline: {
|
|
82
112
|
name: 'roam_create_outline',
|
|
83
|
-
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.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
|
|
113
|
+
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.',
|
|
84
114
|
inputSchema: {
|
|
85
115
|
type: 'object',
|
|
86
116
|
properties: {
|
|
@@ -129,7 +159,7 @@ export const toolSchemas = {
|
|
|
129
159
|
},
|
|
130
160
|
roam_import_markdown: {
|
|
131
161
|
name: 'roam_import_markdown',
|
|
132
|
-
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.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
|
|
162
|
+
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.',
|
|
133
163
|
inputSchema: {
|
|
134
164
|
type: 'object',
|
|
135
165
|
properties: {
|
|
@@ -450,7 +480,7 @@ export const toolSchemas = {
|
|
|
450
480
|
},
|
|
451
481
|
roam_process_batch_actions: {
|
|
452
482
|
name: 'roam_process_batch_actions',
|
|
453
|
-
description: '
|
|
483
|
+
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.',
|
|
454
484
|
inputSchema: {
|
|
455
485
|
type: 'object',
|
|
456
486
|
properties: {
|
|
@@ -534,4 +564,52 @@ export const toolSchemas = {
|
|
|
534
564
|
required: ['block_uid']
|
|
535
565
|
},
|
|
536
566
|
},
|
|
567
|
+
roam_create_table: {
|
|
568
|
+
name: 'roam_create_table',
|
|
569
|
+
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.',
|
|
570
|
+
inputSchema: {
|
|
571
|
+
type: 'object',
|
|
572
|
+
properties: {
|
|
573
|
+
parent_uid: {
|
|
574
|
+
type: 'string',
|
|
575
|
+
description: 'The UID of the parent block or page where the table should be created.'
|
|
576
|
+
},
|
|
577
|
+
order: {
|
|
578
|
+
type: ['integer', 'string'],
|
|
579
|
+
description: 'Optional: Position under the parent. Can be a number (0-based) or "first"/"last". Defaults to "last".',
|
|
580
|
+
default: 'last'
|
|
581
|
+
},
|
|
582
|
+
headers: {
|
|
583
|
+
type: 'array',
|
|
584
|
+
description: 'Column headers for the table. The first header is typically empty (for the row label column). Example: ["", "Option A", "Option B"]',
|
|
585
|
+
items: {
|
|
586
|
+
type: 'string'
|
|
587
|
+
},
|
|
588
|
+
minItems: 1
|
|
589
|
+
},
|
|
590
|
+
rows: {
|
|
591
|
+
type: 'array',
|
|
592
|
+
description: 'Data rows for the table. Each row has a label (first column) and cells (remaining columns).',
|
|
593
|
+
items: {
|
|
594
|
+
type: 'object',
|
|
595
|
+
properties: {
|
|
596
|
+
label: {
|
|
597
|
+
type: 'string',
|
|
598
|
+
description: 'The row label (first column content). Use empty string for blank.'
|
|
599
|
+
},
|
|
600
|
+
cells: {
|
|
601
|
+
type: 'array',
|
|
602
|
+
description: 'Cell values for this row. Must have exactly (headers.length - 1) items.',
|
|
603
|
+
items: {
|
|
604
|
+
type: 'string'
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
required: ['label', 'cells']
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
required: ['parent_uid', 'headers', 'rows']
|
|
613
|
+
}
|
|
614
|
+
},
|
|
537
615
|
};
|
|
@@ -3,12 +3,13 @@ import * as path from 'path';
|
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { PageOperations } from './operations/pages.js';
|
|
5
5
|
import { BlockOperations } from './operations/blocks.js';
|
|
6
|
-
import { BlockRetrievalOperations } from './operations/block-retrieval.js';
|
|
6
|
+
import { BlockRetrievalOperations } from './operations/block-retrieval.js';
|
|
7
7
|
import { SearchOperations } from './operations/search/index.js';
|
|
8
8
|
import { MemoryOperations } from './operations/memory.js';
|
|
9
9
|
import { TodoOperations } from './operations/todos.js';
|
|
10
10
|
import { OutlineOperations } from './operations/outline.js';
|
|
11
11
|
import { BatchOperations } from './operations/batch.js';
|
|
12
|
+
import { TableOperations } from './operations/table.js';
|
|
12
13
|
import { DatomicSearchHandlerImpl } from './operations/search/handlers.js';
|
|
13
14
|
export class ToolHandlers {
|
|
14
15
|
constructor(graph) {
|
|
@@ -16,12 +17,13 @@ export class ToolHandlers {
|
|
|
16
17
|
this.cachedCheatsheet = null;
|
|
17
18
|
this.pageOps = new PageOperations(graph);
|
|
18
19
|
this.blockOps = new BlockOperations(graph);
|
|
19
|
-
this.blockRetrievalOps = new BlockRetrievalOperations(graph);
|
|
20
|
+
this.blockRetrievalOps = new BlockRetrievalOperations(graph);
|
|
20
21
|
this.searchOps = new SearchOperations(graph);
|
|
21
22
|
this.memoryOps = new MemoryOperations(graph);
|
|
22
23
|
this.todoOps = new TodoOperations(graph);
|
|
23
24
|
this.outlineOps = new OutlineOperations(graph);
|
|
24
25
|
this.batchOps = new BatchOperations(graph);
|
|
26
|
+
this.tableOps = new TableOperations(graph);
|
|
25
27
|
}
|
|
26
28
|
// Page Operations
|
|
27
29
|
async findPagesModifiedToday(limit = 50, offset = 0, sort_order = 'desc') {
|
|
@@ -83,6 +85,10 @@ export class ToolHandlers {
|
|
|
83
85
|
async processBatch(actions) {
|
|
84
86
|
return this.batchOps.processBatch(actions);
|
|
85
87
|
}
|
|
88
|
+
// Table Operations
|
|
89
|
+
async createTable(input) {
|
|
90
|
+
return this.tableOps.createTable(input);
|
|
91
|
+
}
|
|
86
92
|
async getRoamMarkdownCheatsheet() {
|
|
87
93
|
if (this.cachedCheatsheet) {
|
|
88
94
|
return this.cachedCheatsheet;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roam-research-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "A Model Context Protocol (MCP) server for Roam Research API integration",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
@@ -22,13 +22,14 @@
|
|
|
22
22
|
"homepage": "https://github.com/2b3pro/roam-research-mcp#readme",
|
|
23
23
|
"type": "module",
|
|
24
24
|
"bin": {
|
|
25
|
-
"roam-research-mcp": "
|
|
25
|
+
"roam-research-mcp": "build/index.js",
|
|
26
|
+
"roam-import": "build/cli/import-markdown.js"
|
|
26
27
|
},
|
|
27
28
|
"files": [
|
|
28
29
|
"build"
|
|
29
30
|
],
|
|
30
31
|
"scripts": {
|
|
31
|
-
"build": "echo \"Using custom instructions: .roam/${CUSTOM_INSTRUCTIONS_PREFIX}custom-instructions.md\" && tsc && cat Roam_Markdown_Cheatsheet.md .roam/${CUSTOM_INSTRUCTIONS_PREFIX}custom-instructions.md > build/Roam_Markdown_Cheatsheet.md && chmod 755 build/index.js",
|
|
32
|
+
"build": "echo \"Using custom instructions: .roam/${CUSTOM_INSTRUCTIONS_PREFIX}custom-instructions.md\" && tsc && cat Roam_Markdown_Cheatsheet.md .roam/${CUSTOM_INSTRUCTIONS_PREFIX}custom-instructions.md > build/Roam_Markdown_Cheatsheet.md && chmod 755 build/index.js build/cli/import-markdown.js",
|
|
32
33
|
"clean": "rm -rf build",
|
|
33
34
|
"watch": "tsc --watch",
|
|
34
35
|
"inspector": "npx @modelcontextprotocol/inspector build/index.js",
|