roam-research-mcp 0.25.5 → 0.25.7

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 CHANGED
@@ -26,12 +26,42 @@ npm install
26
26
  npm run build
27
27
  ```
28
28
 
29
- ## To Test
29
+ ## Docker
30
+
31
+ This project can be easily containerized using Docker. A `Dockerfile` is provided at the root of the repository.
32
+
33
+ ### Build the Docker Image
30
34
 
31
- Run [MCP Inspector](https://github.com/modelcontextprotocol/inspector) after build…
35
+ To build the Docker image, navigate to the project root and run:
32
36
 
37
+ ```bash
38
+ docker build -t roam-research-mcp .
33
39
  ```
34
- npx @modelcontextprotocol/inspector node build/index.js
40
+
41
+ ### Run the Docker Container
42
+
43
+ To run the Docker container and map port 3000 (if your application uses it), you must also provide the necessary environment variables. Use the `-e` flag to pass `ROAM_API_TOKEN`, `ROAM_GRAPH_NAME`, and optionally `MEMORIES_TAG`:
44
+
45
+ ```bash
46
+ docker run -p 3000:3000 \
47
+ -e ROAM_API_TOKEN="your-api-token" \
48
+ -e ROAM_GRAPH_NAME="your-graph-name" \
49
+ -e MEMORIES_TAG="#[[LLM/Memories]]" \
50
+ roam-research-mcp
51
+ ```
52
+
53
+ Alternatively, if you have a `.env` file in the project root (which is copied into the Docker image during build), you can use the `--env-file` flag:
54
+
55
+ ```bash
56
+ docker run -p 3000:3000 --env-file .env roam-research-mcp
57
+ ```
58
+
59
+ ## To Test
60
+
61
+ Run [MCP Inspector](https://github.com/modelcontextprotocol/inspector) after build using the provided npm script:
62
+
63
+ ```bash
64
+ npm run inspector
35
65
  ```
36
66
 
37
67
  ## Features
@@ -48,22 +78,22 @@ The server provides powerful tools for interacting with Roam Research:
48
78
  - Efficient batch operations
49
79
  - Hierarchical outline creation
50
80
 
51
- 1. `roam_fetch_page_by_title`: Fetch and read a page's content by title, recursively resolving block references up to 4 levels deep
52
- 2. `roam_create_page`: Create new pages with optional content
53
- 3. `roam_create_block`: Create new blocks in a page (defaults to today's daily page)
54
- 4. `roam_import_markdown`: Import nested markdown content under specific blocks
55
- 5. `roam_add_todo`: Add multiple todo items to today's daily page with checkbox syntax
56
- 6. `roam_create_outline`: Create hierarchical outlines with proper nesting and structure
57
- 7. `roam_search_block_refs`: Search for block references within pages or across the graph
58
- 8. `roam_search_hierarchy`: Navigate and search through block parent-child relationships
59
- 9. `roam_find_pages_modified_today`: Find all pages that have been modified since midnight today
60
- 10. `roam_search_by_text`: Search for blocks containing specific text across all pages or within a specific page
61
- 11. `roam_update_block`: Update block content with direct text or pattern-based transformations
62
- 12. `roam_search_by_date`: Search for blocks and pages based on creation or modification dates
63
- 13. `roam_search_for_tag`: Search for blocks containing specific tags with optional filtering by nearby tags
64
- 14. `roam_remember`: Store and categorize memories or information with automatic tagging
65
- 15. `roam_recall`: Recall memories of blocks marked with tag MEMORIES_TAG (see below) or blocks on page title of the same name
66
- 16. `roam_datomic_query`: Execute custom Datalog queries on the Roam graph for advanced data retrieval and analysis
81
+ 1. `roam_fetch_page_by_title`: Fetch page content by title.
82
+ 2. `roam_create_page`: Create new pages with optional content and headings.
83
+ 3. `roam_create_block`: Add new blocks to an existing page or today's daily note.
84
+ 4. `roam_import_markdown`: Import nested markdown content under a specific block.
85
+ 5. `roam_add_todo`: Add a list of todo items to today's daily page.
86
+ 6. `roam_create_outline`: Add a structured outline to an existing page or block.
87
+ 7. `roam_search_block_refs`: Search for block references within a page or across the entire graph.
88
+ 8. `roam_search_hierarchy`: Search for parent or child blocks in the block hierarchy.
89
+ 9. `roam_find_pages_modified_today`: Find pages that have been modified today (since midnight).
90
+ 10. `roam_search_by_text`: Search for blocks containing specific text.
91
+ 11. `roam_update_block`: Update a single block identified by its UID.
92
+ 12. `roam_search_by_date`: Search for blocks or pages based on creation or modification dates.
93
+ 13. `roam_search_for_tag`: Search for blocks containing a specific tag and optionally filter by blocks that also contain another tag nearby.
94
+ 14. `roam_remember`: Add a memory or piece of information to remember.
95
+ 15. `roam_recall`: Retrieve all stored memories.
96
+ 16. `roam_datomic_query`: Execute a custom Datomic query on the Roam graph beyond the available search tools.
67
97
 
68
98
  ## Setup
69
99
 
@@ -5,43 +5,58 @@ import { initializeGraph } from '@roam-research/roam-api-sdk';
5
5
  import { API_TOKEN, GRAPH_NAME } from '../config/environment.js';
6
6
  import { toolSchemas } from '../tools/schemas.js';
7
7
  import { ToolHandlers } from '../tools/tool-handlers.js';
8
+ import { readFileSync } from 'node:fs';
9
+ import { join, dirname } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ // Read package.json to get the version
14
+ const packageJsonPath = join(__dirname, '../../package.json');
15
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
16
+ const serverVersion = packageJson.version;
8
17
  export class RoamServer {
9
18
  constructor() {
10
- this.graph = initializeGraph({
11
- token: API_TOKEN,
12
- graph: GRAPH_NAME,
13
- });
14
- this.toolHandlers = new ToolHandlers(this.graph);
19
+ try {
20
+ this.graph = initializeGraph({
21
+ token: API_TOKEN,
22
+ graph: GRAPH_NAME,
23
+ });
24
+ }
25
+ catch (error) {
26
+ const errorMessage = error instanceof Error ? error.message : String(error);
27
+ throw new McpError(ErrorCode.InternalError, `Failed to initialize Roam graph: ${errorMessage}`);
28
+ }
29
+ try {
30
+ this.toolHandlers = new ToolHandlers(this.graph);
31
+ }
32
+ catch (error) {
33
+ const errorMessage = error instanceof Error ? error.message : String(error);
34
+ throw new McpError(ErrorCode.InternalError, `Failed to initialize tool handlers: ${errorMessage}`);
35
+ }
36
+ // Ensure toolSchemas is not empty before proceeding
37
+ if (Object.keys(toolSchemas).length === 0) {
38
+ throw new McpError(ErrorCode.InternalError, 'No tool schemas defined in src/tools/schemas.ts');
39
+ }
15
40
  this.server = new Server({
16
41
  name: 'roam-research',
17
- version: '0.25.5',
42
+ version: serverVersion, // Use the version from package.json
18
43
  }, {
19
44
  capabilities: {
20
45
  tools: {
21
- roam_remember: {},
22
- roam_recall: {},
23
- roam_add_todo: {},
24
- roam_fetch_page_by_title: {},
25
- roam_create_page: {},
26
- roam_create_block: {},
27
- roam_import_markdown: {},
28
- roam_create_outline: {},
29
- roam_search_for_tag: {},
30
- roam_search_by_status: {},
31
- roam_search_block_refs: {},
32
- roam_search_hierarchy: {},
33
- roam_find_pages_modified_today: {},
34
- roam_search_by_text: {},
35
- roam_update_block: {},
36
- roam_update_multiple_blocks: {},
37
- roam_search_by_date: {},
38
- roam_datomic_query: {}
46
+ ...Object.fromEntries(Object.keys(toolSchemas).map((toolName) => [toolName, {}])),
39
47
  },
40
48
  },
41
49
  });
42
50
  this.setupRequestHandlers();
43
51
  // Error handling
44
- this.server.onerror = (error) => { };
52
+ this.server.onerror = (error) => {
53
+ // Re-throw as McpError to be caught by the MCP client
54
+ if (error instanceof McpError) {
55
+ throw error;
56
+ }
57
+ const errorMessage = error instanceof Error ? error.message : String(error);
58
+ throw new McpError(ErrorCode.InternalError, `MCP server internal error: ${errorMessage}`);
59
+ };
45
60
  process.on('SIGINT', async () => {
46
61
  await this.server.close();
47
62
  process.exit(0);
@@ -220,7 +235,13 @@ export class RoamServer {
220
235
  });
221
236
  }
222
237
  async run() {
223
- const transport = new StdioServerTransport();
224
- await this.server.connect(transport);
238
+ try {
239
+ const transport = new StdioServerTransport();
240
+ await this.server.connect(transport);
241
+ }
242
+ catch (error) {
243
+ const errorMessage = error instanceof Error ? error.message : String(error);
244
+ throw new McpError(ErrorCode.InternalError, `Failed to connect MCP server: ${errorMessage}`);
245
+ }
225
246
  }
226
247
  }
@@ -19,21 +19,24 @@ export const toolSchemas = {
19
19
  },
20
20
  },
21
21
  roam_fetch_page_by_title: {
22
+ name: 'roam_fetch_page_by_title',
22
23
  description: 'Fetch page by title, defaults to raw JSON string.',
23
- type: 'object',
24
- properties: {
25
- title: {
26
- type: 'string',
27
- description: 'Title of the page. For date pages, use ordinal date formats such as January 2nd, 2025'
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ title: {
28
+ type: 'string',
29
+ description: 'Title of the page. For date pages, use ordinal date formats such as January 2nd, 2025'
30
+ },
31
+ format: {
32
+ type: 'string',
33
+ enum: ['markdown', 'raw'],
34
+ default: 'raw',
35
+ description: "Format output as markdown or JSON. 'markdown' returns as string; 'raw' returns JSON string of the page's blocks"
36
+ }
28
37
  },
29
- format: {
30
- type: 'string',
31
- enum: ['markdown', 'raw'],
32
- default: 'raw',
33
- description: "Format output as markdown or JSON. 'markdown' returns as string; 'raw' returns JSON string of the page's blocks"
34
- }
38
+ required: ['title']
35
39
  },
36
- required: ['title']
37
40
  },
38
41
  roam_create_page: {
39
42
  name: 'roam_create_page',
@@ -149,7 +152,7 @@ export const toolSchemas = {
149
152
  },
150
153
  roam_import_markdown: {
151
154
  name: 'roam_import_markdown',
152
- description: 'Import nested markdown content into Roam under a specific block. Can locate the parent block by UID or by exact string match within a specific page.',
155
+ 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.',
153
156
  inputSchema: {
154
157
  type: 'object',
155
158
  properties: {
@@ -171,7 +174,7 @@ export const toolSchemas = {
171
174
  },
172
175
  parent_string: {
173
176
  type: 'string',
174
- description: 'Optional: Exact string content of the parent block to add content under (must provide either page_uid or page_title)'
177
+ description: 'Optional: Exact string content of the parent block to add content under (must provide either page_uid (preferred) or page_title)'
175
178
  },
176
179
  order: {
177
180
  type: 'string',
@@ -311,7 +314,7 @@ export const toolSchemas = {
311
314
  },
312
315
  roam_update_block: {
313
316
  name: 'roam_update_block',
314
- 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).',
317
+ 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 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).',
315
318
  inputSchema: {
316
319
  type: 'object',
317
320
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roam-research-mcp",
3
- "version": "0.25.5",
3
+ "version": "0.25.7",
4
4
  "description": "A Model Context Protocol (MCP) server for Roam Research API integration",
5
5
  "private": false,
6
6
  "repository": {
@@ -31,7 +31,8 @@
31
31
  "build": "tsc && chmod 755 build/index.js",
32
32
  "prepare": "npm run build",
33
33
  "watch": "tsc --watch",
34
- "inspector": "npx @modelcontextprotocol/inspector build/index.js"
34
+ "inspector": "npx @modelcontextprotocol/inspector build/index.js",
35
+ "start": "node build/index.js"
35
36
  },
36
37
  "dependencies": {
37
38
  "@modelcontextprotocol/sdk": "0.6.0",