triliumnext-mcp 0.3.10-beta.1 → 0.3.10-beta.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.
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import axios from 'axios';
6
6
  import { logVerbose, logVerboseApi, logVerboseAxiosError } from "../utils/verboseUtils.js";
7
+ import { validateAndTranslateTemplate, createTemplateRelationError } from "../utils/templateMapper.js";
7
8
  /**
8
9
  * Manage note attributes with write operations (create, update, delete)
9
10
  * This function provides write-only access to note attributes
@@ -49,12 +50,30 @@ async function create_single_attribute(noteId, attribute, axiosInstance) {
49
50
  errors: validation.errors
50
51
  };
51
52
  }
53
+ // Translate template names to note IDs for template relations
54
+ let processedValue = attribute.value || "";
55
+ if (attribute.type === "relation" && attribute.name === "template" && attribute.value) {
56
+ try {
57
+ processedValue = validateAndTranslateTemplate(attribute.value);
58
+ logVerbose("create_single_attribute", `Translated template relation`, {
59
+ from: attribute.value,
60
+ to: processedValue
61
+ });
62
+ }
63
+ catch (error) {
64
+ return {
65
+ success: false,
66
+ message: createTemplateRelationError(attribute.value),
67
+ errors: [error instanceof Error ? error.message : 'Template validation failed']
68
+ };
69
+ }
70
+ }
52
71
  // Prepare attribute data for ETAPI
53
72
  const attributeData = {
54
73
  noteId: noteId,
55
74
  type: attribute.type,
56
75
  name: attribute.name,
57
- value: attribute.value || "",
76
+ value: processedValue,
58
77
  position: attribute.position || 10,
59
78
  isInheritable: attribute.isInheritable || false
60
79
  };
@@ -95,11 +114,26 @@ async function create_batch_attributes(noteId, attributes, axiosInstance) {
95
114
  errors.push(`Validation failed for ${attribute.type} '${attribute.name}': ${validation.errors.join(', ')}`);
96
115
  return null;
97
116
  }
117
+ // Translate template names to note IDs for template relations
118
+ let processedValue = attribute.value || "";
119
+ if (attribute.type === "relation" && attribute.name === "template" && attribute.value) {
120
+ try {
121
+ processedValue = validateAndTranslateTemplate(attribute.value);
122
+ logVerbose("create_batch_attributes", `Translated template relation`, {
123
+ from: attribute.value,
124
+ to: processedValue
125
+ });
126
+ }
127
+ catch (error) {
128
+ errors.push(createTemplateRelationError(attribute.value));
129
+ return null;
130
+ }
131
+ }
98
132
  const attributeData = {
99
133
  noteId: noteId,
100
134
  type: attribute.type,
101
135
  name: attribute.name,
102
- value: attribute.value || "",
136
+ value: processedValue,
103
137
  position: attribute.position || 10,
104
138
  isInheritable: attribute.isInheritable || false
105
139
  };
@@ -5,6 +5,7 @@
5
5
  import { processContentArray } from '../utils/contentProcessor.js';
6
6
  import { logVerbose, logVerboseError, logVerboseApi } from '../utils/verboseUtils.js';
7
7
  import { getContentRequirements, validateContentForNoteType, extractTemplateRelation } from '../utils/contentRules.js';
8
+ import { validateAndTranslateTemplate, createTemplateRelationError } from '../utils/templateMapper.js';
8
9
  /**
9
10
  * Strip HTML tags from content for text notes
10
11
  */
@@ -209,11 +210,26 @@ export async function handleCreateNote(args, axiosInstance) {
209
210
  */
210
211
  async function createNoteAttributes(noteId, attributes, axiosInstance) {
211
212
  const attributePromises = attributes.map(async (attr) => {
213
+ // Translate template names to note IDs for template relations
214
+ let processedValue = attr.value || '';
215
+ if (attr.type === "relation" && attr.name === "template" && attr.value) {
216
+ try {
217
+ processedValue = validateAndTranslateTemplate(attr.value);
218
+ logVerbose("createNoteAttributes", `Translated template relation`, {
219
+ from: attr.value,
220
+ to: processedValue
221
+ });
222
+ }
223
+ catch (error) {
224
+ logVerboseError("createNoteAttributes", error);
225
+ throw new Error(createTemplateRelationError(attr.value));
226
+ }
227
+ }
212
228
  const attributeData = {
213
229
  noteId: noteId,
214
230
  type: attr.type,
215
231
  name: attr.name,
216
- value: attr.value || '',
232
+ value: processedValue,
217
233
  position: attr.position || 10,
218
234
  isInheritable: attr.isInheritable || false
219
235
  };
@@ -1,4 +1,5 @@
1
1
  import { logVerboseInput, logVerboseOutput, logVerboseTransform } from "../utils/verboseUtils.js";
2
+ import { translateTemplateNameToId, isBuiltinTemplate } from "../utils/templateMapper.js";
2
3
  export function buildSearchQuery(params) {
3
4
  const queryParts = [];
4
5
  // Verbose logging
@@ -191,6 +192,12 @@ function enhanceRelationProperty(name, op, value) {
191
192
  if (op === 'exists' || op === 'not_exists' || !value) {
192
193
  return name;
193
194
  }
195
+ // Translate built-in template names to note IDs
196
+ if (isTemplateOrSystemRelation(name) && isBuiltinTemplate(value)) {
197
+ const translatedValue = translateTemplateNameToId(value);
198
+ logVerboseTransform("searchQueryBuilder", value, translatedValue, `Translated template name`);
199
+ return `${name}.noteId`;
200
+ }
194
201
  // Auto-detect noteId patterns and apply appropriate suffix
195
202
  if (isNoteIdPattern(value) && isTemplateOrSystemRelation(name)) {
196
203
  return `${name}.noteId`;
@@ -15,7 +15,7 @@ export function createWriteTools() {
15
15
  properties: {
16
16
  parentNoteId: {
17
17
  type: "string",
18
- description: "ID of the parent note",
18
+ description: "ID of the parent note. ⚠️ IMPORTANT: When creating child notes for special note types, ensure proper requirements:\n• RENDER parents: child must be type='code', mime='text/html' (HTML content for rendering)\n• CALENDAR parents: child must have #startDate, #endDate, #startTime, #endTime labels\n• BOARD parents: child must have #status label (e.g., 'To Do', 'In Progress', 'Done')\n• Missing required labels/relations will cause child notes to not display properly",
19
19
  default: "root"
20
20
  },
21
21
  title: {
@@ -25,11 +25,11 @@ export function createWriteTools() {
25
25
  type: {
26
26
  type: "string",
27
27
  enum: ["text", "code", "render", "search", "relationMap", "book", "noteMap", "mermaid", "webView"],
28
- description: "Type of note (aligned with TriliumNext ETAPI specification)",
28
+ description: "Type of note (aligned with TriliumNext ETAPI specification). ⚠️ SPECIAL TYPES REQUIRE CHILD NOTES:\n• RENDER: Creates empty container - requires child HTML code note with ~renderNote relation\n• CALENDAR (template): Creates empty container - requires child notes with date/time labels\n• BOARD (template): Creates empty container - requires child notes with #status labels\n• All other types can contain content directly",
29
29
  },
30
30
  content: {
31
31
  type: "string",
32
- description: "Content of the note (optional). Content requirements by note type: TEXT notes require HTML content (plain text auto-wrapped in <p> tags, e.g., '<p>Hello world</p>', '<strong>bold</strong>'); CODE/MERMAID notes require plain text ONLY (HTML tags rejected, e.g., 'def fibonacci(n):'); ⚠️ OMIT CONTENT for: 1) WEBVIEW notes (use #webViewSrc label instead), 2) Container templates (Board, Calendar, Grid View, List View, Table, Geo Map), 3) System notes: RENDER (create child HTML note with type='code' and mime='application/x-html', then link with ~renderNote relation), SEARCH (queries in search properties), RELATION_MAP (visual maps), NOTE_MAP (visual hierarchies), BOOK (container notes) - these must be EMPTY to work properly. When omitted, note will be created with empty content."
32
+ description: "Content of the note (optional). Content requirements by note type: TEXT notes require HTML content (plain text auto-wrapped in <p> tags, e.g., '<p>Hello world</p>', '<strong>bold</strong>'); CODE/MERMAID notes require plain text ONLY (HTML tags rejected, e.g., 'def fibonacci(n):'); ⚠️ OMIT CONTENT for: 1) WEBVIEW notes (use #webViewSrc label instead), 2) Container templates (Board, Calendar, Grid View, List View, Table, Geo Map), 3) System notes: RENDER, SEARCH, RELATION_MAP, NOTE_MAP, BOOK - these must be EMPTY to work properly. When omitted, note will be created with empty content.\n\n📋 WORKFLOW FOR SPECIAL NOTE TYPES:\n• RENDER notes: Create empty → create child HTML code note → add ~renderNote relation to child\n• CALENDAR/BOARD/GRID/LIST/TABLE/GEO templates: Create empty with ~template relation add child notes with proper labels\n• TEXT SNIPPET templates: Create with ~template relation + content\n• Most other types: Add content directly during creation"
33
33
  },
34
34
  mime: {
35
35
  type: "string",
@@ -37,7 +37,7 @@ export function createWriteTools() {
37
37
  },
38
38
  attributes: {
39
39
  type: "array",
40
- description: "Optional attributes to create with the note (labels and relations). Enables one-step note creation with metadata. Labels use #tag format (e.g., 'important', 'project'), relations connect to other notes (e.g., template relations use 'Board', 'Calendar', 'Text Snippet'). ⚠️ TEMPLATE RESTRICTIONS: Container templates (Board, Calendar, Grid View, List View, Table, Geo Map) MUST be empty notes - add content as child notes.",
40
+ description: "Optional attributes to create with the note (labels and relations). Enables one-step note creation with metadata. ⚠️ CRITICAL: Always add template relations during create_note when possible!\n\n📋 TEMPLATE RELATIONS (add during create_note):\n• ~template = 'Board' (kanban task boards)\n• ~template = 'Calendar' (calendar event displays)\n• ~template = 'Grid View' (grid layouts)\n• ~template = 'List View' (list layouts)\n• ~template = 'Table' (table structures)\n• ~template = 'Geo Map' (geographic maps)\n• ~template = 'Text Snippet' (reusable text)\n\n⚠️ SPECIAL CASES requiring separate steps:\n• ~renderNote = '<noteId>' (RENDER notes - requires existing child note ID)\n• Custom relations pointing to specific notes (use note IDs after creation)\n\n📋 LABELS & OTHER RELATIONS:\n• Labels: #tag format (e.g., #important, #project)\n• Relations: ~connection format (e.g., ~author, ~publisher)\n• Template relations use human-readable names (auto-translated to system IDs)\n\n⚠️ TEMPLATE RESTRICTIONS: Container templates MUST be empty notes - add content as child notes",
41
41
  items: {
42
42
  type: "object",
43
43
  properties: {
@@ -332,7 +332,7 @@ export function createWriteAttributeTools() {
332
332
  return [
333
333
  {
334
334
  name: "manage_attributes",
335
- description: "Manage note attributes with write operations (create, update, delete). Create labels (#tags), template relations (~template), update existing attributes, and organize notes with metadata. IMPORTANT: This tool only provides write access - use read_attributes to view existing attributes. Relations require values pointing to existing notes (e.g., template relations use 'Board', 'Calendar'; author relations use target note titles or IDs). UPDATE LIMITATIONS: For labels, only value and position can be updated. For relations, only position can be updated. The isInheritable property cannot be changed via update - delete and recreate to modify inheritability. Supports single operations and efficient batch creation for better performance.",
335
+ description: "Manage note attributes with write operations (create, update, delete). Create labels (#tags), template relations (~template), update existing attributes, and organize notes with metadata. ⚠️ PRIORITY: Use create_note with attributes parameter for template relations when possible - only use this tool for post-creation modifications or complex scenarios.\n\n✅ BEST PRACTICE: Most template relations (~template = 'Board', 'Calendar', etc.) should be added during create_note\n❌ USE THIS TOOL FOR: ~renderNote relations, custom note-to-note relations, post-creation label updates\n\nIMPORTANT: This tool only provides write access - use read_attributes to view existing attributes. Relations require values pointing to existing notes (e.g., template relations use human-readable names like 'Board', 'Calendar' which are automatically translated to system note IDs; author relations use target note titles or IDs). UPDATE LIMITATIONS: For labels, only value and position can be updated. For relations, only position can be updated. The isInheritable property cannot be changed via update - delete and recreate to modify inheritability. Supports single operations and efficient batch creation for better performance.",
336
336
  inputSchema: {
337
337
  type: "object",
338
338
  properties: {
@@ -362,7 +362,7 @@ export function createWriteAttributeTools() {
362
362
  },
363
363
  value: {
364
364
  type: "string",
365
- description: "Attribute value: REQUIRED for relations (relations must point to existing notes - use template names like 'Board', 'Calendar', 'Text Snippet' or target note IDs/titles like 'Tolkien' or 'abc123def'), optional for labels (e.g., status labels like 'In Progress', priority labels like 'High'). Relations always need values since they connect notes together."
365
+ description: "Attribute value: REQUIRED for relations (relations must point to existing notes - use human-readable template names like 'Board', 'Calendar', 'Text Snippet' which are automatically translated to system note IDs, or use target note IDs/titles like 'Tolkien' or 'abc123def' for custom relations), optional for labels (e.g., status labels like 'In Progress', priority labels like 'High'). Relations always need values since they connect notes together."
366
366
  },
367
367
  position: {
368
368
  type: "number",
@@ -96,14 +96,8 @@ export async function validateContentForUpdate(rawContent, type) {
96
96
  break;
97
97
  case 'code':
98
98
  case 'mermaid':
99
- // For code/mermaid notes, reject HTML content
100
- if (isLikelyHtml(contentString)) {
101
- return {
102
- isValid: false,
103
- processedContent: contentString,
104
- error: `${type} notes require plain text only, but HTML content was detected. Remove HTML tags and use plain text format.`
105
- };
106
- }
99
+ // Allow both plain text and HTML content for code/mermaid notes
100
+ // HTML validation removed to support more flexible content
107
101
  break;
108
102
  case 'render':
109
103
  case 'search':
@@ -13,6 +13,8 @@ const CONTAINER_TEMPLATES = [
13
13
  'Table', // Spreadsheet-like tables
14
14
  'Geo Map' // Geographic maps
15
15
  ];
16
+ // Import template translation utilities
17
+ import { isBuiltinTemplate } from "./templateMapper.js";
16
18
  /**
17
19
  * Get content rules for a note type (without considering templates)
18
20
  */
@@ -34,25 +36,25 @@ export function getNoteTypeContentRules(noteType) {
34
36
  requiresHtml: false,
35
37
  description: "Content must be empty - render notes display HTML content from child notes via ~renderNote relation",
36
38
  examples: [""],
37
- errorMessage: "Render notes must be empty. Create a child code note with type='code' and mime='application/x-html' containing your HTML, then link it with ~renderNote='child-note-title' relation."
39
+ errorMessage: "Render notes must be empty. Create a child code note with type='code' and mime='text/html' containing your HTML, then link it with ~renderNote='child-note-title' relation."
38
40
  };
39
41
  case 'code':
40
42
  return {
41
43
  allowContent: true,
42
44
  enforceEmpty: false,
43
45
  requiresHtml: false,
44
- description: "Plain text only (no HTML tags)",
45
- examples: ["def fibonacci(n):", "console.log('hello');"],
46
- errorMessage: "Code notes require plain text only. HTML tags are not allowed."
46
+ description: "Plain text or HTML content allowed",
47
+ examples: ["def fibonacci(n):", "console.log('hello');", "<div>HTML code example</div>"],
48
+ errorMessage: "Code notes accept both plain text and HTML content."
47
49
  };
48
50
  case 'mermaid':
49
51
  return {
50
52
  allowContent: true,
51
53
  enforceEmpty: false,
52
54
  requiresHtml: false,
53
- description: "Plain text only (Mermaid diagram syntax)",
54
- examples: ["graph TD; A-->B", "sequenceDiagram; A->B: Hello"],
55
- errorMessage: "Mermaid notes require plain text diagram syntax only. HTML tags are not allowed."
55
+ description: "Plain text or HTML content allowed (Mermaid diagram syntax)",
56
+ examples: ["graph TD; A-->B", "sequenceDiagram; A->B: Hello", "<div>HTML with Mermaid</div>"],
57
+ errorMessage: "Mermaid notes accept both plain text and HTML content."
56
58
  };
57
59
  case 'webView':
58
60
  return {
@@ -132,7 +134,7 @@ export function getTemplateContentRules(noteType, templateRelation) {
132
134
  ? templateRelation
133
135
  : templateRelation?.value;
134
136
  // Check if this is a container template that must be empty (overrides base rules)
135
- if (noteType === 'book' && templateValue && CONTAINER_TEMPLATES.includes(templateValue)) {
137
+ if (noteType === 'book' && templateValue && isBuiltinTemplate(templateValue) && CONTAINER_TEMPLATES.includes(templateValue)) {
136
138
  return {
137
139
  ...baseRules,
138
140
  allowContent: false,
@@ -231,9 +233,7 @@ export async function validateContentForNoteType(content, noteType, currentConte
231
233
  // Type-specific validation
232
234
  switch (noteType) {
233
235
  case 'text':
234
- case 'render':
235
- case 'webView':
236
- // HTML required for these types
236
+ // HTML required for text notes
237
237
  if (rules.requiresHtml && !isLikelyHtml(textContent)) {
238
238
  // Auto-wrap plain text in HTML
239
239
  const wrappedContent = `<p>${textContent}</p>`;
@@ -246,16 +246,8 @@ export async function validateContentForNoteType(content, noteType, currentConte
246
246
  break;
247
247
  case 'code':
248
248
  case 'mermaid':
249
- // Plain text required for code/mermaid notes
250
- if (rules.requiresHtml === false && isLikelyHtml(textContent)) {
251
- return {
252
- valid: false,
253
- content,
254
- error: `${noteType} notes require plain text only, but HTML content was detected. ` +
255
- `Remove HTML tags and use plain text format. ` +
256
- `Expected format: ${rules.examples.join(', ')}`
257
- };
258
- }
249
+ // Allow both plain text and HTML content for code/mermaid notes
250
+ // HTML validation removed to support more flexible content
259
251
  break;
260
252
  }
261
253
  return {
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Template name to note ID mapping system for TriliumNext MCP
3
+ *
4
+ * This module provides translation between human-readable template names
5
+ * and their corresponding system note IDs in TriliumNext.
6
+ */
7
+ // Built-in template name to note ID mapping
8
+ export const TEMPLATE_NAME_TO_ID = {
9
+ 'Grid View': '_template_grid_view',
10
+ 'Calendar': '_template_calendar',
11
+ 'Board': '_template_board',
12
+ 'List View': '_template_list_view',
13
+ 'Table': '_template_table',
14
+ 'Geo Map': '_template_geo_map',
15
+ 'Text Snippet': '_template_text_snippet'
16
+ };
17
+ // Reverse mapping for ID to name resolution
18
+ export const TEMPLATE_ID_TO_NAME = Object.fromEntries(Object.entries(TEMPLATE_NAME_TO_ID).map(([name, id]) => [id, name]));
19
+ // List of all built-in template names for validation
20
+ export const BUILTIN_TEMPLATE_NAMES = Object.keys(TEMPLATE_NAME_TO_ID);
21
+ // List of all built-in template IDs for validation
22
+ export const BUILTIN_TEMPLATE_IDS = Object.values(TEMPLATE_NAME_TO_ID);
23
+ /**
24
+ * Translates a human-readable template name to its system note ID
25
+ * @param templateName - Human-readable template name (e.g., "Grid View")
26
+ * @returns System note ID (e.g., "_template_grid_view")
27
+ */
28
+ export function translateTemplateNameToId(templateName) {
29
+ return TEMPLATE_NAME_TO_ID[templateName] || templateName;
30
+ }
31
+ /**
32
+ * Translates a system note ID back to human-readable template name
33
+ * @param templateId - System note ID (e.g., "_template_grid_view")
34
+ * @returns Human-readable template name (e.g., "Grid View")
35
+ */
36
+ export function translateTemplateIdToName(templateId) {
37
+ return TEMPLATE_ID_TO_NAME[templateId] || templateId;
38
+ }
39
+ /**
40
+ * Checks if a template name is a built-in template
41
+ * @param templateName - Template name to check
42
+ * @returns True if it's a built-in template
43
+ */
44
+ export function isBuiltinTemplate(templateName) {
45
+ return templateName in TEMPLATE_NAME_TO_ID;
46
+ }
47
+ /**
48
+ * Checks if a template ID is a built-in template ID
49
+ * @param templateId - Template ID to check
50
+ * @returns True if it's a built-in template ID
51
+ */
52
+ export function isBuiltinTemplateId(templateId) {
53
+ return templateId in TEMPLATE_ID_TO_NAME;
54
+ }
55
+ /**
56
+ * Validates and translates a template name for API use
57
+ * @param templateName - Template name to validate and translate
58
+ * @returns Translated template ID ready for API calls
59
+ * @throws Error if template name is invalid
60
+ */
61
+ export function validateAndTranslateTemplate(templateName) {
62
+ if (typeof templateName !== 'string' || templateName.trim() === '') {
63
+ throw new Error('Template name cannot be empty');
64
+ }
65
+ // Check if it's a built-in template
66
+ if (isBuiltinTemplate(templateName)) {
67
+ return translateTemplateNameToId(templateName);
68
+ }
69
+ // Check if it's already a valid note ID pattern
70
+ if (isNoteIdPattern(templateName)) {
71
+ return templateName;
72
+ }
73
+ // Not a built-in template and not a note ID - show helpful error
74
+ throw new Error(`Invalid template: "${templateName}". Template relations must link to a note ID. ` +
75
+ `For built-in templates, use one of: ${BUILTIN_TEMPLATE_NAMES.join(', ')}. ` +
76
+ `For custom templates, use the note ID (e.g., "abc123"). ` +
77
+ `~template relations should always reference note IDs, not human-readable names.`);
78
+ }
79
+ /**
80
+ * Checks if a string matches Trilium note ID patterns
81
+ * @param value - String to check
82
+ * @returns True if it matches note ID patterns
83
+ */
84
+ function isNoteIdPattern(value) {
85
+ // Trilium note IDs are typically alphanumeric with underscores, like "_template_grid_view" or "abc123def"
86
+ return /^[a-zA-Z0-9_]+$/.test(value) && value.length > 2;
87
+ }
88
+ /**
89
+ * Gets a list of available built-in templates for error messages
90
+ * @returns Formatted string listing available templates
91
+ */
92
+ export function getAvailableTemplatesMessage() {
93
+ return `Available built-in templates: ${BUILTIN_TEMPLATE_NAMES.join(', ')}. ` +
94
+ `Custom templates should use their note ID (e.g., "abc123").`;
95
+ }
96
+ /**
97
+ * Provides enhanced error message for template relation validation
98
+ * @param templateValue - The template value that failed validation
99
+ * @returns Detailed error message
100
+ */
101
+ export function createTemplateRelationError(templateValue) {
102
+ if (typeof templateValue !== 'string' || templateValue.trim() === '') {
103
+ return 'Template relation value cannot be empty';
104
+ }
105
+ if (isBuiltinTemplate(templateValue)) {
106
+ // This shouldn't happen if validation is working correctly
107
+ return `Built-in template "${templateValue}" should have been translated to "${translateTemplateNameToId(templateValue)}"`;
108
+ }
109
+ if (isNoteIdPattern(templateValue)) {
110
+ return `Template note ID "${templateValue}" may not exist. Verify the note ID is correct.`;
111
+ }
112
+ return `Invalid template relation: "${templateValue}". ${getAvailableTemplatesMessage()}`;
113
+ }
@@ -148,7 +148,9 @@ export function validateOperator(op) {
148
148
  export function validateTemplateRelation(templateName) {
149
149
  const validTemplates = ['Calendar', 'Board', 'Text Snippet', 'Grid View', 'List View', 'Table', 'Geo Map'];
150
150
  if (typeof templateName !== 'string' || !validTemplates.includes(templateName)) {
151
- throw new Error(`Invalid template: ${templateName}. Must be one of: ${validTemplates.join(', ')}`);
151
+ throw new Error(`Invalid template: ${templateName}. Must be one of: ${validTemplates.join(', ')}. ` +
152
+ `Template relations must link to note IDs. For built-in templates, use their note ID (e.g., "_template_grid_view"). ` +
153
+ `For custom templates, use the actual note ID.`);
152
154
  }
153
155
  return templateName;
154
156
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triliumnext-mcp",
3
- "version": "0.3.10-beta.1",
3
+ "version": "0.3.10-beta.2",
4
4
  "description": "A model context protocol server for TriliumNext Notes",
5
5
  "type": "module",
6
6
  "bin": {