roam-research-mcp 0.23.0 → 0.23.1

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.
@@ -54,20 +54,14 @@ export class OutlineOperations {
54
54
  }
55
55
  // If still not found and this is the first retry, try to create the page
56
56
  if (retry === 0) {
57
- try {
58
- await createPage(this.graph, {
59
- action: 'create-page',
60
- page: { title: titleOrUid }
61
- });
62
- // Wait a bit and continue to next retry to check if page was created
63
- await new Promise(resolve => setTimeout(resolve, delayMs));
64
- continue;
65
- }
66
- catch (error) {
67
- console.error('Error creating page:', error);
68
- // Continue to next retry
69
- continue;
70
- }
57
+ const success = await createPage(this.graph, {
58
+ action: 'create-page',
59
+ page: { title: titleOrUid }
60
+ });
61
+ // Even if createPage returns false, the page might still have been created
62
+ // Wait a bit and continue to next retry
63
+ await new Promise(resolve => setTimeout(resolve, delayMs));
64
+ continue;
71
65
  }
72
66
  if (retry < maxRetries - 1) {
73
67
  await new Promise(resolve => setTimeout(resolve, delayMs));
@@ -78,23 +72,21 @@ export class OutlineOperations {
78
72
  // Get or create the target page
79
73
  const targetPageUid = await findOrCreatePage(page_title_uid || formatRoamDate(new Date()));
80
74
  // Helper function to find block with improved relationship checks
81
- const findBlockWithRetry = async (pageUid, blockString, maxRetries = 5, initialDelay = 1000, case_sensitive = false) => {
75
+ const findBlockWithRetry = async (pageUid, blockString, maxRetries = 5, initialDelay = 1000) => {
82
76
  // Try multiple query strategies
83
77
  const queries = [
84
78
  // Strategy 1: Direct page and string match
85
79
  `[:find ?b-uid ?order
86
80
  :where [?p :block/uid "${pageUid}"]
87
81
  [?b :block/page ?p]
88
- [?b :block/string ?block-str]
89
- [(${case_sensitive ? '=' : 'clojure.string/equals-ignore-case'} ?block-str "${blockString}")]
82
+ [?b :block/string "${blockString}"]
90
83
  [?b :block/order ?order]
91
84
  [?b :block/uid ?b-uid]]`,
92
85
  // Strategy 2: Parent-child relationship
93
86
  `[:find ?b-uid ?order
94
87
  :where [?p :block/uid "${pageUid}"]
95
88
  [?b :block/parents ?p]
96
- [?b :block/string ?block-str]
97
- [(${case_sensitive ? '=' : 'clojure.string/equals-ignore-case'} ?block-str "${blockString}")]
89
+ [?b :block/string "${blockString}"]
98
90
  [?b :block/order ?order]
99
91
  [?b :block/uid ?b-uid]]`,
100
92
  // Strategy 3: Broader page relationship
@@ -102,8 +94,7 @@ export class OutlineOperations {
102
94
  :where [?p :block/uid "${pageUid}"]
103
95
  [?b :block/page ?page]
104
96
  [?p :block/page ?page]
105
- [?b :block/string ?block-str]
106
- [(${case_sensitive ? '=' : 'clojure.string/equals-ignore-case'} ?block-str "${blockString}")]
97
+ [?b :block/string "${blockString}"]
107
98
  [?b :block/order ?order]
108
99
  [?b :block/uid ?b-uid]]`
109
100
  ];
@@ -125,7 +116,7 @@ export class OutlineOperations {
125
116
  throw new McpError(ErrorCode.InternalError, `Failed to find block "${blockString}" under page "${pageUid}" after trying multiple strategies`);
126
117
  };
127
118
  // Helper function to create and verify block with improved error handling
128
- const createAndVerifyBlock = async (content, parentUid, maxRetries = 5, initialDelay = 1000, isRetry = false, case_sensitive = false) => {
119
+ const createAndVerifyBlock = async (content, parentUid, maxRetries = 5, initialDelay = 1000, isRetry = false) => {
129
120
  try {
130
121
  // Initial delay before any operations
131
122
  if (!isRetry) {
@@ -133,25 +124,25 @@ export class OutlineOperations {
133
124
  }
134
125
  for (let retry = 0; retry < maxRetries; retry++) {
135
126
  console.log(`Attempt ${retry + 1}/${maxRetries} to create block "${content}" under "${parentUid}"`);
127
+ // Create block
128
+ const success = await createBlock(this.graph, {
129
+ action: 'create-block',
130
+ location: {
131
+ 'parent-uid': parentUid,
132
+ order: 'last'
133
+ },
134
+ block: { string: content }
135
+ });
136
+ // Wait with exponential backoff
137
+ const delay = initialDelay * Math.pow(2, retry);
138
+ await new Promise(resolve => setTimeout(resolve, delay));
136
139
  try {
137
- // Create block
138
- await createBlock(this.graph, {
139
- action: 'create-block',
140
- location: {
141
- 'parent-uid': parentUid,
142
- order: 'first'
143
- },
144
- block: { string: content }
145
- });
146
- // Wait with exponential backoff
147
- const delay = initialDelay * Math.pow(2, retry);
148
- await new Promise(resolve => setTimeout(resolve, delay));
149
140
  // Try to find the block using our improved findBlockWithRetry
150
- return await findBlockWithRetry(parentUid, content, maxRetries, initialDelay, case_sensitive);
141
+ return await findBlockWithRetry(parentUid, content);
151
142
  }
152
143
  catch (error) {
153
144
  const errorMessage = error instanceof Error ? error.message : String(error);
154
- console.log(`Failed to create/find block on attempt ${retry + 1}: ${errorMessage}`);
145
+ console.log(`Failed to find block on attempt ${retry + 1}: ${errorMessage}`);
155
146
  if (retry === maxRetries - 1)
156
147
  throw error;
157
148
  }
@@ -165,7 +156,7 @@ export class OutlineOperations {
165
156
  // Otherwise, try one more time with a clean slate
166
157
  console.log(`Retrying block creation for "${content}" with fresh attempt`);
167
158
  await new Promise(resolve => setTimeout(resolve, initialDelay * 2));
168
- return createAndVerifyBlock(content, parentUid, maxRetries, initialDelay, true, case_sensitive);
159
+ return createAndVerifyBlock(content, parentUid, maxRetries, initialDelay, true);
169
160
  }
170
161
  };
171
162
  // Get or create the parent block
@@ -429,7 +429,7 @@ export const toolSchemas = {
429
429
  },
430
430
  roam_datomic_query: {
431
431
  name: 'roam_datomic_query',
432
- description: 'Execute a custom Datomic query on the Roam graph. This provides direct access to Roam\'s query engine for advanced data retrieval. Note: The Roam graph is case-sensitive.\nA list 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).\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.',
432
+ description: 'Execute a custom Datomic query on the Roam graph beyond the available search tools. This provides direct access to Roam\'s query engine for advanced data retrieval. Note: The Roam graph is case-sensitive.\nA list 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).\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.',
433
433
  inputSchema: {
434
434
  type: 'object',
435
435
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roam-research-mcp",
3
- "version": "0.23.0",
3
+ "version": "0.23.1",
4
4
  "description": "A Model Context Protocol (MCP) server for Roam Research API integration",
5
5
  "private": false,
6
6
  "repository": {