@noteplanco/noteplan-mcp 1.1.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.
- package/README.md +257 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/noteplan/embeddings.d.ts +170 -0
- package/dist/noteplan/embeddings.d.ts.map +1 -0
- package/dist/noteplan/embeddings.js +684 -0
- package/dist/noteplan/embeddings.js.map +1 -0
- package/dist/noteplan/file-reader.d.ts +77 -0
- package/dist/noteplan/file-reader.d.ts.map +1 -0
- package/dist/noteplan/file-reader.js +488 -0
- package/dist/noteplan/file-reader.js.map +1 -0
- package/dist/noteplan/file-writer.d.ts +108 -0
- package/dist/noteplan/file-writer.d.ts.map +1 -0
- package/dist/noteplan/file-writer.js +621 -0
- package/dist/noteplan/file-writer.js.map +1 -0
- package/dist/noteplan/filter-store.d.ts +28 -0
- package/dist/noteplan/filter-store.d.ts.map +1 -0
- package/dist/noteplan/filter-store.js +180 -0
- package/dist/noteplan/filter-store.js.map +1 -0
- package/dist/noteplan/frontmatter-parser.d.ts +45 -0
- package/dist/noteplan/frontmatter-parser.d.ts.map +1 -0
- package/dist/noteplan/frontmatter-parser.js +259 -0
- package/dist/noteplan/frontmatter-parser.js.map +1 -0
- package/dist/noteplan/fuzzy-search.d.ts +7 -0
- package/dist/noteplan/fuzzy-search.d.ts.map +1 -0
- package/dist/noteplan/fuzzy-search.js +66 -0
- package/dist/noteplan/fuzzy-search.js.map +1 -0
- package/dist/noteplan/markdown-parser.d.ts +87 -0
- package/dist/noteplan/markdown-parser.d.ts.map +1 -0
- package/dist/noteplan/markdown-parser.js +519 -0
- package/dist/noteplan/markdown-parser.js.map +1 -0
- package/dist/noteplan/preferences.d.ts +44 -0
- package/dist/noteplan/preferences.d.ts.map +1 -0
- package/dist/noteplan/preferences.js +156 -0
- package/dist/noteplan/preferences.js.map +1 -0
- package/dist/noteplan/ripgrep-search.d.ts +29 -0
- package/dist/noteplan/ripgrep-search.d.ts.map +1 -0
- package/dist/noteplan/ripgrep-search.js +110 -0
- package/dist/noteplan/ripgrep-search.js.map +1 -0
- package/dist/noteplan/sqlite-reader.d.ts +77 -0
- package/dist/noteplan/sqlite-reader.d.ts.map +1 -0
- package/dist/noteplan/sqlite-reader.js +605 -0
- package/dist/noteplan/sqlite-reader.js.map +1 -0
- package/dist/noteplan/sqlite-writer.d.ts +63 -0
- package/dist/noteplan/sqlite-writer.d.ts.map +1 -0
- package/dist/noteplan/sqlite-writer.js +574 -0
- package/dist/noteplan/sqlite-writer.js.map +1 -0
- package/dist/noteplan/types.d.ts +97 -0
- package/dist/noteplan/types.d.ts.map +1 -0
- package/dist/noteplan/types.js +33 -0
- package/dist/noteplan/types.js.map +1 -0
- package/dist/noteplan/unified-store.d.ts +289 -0
- package/dist/noteplan/unified-store.d.ts.map +1 -0
- package/dist/noteplan/unified-store.js +1308 -0
- package/dist/noteplan/unified-store.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +2468 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/calendar.d.ts +311 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +504 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/embeddings.d.ts +244 -0
- package/dist/tools/embeddings.d.ts.map +1 -0
- package/dist/tools/embeddings.js +226 -0
- package/dist/tools/embeddings.js.map +1 -0
- package/dist/tools/events.d.ts +176 -0
- package/dist/tools/events.d.ts.map +1 -0
- package/dist/tools/events.js +326 -0
- package/dist/tools/events.js.map +1 -0
- package/dist/tools/filters.d.ts +205 -0
- package/dist/tools/filters.d.ts.map +1 -0
- package/dist/tools/filters.js +347 -0
- package/dist/tools/filters.js.map +1 -0
- package/dist/tools/memory.d.ts +6 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +161 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/notes.d.ts +1221 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +1868 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/plugins.d.ts +140 -0
- package/dist/tools/plugins.d.ts.map +1 -0
- package/dist/tools/plugins.js +782 -0
- package/dist/tools/plugins.js.map +1 -0
- package/dist/tools/reminders.d.ts +207 -0
- package/dist/tools/reminders.d.ts.map +1 -0
- package/dist/tools/reminders.js +323 -0
- package/dist/tools/reminders.js.map +1 -0
- package/dist/tools/search.d.ts +58 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +373 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/spaces.d.ts +484 -0
- package/dist/tools/spaces.d.ts.map +1 -0
- package/dist/tools/spaces.js +870 -0
- package/dist/tools/spaces.js.map +1 -0
- package/dist/tools/tasks.d.ts +313 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +690 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/themes.d.ts +91 -0
- package/dist/tools/themes.d.ts.map +1 -0
- package/dist/tools/themes.js +294 -0
- package/dist/tools/themes.js.map +1 -0
- package/dist/tools/ui.d.ts +89 -0
- package/dist/tools/ui.d.ts.map +1 -0
- package/dist/tools/ui.js +137 -0
- package/dist/tools/ui.js.map +1 -0
- package/dist/utils/applescript.d.ts +5 -0
- package/dist/utils/applescript.d.ts.map +1 -0
- package/dist/utils/applescript.js +27 -0
- package/dist/utils/applescript.js.map +1 -0
- package/dist/utils/confirmation-tokens.d.ts +19 -0
- package/dist/utils/confirmation-tokens.d.ts.map +1 -0
- package/dist/utils/confirmation-tokens.js +58 -0
- package/dist/utils/confirmation-tokens.js.map +1 -0
- package/dist/utils/date-filters.d.ts +15 -0
- package/dist/utils/date-filters.d.ts.map +1 -0
- package/dist/utils/date-filters.js +129 -0
- package/dist/utils/date-filters.js.map +1 -0
- package/dist/utils/date-utils.d.ts +113 -0
- package/dist/utils/date-utils.d.ts.map +1 -0
- package/dist/utils/date-utils.js +341 -0
- package/dist/utils/date-utils.js.map +1 -0
- package/dist/utils/folder-matcher.d.ts +14 -0
- package/dist/utils/folder-matcher.d.ts.map +1 -0
- package/dist/utils/folder-matcher.js +191 -0
- package/dist/utils/folder-matcher.js.map +1 -0
- package/dist/utils/version.d.ts +10 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +88 -0
- package/dist/utils/version.js.map +1 -0
- package/docs/plugin-api/Calendar.md +448 -0
- package/docs/plugin-api/CalendarItem.md +198 -0
- package/docs/plugin-api/Clipboard.md +101 -0
- package/docs/plugin-api/CommandBar.md +251 -0
- package/docs/plugin-api/DataStore.md +700 -0
- package/docs/plugin-api/Editor.md +982 -0
- package/docs/plugin-api/HTMLView.md +337 -0
- package/docs/plugin-api/NoteObject.md +588 -0
- package/docs/plugin-api/NotePlan.md +398 -0
- package/docs/plugin-api/ParagraphObject.md +242 -0
- package/docs/plugin-api/RangeObject.md +56 -0
- package/docs/plugin-api/getting-started.md +545 -0
- package/docs/plugin-api/plugin-api-condensed.md +526 -0
- package/docs/plugin-api/plugin.json +26 -0
- package/docs/plugin-api/script.js +542 -0
- package/package.json +60 -0
- package/scripts/calendar-helper +0 -0
- package/scripts/reminders-helper +0 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,2468 @@
|
|
|
1
|
+
// MCP Server with tool registration
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
// Import tool implementations
|
|
9
|
+
import * as noteTools from './tools/notes.js';
|
|
10
|
+
import * as searchTools from './tools/search.js';
|
|
11
|
+
import * as taskTools from './tools/tasks.js';
|
|
12
|
+
import * as calendarTools from './tools/calendar.js';
|
|
13
|
+
import * as spaceTools from './tools/spaces.js';
|
|
14
|
+
import * as filterTools from './tools/filters.js';
|
|
15
|
+
import * as eventTools from './tools/events.js';
|
|
16
|
+
import * as reminderTools from './tools/reminders.js';
|
|
17
|
+
import * as embeddingsTools from './tools/embeddings.js';
|
|
18
|
+
import * as memoryTools from './tools/memory.js';
|
|
19
|
+
import * as uiTools from './tools/ui.js';
|
|
20
|
+
import * as pluginTools from './tools/plugins.js';
|
|
21
|
+
import * as themeTools from './tools/themes.js';
|
|
22
|
+
import { parseFlexibleDate } from './utils/date-utils.js';
|
|
23
|
+
import { upgradeMessage, getNotePlanVersion, MIN_BUILD_ADVANCED_FEATURES } from './utils/version.js';
|
|
24
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
25
|
+
const __dirname = path.dirname(__filename);
|
|
26
|
+
const PLUGIN_API_DOCS_DIR = path.join(__dirname, '../docs/plugin-api');
|
|
27
|
+
const PLUGIN_API_RESOURCES = [
|
|
28
|
+
{ file: 'plugin-api-condensed.md', name: 'Plugin API Reference (Condensed)', desc: 'Complete NotePlan plugin API — all signatures, types, and patterns in one reference. Read this first.' },
|
|
29
|
+
{ file: 'getting-started.md', name: 'Getting Started Guide', desc: 'How to create NotePlan plugins — structure, setup, first plugin, testing, HTML views' },
|
|
30
|
+
{ file: 'Editor.md', name: 'Editor API', desc: 'Note manipulation — insertText, paragraphs, selection, themes, openNoteByTitle' },
|
|
31
|
+
{ file: 'DataStore.md', name: 'DataStore API', desc: 'Data access — folders, notes, preferences, teamspaces, hashtags' },
|
|
32
|
+
{ file: 'NoteObject.md', name: 'Note Object', desc: 'Note properties/methods — content, paragraphs, frontmatter, dates' },
|
|
33
|
+
{ file: 'Calendar.md', name: 'Calendar API', desc: 'Calendar events and reminders — add, update, query' },
|
|
34
|
+
{ file: 'NotePlan.md', name: 'NotePlan API', desc: 'Core globals — environment, AI, themes, settings' },
|
|
35
|
+
{ file: 'CommandBar.md', name: 'CommandBar API', desc: 'User interaction — showOptions, showInput, showLoading, textPrompt' },
|
|
36
|
+
{ file: 'HTMLView.md', name: 'HTMLView API', desc: 'HTML views — showWindow, showInMainWindow, showInSplitView, JS bridge' },
|
|
37
|
+
{ file: 'CalendarItem.md', name: 'CalendarItem Object', desc: 'Calendar event/reminder structure and properties' },
|
|
38
|
+
{ file: 'ParagraphObject.md', name: 'Paragraph Object', desc: 'Paragraph structure — type, content, heading level, indents, links' },
|
|
39
|
+
{ file: 'Clipboard.md', name: 'Clipboard API', desc: 'Read/write system clipboard' },
|
|
40
|
+
{ file: 'RangeObject.md', name: 'Range Object', desc: 'Text range — start, end, length for selections' },
|
|
41
|
+
{ file: 'plugin.json', name: 'Demo plugin.json', desc: 'Example plugin manifest — ID, name, commands, settings, dependencies' },
|
|
42
|
+
{ file: 'script.js', name: 'Demo script.js', desc: 'Example plugin implementation with multiple API usage examples' },
|
|
43
|
+
];
|
|
44
|
+
function normalizeToolName(name) {
|
|
45
|
+
const separatorIndex = name.lastIndexOf(':');
|
|
46
|
+
if (separatorIndex === -1)
|
|
47
|
+
return name;
|
|
48
|
+
const normalized = name.slice(separatorIndex + 1).trim();
|
|
49
|
+
return normalized || name;
|
|
50
|
+
}
|
|
51
|
+
function outputSchemaWithErrors(properties = {}) {
|
|
52
|
+
return {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: {
|
|
55
|
+
success: { type: 'boolean' },
|
|
56
|
+
durationMs: { type: 'number' },
|
|
57
|
+
stageTimings: {
|
|
58
|
+
type: 'object',
|
|
59
|
+
additionalProperties: { type: 'number' },
|
|
60
|
+
},
|
|
61
|
+
performanceHints: {
|
|
62
|
+
type: 'array',
|
|
63
|
+
items: { type: 'string' },
|
|
64
|
+
},
|
|
65
|
+
suggestedNextTools: {
|
|
66
|
+
type: 'array',
|
|
67
|
+
items: { type: 'string' },
|
|
68
|
+
},
|
|
69
|
+
memoryHints: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
storedMemories: { type: 'number' },
|
|
73
|
+
tip: { type: 'string' },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
...properties,
|
|
77
|
+
error: { type: 'string' },
|
|
78
|
+
code: { type: 'string' },
|
|
79
|
+
hint: { type: 'string' },
|
|
80
|
+
suggestedTool: { type: 'string' },
|
|
81
|
+
retryable: { type: 'boolean' },
|
|
82
|
+
},
|
|
83
|
+
required: ['success'],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const GENERIC_TOOL_OUTPUT_SCHEMA = outputSchemaWithErrors();
|
|
87
|
+
const MESSAGE_OUTPUT_SCHEMA = outputSchemaWithErrors({ message: { type: 'string' } });
|
|
88
|
+
const NOTE_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
89
|
+
note: { type: 'object' },
|
|
90
|
+
created: { type: 'boolean' },
|
|
91
|
+
contentIncluded: { type: 'boolean' },
|
|
92
|
+
contentLength: { type: 'number' },
|
|
93
|
+
lineCount: { type: 'number' },
|
|
94
|
+
preview: { type: 'string' },
|
|
95
|
+
previewTruncated: { type: 'boolean' },
|
|
96
|
+
rangeStartLine: { type: 'number' },
|
|
97
|
+
rangeEndLine: { type: 'number' },
|
|
98
|
+
rangeLineCount: { type: 'number' },
|
|
99
|
+
returnedLineCount: { type: 'number' },
|
|
100
|
+
offset: { type: 'number' },
|
|
101
|
+
limit: { type: 'number' },
|
|
102
|
+
hasMore: { type: 'boolean' },
|
|
103
|
+
nextCursor: { type: ['string', 'null'] },
|
|
104
|
+
content: { type: 'string' },
|
|
105
|
+
lines: { type: 'array', items: { type: 'object' } },
|
|
106
|
+
});
|
|
107
|
+
const NOTES_LIST_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
108
|
+
count: { type: 'number' },
|
|
109
|
+
totalCount: { type: 'number' },
|
|
110
|
+
offset: { type: 'number' },
|
|
111
|
+
limit: { type: 'number' },
|
|
112
|
+
hasMore: { type: 'boolean' },
|
|
113
|
+
nextCursor: { type: ['string', 'null'] },
|
|
114
|
+
notes: { type: 'array', items: { type: 'object' } },
|
|
115
|
+
});
|
|
116
|
+
const RESOLVE_NOTE_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
117
|
+
query: { type: 'string' },
|
|
118
|
+
count: { type: 'number' },
|
|
119
|
+
exactMatch: { type: 'boolean' },
|
|
120
|
+
ambiguous: { type: 'boolean' },
|
|
121
|
+
confidence: { type: 'number' },
|
|
122
|
+
confidenceDelta: { type: 'number' },
|
|
123
|
+
resolved: { type: ['object', 'null'] },
|
|
124
|
+
suggestedGetNoteArgs: { type: ['object', 'null'] },
|
|
125
|
+
candidates: { type: 'array', items: { type: 'object' } },
|
|
126
|
+
});
|
|
127
|
+
const SEARCH_NOTES_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
128
|
+
query: { type: 'string' },
|
|
129
|
+
searchField: { type: 'string' },
|
|
130
|
+
queryMode: { type: 'string' },
|
|
131
|
+
effectiveQuery: { type: 'string' },
|
|
132
|
+
tokenTerms: { type: 'array', items: { type: 'string' } },
|
|
133
|
+
minTokenMatches: { type: 'number' },
|
|
134
|
+
count: { type: 'number' },
|
|
135
|
+
propertyFilters: { type: 'object', additionalProperties: { type: 'string' } },
|
|
136
|
+
propertyCaseSensitive: { type: 'boolean' },
|
|
137
|
+
partialResults: { type: 'boolean' },
|
|
138
|
+
searchBackend: { type: 'string' },
|
|
139
|
+
warnings: { type: 'array', items: { type: 'string' } },
|
|
140
|
+
results: { type: 'array', items: { type: 'object' } },
|
|
141
|
+
});
|
|
142
|
+
const RANGE_NOTES_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
143
|
+
period: { type: 'string' },
|
|
144
|
+
startDate: { type: 'string' },
|
|
145
|
+
endDate: { type: 'string' },
|
|
146
|
+
noteCount: { type: 'number' },
|
|
147
|
+
totalDays: { type: 'number' },
|
|
148
|
+
scannedDays: { type: 'number' },
|
|
149
|
+
truncatedByMaxDays: { type: 'boolean' },
|
|
150
|
+
maxDays: { type: 'number' },
|
|
151
|
+
offset: { type: 'number' },
|
|
152
|
+
limit: { type: 'number' },
|
|
153
|
+
hasMore: { type: 'boolean' },
|
|
154
|
+
nextCursor: { type: ['string', 'null'] },
|
|
155
|
+
notes: { type: 'array', items: { type: 'object' } },
|
|
156
|
+
});
|
|
157
|
+
const FOLDER_NOTES_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
158
|
+
folder: { type: 'string' },
|
|
159
|
+
noteCount: { type: 'number' },
|
|
160
|
+
totalInFolder: { type: 'number' },
|
|
161
|
+
offset: { type: 'number' },
|
|
162
|
+
limit: { type: 'number' },
|
|
163
|
+
hasMore: { type: 'boolean' },
|
|
164
|
+
nextCursor: { type: ['string', 'null'] },
|
|
165
|
+
notes: { type: 'array', items: { type: 'object' } },
|
|
166
|
+
});
|
|
167
|
+
const SPACES_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
168
|
+
count: { type: 'number' },
|
|
169
|
+
totalCount: { type: 'number' },
|
|
170
|
+
offset: { type: 'number' },
|
|
171
|
+
limit: { type: 'number' },
|
|
172
|
+
hasMore: { type: 'boolean' },
|
|
173
|
+
nextCursor: { type: ['string', 'null'] },
|
|
174
|
+
spaces: { type: 'array', items: { type: 'object' } },
|
|
175
|
+
});
|
|
176
|
+
const TAGS_OUTPUT_SCHEMA = outputSchemaWithErrors({
|
|
177
|
+
count: { type: 'number' },
|
|
178
|
+
totalCount: { type: 'number' },
|
|
179
|
+
offset: { type: 'number' },
|
|
180
|
+
limit: { type: 'number' },
|
|
181
|
+
hasMore: { type: 'boolean' },
|
|
182
|
+
nextCursor: { type: ['string', 'null'] },
|
|
183
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
184
|
+
});
|
|
185
|
+
function getToolOutputSchema(toolName) {
|
|
186
|
+
switch (toolName) {
|
|
187
|
+
case 'noteplan_search':
|
|
188
|
+
return SEARCH_NOTES_OUTPUT_SCHEMA;
|
|
189
|
+
// Consolidated tools — use GENERIC since return shape varies by action/route
|
|
190
|
+
case 'noteplan_get_notes':
|
|
191
|
+
case 'noteplan_manage_note':
|
|
192
|
+
case 'noteplan_edit_content':
|
|
193
|
+
case 'noteplan_paragraphs':
|
|
194
|
+
case 'noteplan_folders':
|
|
195
|
+
case 'noteplan_filters':
|
|
196
|
+
case 'noteplan_eventkit':
|
|
197
|
+
case 'noteplan_memory':
|
|
198
|
+
case 'noteplan_ui':
|
|
199
|
+
case 'noteplan_plugins':
|
|
200
|
+
case 'noteplan_themes':
|
|
201
|
+
case 'noteplan_embeddings':
|
|
202
|
+
return GENERIC_TOOL_OUTPUT_SCHEMA;
|
|
203
|
+
default:
|
|
204
|
+
return GENERIC_TOOL_OUTPUT_SCHEMA;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function resolveScheduleDate(dateInput) {
|
|
208
|
+
const compact = parseFlexibleDate(dateInput); // returns YYYYMMDD
|
|
209
|
+
// Convert YYYYMMDD → YYYY-MM-DD for NotePlan scheduling syntax
|
|
210
|
+
const match = compact.match(/^(\d{4})(\d{2})(\d{2})$/);
|
|
211
|
+
if (!match)
|
|
212
|
+
return dateInput; // fallback: use as-is
|
|
213
|
+
return `${match[1]}-${match[2]}-${match[3]}`;
|
|
214
|
+
}
|
|
215
|
+
function appendScheduleDate(content, scheduleDate) {
|
|
216
|
+
if (!scheduleDate)
|
|
217
|
+
return content;
|
|
218
|
+
const formatted = resolveScheduleDate(scheduleDate);
|
|
219
|
+
return `${content} >${formatted}`;
|
|
220
|
+
}
|
|
221
|
+
const PERIOD_TYPE_MAP = {
|
|
222
|
+
week: 'weekly',
|
|
223
|
+
month: 'monthly',
|
|
224
|
+
quarter: 'quarterly',
|
|
225
|
+
year: 'yearly',
|
|
226
|
+
};
|
|
227
|
+
function dispatchGetNotes(args) {
|
|
228
|
+
const { resolve, resolveQuery, id, title, filename, date, period, count, rangePeriod, startDate, endDate, folder, space, types, query, limit, offset, cursor, minScore, ambiguityDelta,
|
|
229
|
+
// periodic note params
|
|
230
|
+
week, month, quarter, year, fromDate, includeContent, includeMissing, maxLookback,
|
|
231
|
+
// range params
|
|
232
|
+
maxDays, } = args;
|
|
233
|
+
// 1. resolve mode
|
|
234
|
+
if (resolve) {
|
|
235
|
+
return noteTools.resolveNote({
|
|
236
|
+
query: resolveQuery ?? query,
|
|
237
|
+
space, folder, types, limit, minScore, ambiguityDelta,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// 2. single note by identifier
|
|
241
|
+
if (id || title || filename) {
|
|
242
|
+
return noteTools.getNote(args);
|
|
243
|
+
}
|
|
244
|
+
// 3. recent periodic notes (period + count)
|
|
245
|
+
if (period && count) {
|
|
246
|
+
const periodicType = PERIOD_TYPE_MAP[period] ?? period;
|
|
247
|
+
return calendarTools.getRecentPeriodicNotes({
|
|
248
|
+
type: periodicType, count, fromDate, includeContent, includeMissing, maxLookback, space,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
// 4. single periodic note (period, no count)
|
|
252
|
+
if (period && !count) {
|
|
253
|
+
const periodicType = PERIOD_TYPE_MAP[period] ?? period;
|
|
254
|
+
return calendarTools.getPeriodicNote({
|
|
255
|
+
type: periodicType, date, week, month, quarter, year, space,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
// 5. date range
|
|
259
|
+
if (rangePeriod || (startDate && endDate)) {
|
|
260
|
+
return calendarTools.getNotesInRange({
|
|
261
|
+
period: rangePeriod ?? 'custom', startDate, endDate, includeContent, maxDays, limit, offset, cursor, space,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
// 6. folder listing (no id/title/filename/date)
|
|
265
|
+
if (folder && !date) {
|
|
266
|
+
return calendarTools.getNotesInFolder({
|
|
267
|
+
folder, includeContent, limit, offset, cursor, space,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
// 7. calendar note by date
|
|
271
|
+
if (date) {
|
|
272
|
+
return calendarTools.getCalendarNote({ date, space });
|
|
273
|
+
}
|
|
274
|
+
// 8. fallback: list notes
|
|
275
|
+
return noteTools.listNotes({
|
|
276
|
+
folder, space, types, query, limit, offset, cursor,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
function toBoundedInt(value, defaultValue, min, max) {
|
|
280
|
+
const numeric = typeof value === 'number' ? value : Number(value);
|
|
281
|
+
if (!Number.isFinite(numeric))
|
|
282
|
+
return defaultValue;
|
|
283
|
+
return Math.min(max, Math.max(min, Math.floor(numeric)));
|
|
284
|
+
}
|
|
285
|
+
function isDebugTimingsEnabled(args) {
|
|
286
|
+
if (!args || typeof args !== 'object')
|
|
287
|
+
return false;
|
|
288
|
+
const rawValue = args.debugTimings;
|
|
289
|
+
if (typeof rawValue === 'boolean')
|
|
290
|
+
return rawValue;
|
|
291
|
+
if (typeof rawValue === 'string') {
|
|
292
|
+
const normalized = rawValue.trim().toLowerCase();
|
|
293
|
+
return normalized === 'true' || normalized === '1';
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
function withDebugTimingsInputSchema(inputSchema) {
|
|
298
|
+
const schema = { ...inputSchema };
|
|
299
|
+
const properties = schema.properties && typeof schema.properties === 'object'
|
|
300
|
+
? { ...schema.properties }
|
|
301
|
+
: {};
|
|
302
|
+
if (!('debugTimings' in properties)) {
|
|
303
|
+
properties.debugTimings = {
|
|
304
|
+
type: 'boolean',
|
|
305
|
+
description: 'Include durationMs timing metadata in response (default: false)',
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
schema.properties = properties;
|
|
309
|
+
return schema;
|
|
310
|
+
}
|
|
311
|
+
function compactDescription(description, maxLength = 120) {
|
|
312
|
+
const firstLine = description
|
|
313
|
+
.split('\n')
|
|
314
|
+
.map((line) => line.trim())
|
|
315
|
+
.find((line) => line.length > 0) ?? '';
|
|
316
|
+
if (firstLine.length <= maxLength)
|
|
317
|
+
return firstLine;
|
|
318
|
+
return `${firstLine.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
319
|
+
}
|
|
320
|
+
function stripDescriptions(value) {
|
|
321
|
+
if (Array.isArray(value)) {
|
|
322
|
+
return value.map((item) => stripDescriptions(item));
|
|
323
|
+
}
|
|
324
|
+
if (!value || typeof value !== 'object') {
|
|
325
|
+
return value;
|
|
326
|
+
}
|
|
327
|
+
const input = value;
|
|
328
|
+
const output = {};
|
|
329
|
+
for (const [key, nested] of Object.entries(input)) {
|
|
330
|
+
if (key === 'description')
|
|
331
|
+
continue;
|
|
332
|
+
output[key] = stripDescriptions(nested);
|
|
333
|
+
}
|
|
334
|
+
return output;
|
|
335
|
+
}
|
|
336
|
+
function compactToolDefinition(tool, maxDescLength = 120) {
|
|
337
|
+
return {
|
|
338
|
+
name: tool.name,
|
|
339
|
+
description: compactDescription(tool.description, maxDescLength),
|
|
340
|
+
inputSchema: stripDescriptions(tool.inputSchema),
|
|
341
|
+
annotations: tool.annotations,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function getToolAnnotations(toolName) {
|
|
345
|
+
// Read-only tools
|
|
346
|
+
const readOnlyTools = new Set([
|
|
347
|
+
'noteplan_get_notes',
|
|
348
|
+
'noteplan_search',
|
|
349
|
+
]);
|
|
350
|
+
// Consolidated tools with mixed read+write actions get pessimistic annotations
|
|
351
|
+
const destructiveTools = new Set([
|
|
352
|
+
'noteplan_manage_note',
|
|
353
|
+
'noteplan_edit_content',
|
|
354
|
+
'noteplan_paragraphs',
|
|
355
|
+
'noteplan_folders',
|
|
356
|
+
'noteplan_filters',
|
|
357
|
+
'noteplan_eventkit',
|
|
358
|
+
'noteplan_memory',
|
|
359
|
+
'noteplan_plugins',
|
|
360
|
+
'noteplan_themes',
|
|
361
|
+
'noteplan_embeddings',
|
|
362
|
+
]);
|
|
363
|
+
const nonIdempotentTools = new Set([
|
|
364
|
+
'noteplan_manage_note',
|
|
365
|
+
'noteplan_edit_content',
|
|
366
|
+
'noteplan_paragraphs',
|
|
367
|
+
'noteplan_folders',
|
|
368
|
+
'noteplan_filters',
|
|
369
|
+
'noteplan_eventkit',
|
|
370
|
+
'noteplan_memory',
|
|
371
|
+
'noteplan_ui',
|
|
372
|
+
'noteplan_plugins',
|
|
373
|
+
'noteplan_themes',
|
|
374
|
+
'noteplan_embeddings',
|
|
375
|
+
]);
|
|
376
|
+
const openWorldTools = new Set([
|
|
377
|
+
'noteplan_eventkit',
|
|
378
|
+
'noteplan_embeddings',
|
|
379
|
+
'noteplan_plugins',
|
|
380
|
+
]);
|
|
381
|
+
return {
|
|
382
|
+
readOnlyHint: readOnlyTools.has(toolName),
|
|
383
|
+
destructiveHint: destructiveTools.has(toolName),
|
|
384
|
+
idempotentHint: !nonIdempotentTools.has(toolName),
|
|
385
|
+
openWorldHint: openWorldTools.has(toolName),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const QUERY_SYNONYMS = {
|
|
389
|
+
todo: ['task', 'tasks', 'reminder', 'reminders', 'checklist'],
|
|
390
|
+
tasks: ['task', 'todo', 'reminder'],
|
|
391
|
+
meeting: ['calendar', 'event', 'schedule', 'appointment'],
|
|
392
|
+
events: ['event', 'calendar', 'schedule', 'meeting'],
|
|
393
|
+
workspace: ['space', 'spaces', 'teamspace'],
|
|
394
|
+
teamspace: ['space', 'workspace', 'spaces'],
|
|
395
|
+
folder: ['folders', 'directory', 'path', 'project'],
|
|
396
|
+
projects: ['project', 'folder'],
|
|
397
|
+
resolve: ['disambiguate', 'canonical', 'match'],
|
|
398
|
+
disambiguate: ['resolve', 'canonical', 'match'],
|
|
399
|
+
edit: ['update', 'modify', 'change'],
|
|
400
|
+
delete: ['remove', 'erase', 'clear'],
|
|
401
|
+
restore: ['recover', 'undo', 'undelete'],
|
|
402
|
+
create: ['add', 'new', 'make'],
|
|
403
|
+
paragraph: ['line', 'block', 'section', 'text'],
|
|
404
|
+
lines: ['line', 'paragraph', 'content'],
|
|
405
|
+
embeddings: ['semantic', 'vector', 'similarity', 'meaning'],
|
|
406
|
+
semantic: ['embeddings', 'vector', 'similarity'],
|
|
407
|
+
};
|
|
408
|
+
function getToolSearchAliases(toolName) {
|
|
409
|
+
const aliases = [];
|
|
410
|
+
switch (toolName) {
|
|
411
|
+
case 'noteplan_get_notes':
|
|
412
|
+
aliases.push('notes', 'documents', 'markdown', 'resolve note', 'canonical note', 'disambiguate note', 'today', 'daily note', 'journal', 'calendar note', 'date note', 'weekly notes', 'monthly notes', 'periodic notes', 'quarterly', 'date range', 'this week', 'last week', 'folder notes', 'browse folder', 'list notes');
|
|
413
|
+
break;
|
|
414
|
+
case 'noteplan_search':
|
|
415
|
+
aliases.push('search notes', 'find notes', 'full-text search', 'tags', 'hashtags');
|
|
416
|
+
break;
|
|
417
|
+
case 'noteplan_manage_note':
|
|
418
|
+
aliases.push('create note', 'update note', 'delete note', 'move note', 'rename note', 'restore note', 'frontmatter', 'property', 'set property');
|
|
419
|
+
break;
|
|
420
|
+
case 'noteplan_edit_content':
|
|
421
|
+
aliases.push('insert', 'append', 'edit line', 'delete lines', 'replace lines', 'edit content', 'today', 'daily note');
|
|
422
|
+
break;
|
|
423
|
+
case 'noteplan_paragraphs':
|
|
424
|
+
aliases.push('paragraphs', 'lines', 'line numbers', 'search paragraph', 'find paragraph', 'tasks', 'todos', 'checklist', 'add task', 'complete task', 'update task', 'search tasks', 'global tasks');
|
|
425
|
+
break;
|
|
426
|
+
case 'noteplan_folders':
|
|
427
|
+
aliases.push('folders', 'directory', 'create folder', 'move folder', 'rename folder', 'delete folder', 'resolve folder', 'find folder', 'spaces', 'workspaces', 'teamspaces');
|
|
428
|
+
break;
|
|
429
|
+
case 'noteplan_filters':
|
|
430
|
+
aliases.push('filters', 'saved filters', 'task filters', 'filter parameters', 'run filter');
|
|
431
|
+
break;
|
|
432
|
+
case 'noteplan_eventkit':
|
|
433
|
+
aliases.push('calendar', 'event', 'events', 'schedule', 'meeting', 'appointment', 'create event', 'delete event', 'reminder', 'reminders', 'todo', 'checklist', 'create reminder', 'complete reminder');
|
|
434
|
+
break;
|
|
435
|
+
case 'noteplan_memory':
|
|
436
|
+
aliases.push('memory', 'memories', 'preference', 'preferences', 'remember', 'correction');
|
|
437
|
+
break;
|
|
438
|
+
case 'noteplan_ui':
|
|
439
|
+
aliases.push('ui', 'open note', 'open today', 'search ui', 'run plugin', 'sidebar', 'toggle sidebar');
|
|
440
|
+
break;
|
|
441
|
+
case 'noteplan_plugins':
|
|
442
|
+
aliases.push('plugin', 'plugins', 'extension', 'command', 'addon', 'create plugin', 'install plugin', 'plugin log', 'plugin source', 'screenshot');
|
|
443
|
+
break;
|
|
444
|
+
case 'noteplan_themes':
|
|
445
|
+
aliases.push('theme', 'themes', 'colors', 'dark mode', 'light mode', 'appearance');
|
|
446
|
+
break;
|
|
447
|
+
case 'noteplan_embeddings':
|
|
448
|
+
aliases.push('embeddings', 'semantic search', 'vector search', 'similarity');
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
return aliases;
|
|
452
|
+
}
|
|
453
|
+
function expandQueryTokens(query) {
|
|
454
|
+
const tokens = query
|
|
455
|
+
.toLowerCase()
|
|
456
|
+
.split(/\s+/)
|
|
457
|
+
.map((token) => token.trim())
|
|
458
|
+
.filter(Boolean);
|
|
459
|
+
const expanded = new Set(tokens);
|
|
460
|
+
for (const token of tokens) {
|
|
461
|
+
const synonyms = QUERY_SYNONYMS[token];
|
|
462
|
+
if (!synonyms)
|
|
463
|
+
continue;
|
|
464
|
+
synonyms.forEach((synonym) => expanded.add(synonym));
|
|
465
|
+
}
|
|
466
|
+
return Array.from(expanded);
|
|
467
|
+
}
|
|
468
|
+
function scoreToolMatch(tool, query) {
|
|
469
|
+
const q = query.toLowerCase();
|
|
470
|
+
const name = tool.name.toLowerCase();
|
|
471
|
+
const description = tool.description.toLowerCase();
|
|
472
|
+
const aliases = getToolSearchAliases(tool.name);
|
|
473
|
+
const aliasText = aliases.join(' ').toLowerCase();
|
|
474
|
+
const searchable = `${name} ${description} ${aliasText}`;
|
|
475
|
+
const queryTokens = expandQueryTokens(q);
|
|
476
|
+
if (name === q)
|
|
477
|
+
return 1.0;
|
|
478
|
+
if (name.startsWith(q))
|
|
479
|
+
return 0.95;
|
|
480
|
+
if (name.includes(q))
|
|
481
|
+
return 0.9;
|
|
482
|
+
if (aliases.some((alias) => alias.toLowerCase() === q))
|
|
483
|
+
return 0.88;
|
|
484
|
+
if (description.includes(q))
|
|
485
|
+
return 0.75;
|
|
486
|
+
if (aliasText.includes(q))
|
|
487
|
+
return 0.74;
|
|
488
|
+
if (queryTokens.length === 0)
|
|
489
|
+
return 0;
|
|
490
|
+
const tokenHits = queryTokens.filter((token) => searchable.includes(token)).length;
|
|
491
|
+
return tokenHits > 0 ? tokenHits / queryTokens.length * 0.62 : 0;
|
|
492
|
+
}
|
|
493
|
+
function searchToolDefinitions(tools, query, limit) {
|
|
494
|
+
return tools
|
|
495
|
+
.map((tool) => ({ tool, score: scoreToolMatch(tool, query) }))
|
|
496
|
+
.filter((entry) => entry.score > 0)
|
|
497
|
+
.sort((a, b) => {
|
|
498
|
+
if (Math.abs(a.score - b.score) > 0.001)
|
|
499
|
+
return b.score - a.score;
|
|
500
|
+
return a.tool.name.localeCompare(b.tool.name);
|
|
501
|
+
})
|
|
502
|
+
.slice(0, limit);
|
|
503
|
+
}
|
|
504
|
+
function inferToolErrorMeta(toolName, errorMessage, registeredToolNames) {
|
|
505
|
+
const message = errorMessage.toLowerCase();
|
|
506
|
+
if (message.includes('unknown tool')) {
|
|
507
|
+
const toolList = registeredToolNames?.join(', ') ?? 'noteplan_get_notes, noteplan_search, noteplan_manage_note, noteplan_edit_content, noteplan_paragraphs, noteplan_folders, noteplan_filters, noteplan_eventkit, noteplan_memory';
|
|
508
|
+
return {
|
|
509
|
+
code: 'ERR_UNKNOWN_TOOL',
|
|
510
|
+
hint: `Check tool name spelling. Available tools: ${toolList}.`,
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
if (message.includes('query is required')) {
|
|
514
|
+
return {
|
|
515
|
+
code: 'ERR_QUERY_REQUIRED',
|
|
516
|
+
hint: 'Provide a non-empty query string to run this operation.',
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (message.includes('requires a newer version of noteplan')) {
|
|
520
|
+
return {
|
|
521
|
+
code: 'ERR_VERSION_GATE',
|
|
522
|
+
hint: 'Update NotePlan to the latest version, then retry.',
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
if (message.includes('embeddings are disabled')) {
|
|
526
|
+
return {
|
|
527
|
+
code: 'ERR_EMBEDDINGS_DISABLED',
|
|
528
|
+
hint: 'Enable embeddings in MCP env: NOTEPLAN_EMBEDDINGS_ENABLED=true.',
|
|
529
|
+
suggestedTool: 'noteplan_embeddings',
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
if (message.includes('embeddings api key is missing')) {
|
|
533
|
+
return {
|
|
534
|
+
code: 'ERR_EMBEDDINGS_NOT_CONFIGURED',
|
|
535
|
+
hint: 'Set NOTEPLAN_EMBEDDINGS_API_KEY (and optionally provider/model/base URL), then retry sync/search.',
|
|
536
|
+
suggestedTool: 'noteplan_embeddings',
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
if (message.includes('provide one note reference')) {
|
|
540
|
+
return {
|
|
541
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
542
|
+
hint: 'Pass one of: id, filename, title, or date to identify the note target.',
|
|
543
|
+
suggestedTool: 'noteplan_get_notes',
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
if (message.includes('provide lineindex') ||
|
|
547
|
+
message.includes('lineindex must be') ||
|
|
548
|
+
message.includes('line must be') ||
|
|
549
|
+
message.includes('line and lineindex reference different')) {
|
|
550
|
+
return {
|
|
551
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
552
|
+
hint: 'For task updates, pass either lineIndex (0-based) or line (1-based).',
|
|
553
|
+
suggestedTool: 'noteplan_paragraphs',
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
if (message.includes('provide at least one field to update')) {
|
|
557
|
+
return {
|
|
558
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
559
|
+
hint: 'For noteplan_paragraphs(action=update), pass content, status, or both.',
|
|
560
|
+
suggestedTool: 'noteplan_paragraphs',
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
if (message.includes('empty content is blocked') || message.includes('empty line content is blocked') || message.includes('empty task content is blocked')) {
|
|
564
|
+
return {
|
|
565
|
+
code: 'ERR_EMPTY_CONTENT_BLOCKED',
|
|
566
|
+
hint: 'Use allowEmptyContent=true for intentional clears, or use noteplan_edit_content(action=delete_lines).',
|
|
567
|
+
suggestedTool: 'noteplan_edit_content',
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (message.includes('empty replacement content is blocked')) {
|
|
571
|
+
return {
|
|
572
|
+
code: 'ERR_EMPTY_CONTENT_BLOCKED',
|
|
573
|
+
hint: 'Use noteplan_edit_content(action=delete_lines) for deletion, or set allowEmptyContent=true.',
|
|
574
|
+
suggestedTool: 'noteplan_edit_content',
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
if (message.includes('supported for local notes only') || message.includes('supported for project notes only')) {
|
|
578
|
+
return {
|
|
579
|
+
code: 'ERR_UNSUPPORTED_TARGET',
|
|
580
|
+
hint: 'These tools currently operate on local project notes under Notes/.',
|
|
581
|
+
suggestedTool: 'noteplan_get_notes',
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
if (message.includes('not in teamspace @trash') || message.includes('local note is not in @trash')) {
|
|
585
|
+
return {
|
|
586
|
+
code: 'ERR_NOT_IN_TRASH',
|
|
587
|
+
hint: 'Restore only works for notes currently in trash.',
|
|
588
|
+
suggestedTool: 'noteplan_manage_note',
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
if (message.includes('note is in trash')) {
|
|
592
|
+
return {
|
|
593
|
+
code: 'ERR_NOTE_IN_TRASH',
|
|
594
|
+
hint: 'Use noteplan_manage_note(action=restore) to recover this note, then retry.',
|
|
595
|
+
suggestedTool: 'noteplan_manage_note',
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
if (message.includes('full note replacement is blocked')) {
|
|
599
|
+
return {
|
|
600
|
+
code: 'ERR_FULL_REPLACE_CONFIRMATION_REQUIRED',
|
|
601
|
+
hint: 'Set fullReplace=true only for intentional whole-note rewrites; otherwise use noteplan_edit_content.',
|
|
602
|
+
suggestedTool: 'noteplan_paragraphs',
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
if (message.includes('confirmation token is required')) {
|
|
606
|
+
return {
|
|
607
|
+
code: 'ERR_CONFIRMATION_REQUIRED',
|
|
608
|
+
hint: 'Run the same destructive tool with dryRun=true to get a confirmationToken, then retry with that token.',
|
|
609
|
+
suggestedTool: toolName,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
if (message.includes('confirmation token is invalid') || message.includes('confirmation token is expired')) {
|
|
613
|
+
return {
|
|
614
|
+
code: 'ERR_CONFIRMATION_INVALID',
|
|
615
|
+
hint: 'Regenerate the token by rerunning the same tool with dryRun=true, then retry promptly.',
|
|
616
|
+
suggestedTool: toolName,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
if (message.includes('line') && (message.includes('does not exist') || message.includes('invalid line index'))) {
|
|
620
|
+
return {
|
|
621
|
+
code: 'ERR_INVALID_LINE_REFERENCE',
|
|
622
|
+
hint: 'Fetch valid line numbers first with noteplan_paragraphs.',
|
|
623
|
+
suggestedTool: 'noteplan_paragraphs',
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
if (message.includes('ambiguous')) {
|
|
627
|
+
return {
|
|
628
|
+
code: 'ERR_AMBIGUOUS_TARGET',
|
|
629
|
+
hint: 'Resolve the target first, then retry with the canonical identifier.',
|
|
630
|
+
suggestedTool: toolName.includes('folder') ? 'noteplan_folders' : 'noteplan_get_notes',
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
if (message.includes('not found') && toolName.includes('filter')) {
|
|
634
|
+
return {
|
|
635
|
+
code: 'ERR_NOT_FOUND',
|
|
636
|
+
hint: 'List filters first, then retry with an exact filter name.',
|
|
637
|
+
suggestedTool: 'noteplan_filters',
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
if (message.includes('not found')) {
|
|
641
|
+
if (toolName.includes('folder')) {
|
|
642
|
+
return {
|
|
643
|
+
code: 'ERR_NOT_FOUND',
|
|
644
|
+
hint: 'Resolve the folder first to a canonical path, then retry.',
|
|
645
|
+
suggestedTool: 'noteplan_folders',
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
code: 'ERR_NOT_FOUND',
|
|
650
|
+
hint: 'Resolve the note first to a canonical ID/filename, then retry.',
|
|
651
|
+
suggestedTool: 'noteplan_get_notes',
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
if (message.includes('timed out') || message.includes('timeout')) {
|
|
655
|
+
return {
|
|
656
|
+
code: 'ERR_TIMEOUT',
|
|
657
|
+
hint: 'Try a narrower query or smaller range and retry.',
|
|
658
|
+
retryable: true,
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
return {
|
|
662
|
+
code: 'ERR_TOOL_EXECUTION',
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function enrichErrorResult(result, toolName, registeredToolNames) {
|
|
666
|
+
if (!result || typeof result !== 'object')
|
|
667
|
+
return result;
|
|
668
|
+
const typed = result;
|
|
669
|
+
if (typed.success !== false)
|
|
670
|
+
return result;
|
|
671
|
+
if (typeof typed.error !== 'string')
|
|
672
|
+
return result;
|
|
673
|
+
const meta = inferToolErrorMeta(toolName, typed.error, registeredToolNames);
|
|
674
|
+
return {
|
|
675
|
+
...typed,
|
|
676
|
+
code: typeof typed.code === 'string' ? typed.code : meta.code,
|
|
677
|
+
hint: typeof typed.hint === 'string' ? typed.hint : meta.hint,
|
|
678
|
+
suggestedTool: typeof typed.suggestedTool === 'string' ? typed.suggestedTool : meta.suggestedTool,
|
|
679
|
+
retryable: typeof typed.retryable === 'boolean' ? typed.retryable : meta.retryable,
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function withSuggestedNextTools(result, toolName, availableToolNames) {
|
|
683
|
+
if (!result || typeof result !== 'object' || Array.isArray(result))
|
|
684
|
+
return result;
|
|
685
|
+
const typed = result;
|
|
686
|
+
if (typed.success !== true)
|
|
687
|
+
return result;
|
|
688
|
+
if (Array.isArray(typed.suggestedNextTools) && typed.suggestedNextTools.length > 0)
|
|
689
|
+
return result;
|
|
690
|
+
let suggestedNextTools = [];
|
|
691
|
+
switch (toolName) {
|
|
692
|
+
case 'noteplan_get_notes':
|
|
693
|
+
suggestedNextTools = ['noteplan_paragraphs', 'noteplan_edit_content'];
|
|
694
|
+
break;
|
|
695
|
+
case 'noteplan_paragraphs':
|
|
696
|
+
suggestedNextTools = ['noteplan_edit_content', 'noteplan_get_notes'];
|
|
697
|
+
break;
|
|
698
|
+
case 'noteplan_edit_content':
|
|
699
|
+
suggestedNextTools = ['noteplan_paragraphs', 'noteplan_get_notes'];
|
|
700
|
+
break;
|
|
701
|
+
case 'noteplan_search':
|
|
702
|
+
suggestedNextTools = ['noteplan_get_notes', 'noteplan_paragraphs'];
|
|
703
|
+
break;
|
|
704
|
+
case 'noteplan_manage_note':
|
|
705
|
+
suggestedNextTools = ['noteplan_get_notes'];
|
|
706
|
+
break;
|
|
707
|
+
case 'noteplan_folders':
|
|
708
|
+
suggestedNextTools = ['noteplan_manage_note', 'noteplan_get_notes'];
|
|
709
|
+
break;
|
|
710
|
+
case 'noteplan_filters':
|
|
711
|
+
suggestedNextTools = ['noteplan_paragraphs', 'noteplan_filters'];
|
|
712
|
+
break;
|
|
713
|
+
case 'noteplan_eventkit':
|
|
714
|
+
suggestedNextTools = ['noteplan_eventkit'];
|
|
715
|
+
break;
|
|
716
|
+
case 'noteplan_memory':
|
|
717
|
+
suggestedNextTools = ['noteplan_memory'];
|
|
718
|
+
break;
|
|
719
|
+
case 'noteplan_embeddings':
|
|
720
|
+
suggestedNextTools = ['noteplan_get_notes', 'noteplan_embeddings'];
|
|
721
|
+
break;
|
|
722
|
+
case 'noteplan_plugins':
|
|
723
|
+
suggestedNextTools = ['noteplan_plugins', 'noteplan_ui'];
|
|
724
|
+
break;
|
|
725
|
+
case 'noteplan_themes':
|
|
726
|
+
suggestedNextTools = ['noteplan_themes'];
|
|
727
|
+
break;
|
|
728
|
+
default:
|
|
729
|
+
suggestedNextTools = [];
|
|
730
|
+
}
|
|
731
|
+
const filtered = availableToolNames
|
|
732
|
+
? suggestedNextTools.filter((t) => availableToolNames.has(t))
|
|
733
|
+
: suggestedNextTools;
|
|
734
|
+
if (filtered.length === 0)
|
|
735
|
+
return result;
|
|
736
|
+
return {
|
|
737
|
+
...typed,
|
|
738
|
+
suggestedNextTools: filtered.slice(0, 3),
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
const MEMORY_HINT_TOOLS = new Set([
|
|
742
|
+
'noteplan_edit_content',
|
|
743
|
+
'noteplan_paragraphs',
|
|
744
|
+
'noteplan_manage_note',
|
|
745
|
+
]);
|
|
746
|
+
function withMemoryHints(result, toolName) {
|
|
747
|
+
if (!MEMORY_HINT_TOOLS.has(toolName))
|
|
748
|
+
return result;
|
|
749
|
+
if (!result || typeof result !== 'object' || Array.isArray(result))
|
|
750
|
+
return result;
|
|
751
|
+
const typed = result;
|
|
752
|
+
if (typed.success !== true)
|
|
753
|
+
return result;
|
|
754
|
+
try {
|
|
755
|
+
const count = memoryTools.getMemoryCount();
|
|
756
|
+
if (count === 0)
|
|
757
|
+
return result; // Skip hint noise when no memories stored
|
|
758
|
+
return {
|
|
759
|
+
...typed,
|
|
760
|
+
memoryHints: {
|
|
761
|
+
storedMemories: count,
|
|
762
|
+
tip: `You have ${count} stored memory/memories. Consider checking noteplan_memory (action: list) before making formatting or style decisions.`,
|
|
763
|
+
},
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
catch {
|
|
767
|
+
return result;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function withDuration(result, durationMs, includeTiming) {
|
|
771
|
+
if (!includeTiming)
|
|
772
|
+
return result;
|
|
773
|
+
if (result && typeof result === 'object' && !Array.isArray(result)) {
|
|
774
|
+
return {
|
|
775
|
+
...result,
|
|
776
|
+
durationMs,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
return {
|
|
780
|
+
success: true,
|
|
781
|
+
data: result,
|
|
782
|
+
durationMs,
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
// Create the server
|
|
786
|
+
export function createServer() {
|
|
787
|
+
const server = new Server({
|
|
788
|
+
name: 'noteplan-mcp',
|
|
789
|
+
version: '1.0.0',
|
|
790
|
+
}, {
|
|
791
|
+
capabilities: {
|
|
792
|
+
tools: {},
|
|
793
|
+
resources: {},
|
|
794
|
+
},
|
|
795
|
+
});
|
|
796
|
+
const embeddingsToolsEnabled = embeddingsTools.areEmbeddingsToolsEnabled();
|
|
797
|
+
const versionInfo = getNotePlanVersion();
|
|
798
|
+
const advancedFeaturesEnabled = versionInfo.build >= MIN_BUILD_ADVANCED_FEATURES;
|
|
799
|
+
console.error(`[noteplan-mcp] Detected NotePlan ${versionInfo.version} (build ${versionInfo.build}, source: ${versionInfo.source}). Advanced features: ${advancedFeaturesEnabled ? 'enabled' : 'disabled'}.`);
|
|
800
|
+
const toolDefinitions = [
|
|
801
|
+
// ── Consolidated tools (16 — action/param-based dispatch) ──
|
|
802
|
+
{
|
|
803
|
+
name: 'noteplan_get_notes',
|
|
804
|
+
description: 'Unified note retrieval: get a single note, list notes, resolve references, fetch today/calendar/periodic notes, date ranges, or folder contents.\n\nRouting:\n- resolve=true + resolveQuery → resolve a note reference to canonical target\n- id/title/filename → get single note (metadata + optional content)\n- period + count → recent periodic notes (e.g., last 6 weekly notes)\n- period (no count) → single periodic note (week/month/quarter/year)\n- rangePeriod or startDate+endDate → daily notes in date range\n- folder (no id/title/filename/date) → notes in folder\n- date → calendar note for that date (use "today" for today\'s note)\n- fallback (no params) → list notes with optional filters',
|
|
805
|
+
inputSchema: {
|
|
806
|
+
type: 'object',
|
|
807
|
+
properties: {
|
|
808
|
+
// Single note params
|
|
809
|
+
id: {
|
|
810
|
+
type: 'string',
|
|
811
|
+
description: 'Note ID (BEST for space notes — get from search results)',
|
|
812
|
+
},
|
|
813
|
+
title: {
|
|
814
|
+
type: 'string',
|
|
815
|
+
description: 'Note title to search for',
|
|
816
|
+
},
|
|
817
|
+
filename: {
|
|
818
|
+
type: 'string',
|
|
819
|
+
description: 'Direct filename/path (for local notes only)',
|
|
820
|
+
},
|
|
821
|
+
date: {
|
|
822
|
+
type: 'string',
|
|
823
|
+
description: 'Date for calendar notes (YYYYMMDD, YYYY-MM-DD, today, tomorrow, yesterday)',
|
|
824
|
+
},
|
|
825
|
+
space: {
|
|
826
|
+
type: 'string',
|
|
827
|
+
description: 'Space name or ID scope',
|
|
828
|
+
},
|
|
829
|
+
includeContent: {
|
|
830
|
+
type: 'boolean',
|
|
831
|
+
description: 'Include note body content (default: false)',
|
|
832
|
+
},
|
|
833
|
+
startLine: {
|
|
834
|
+
type: 'number',
|
|
835
|
+
description: 'First line when includeContent=true (1-indexed)',
|
|
836
|
+
},
|
|
837
|
+
endLine: {
|
|
838
|
+
type: 'number',
|
|
839
|
+
description: 'Last line when includeContent=true (1-indexed)',
|
|
840
|
+
},
|
|
841
|
+
previewChars: {
|
|
842
|
+
type: 'number',
|
|
843
|
+
description: 'Preview length when includeContent=false (default: 280)',
|
|
844
|
+
},
|
|
845
|
+
// Resolve params
|
|
846
|
+
resolve: {
|
|
847
|
+
type: 'boolean',
|
|
848
|
+
description: 'Enable resolve mode: find canonical note from a fuzzy reference',
|
|
849
|
+
},
|
|
850
|
+
resolveQuery: {
|
|
851
|
+
type: 'string',
|
|
852
|
+
description: 'Note reference to resolve (ID, title, filename, or date token)',
|
|
853
|
+
},
|
|
854
|
+
minScore: {
|
|
855
|
+
type: 'number',
|
|
856
|
+
description: 'Minimum score for auto-resolution (default: 0.88)',
|
|
857
|
+
},
|
|
858
|
+
ambiguityDelta: {
|
|
859
|
+
type: 'number',
|
|
860
|
+
description: 'If top scores are within this delta, treat as ambiguous (default: 0.06)',
|
|
861
|
+
},
|
|
862
|
+
// Periodic note params
|
|
863
|
+
period: {
|
|
864
|
+
type: 'string',
|
|
865
|
+
enum: ['week', 'month', 'quarter', 'year'],
|
|
866
|
+
description: 'Periodic note type. With count → recent sequence; without → single period',
|
|
867
|
+
},
|
|
868
|
+
count: {
|
|
869
|
+
type: 'number',
|
|
870
|
+
description: 'Number of recent periodic notes to return (triggers multi-note mode)',
|
|
871
|
+
},
|
|
872
|
+
fromDate: {
|
|
873
|
+
type: 'string',
|
|
874
|
+
description: 'Reference date for periodic notes (YYYY-MM-DD, default: today)',
|
|
875
|
+
},
|
|
876
|
+
includeMissing: {
|
|
877
|
+
type: 'boolean',
|
|
878
|
+
description: 'Include missing period slots in response (default: false)',
|
|
879
|
+
},
|
|
880
|
+
maxLookback: {
|
|
881
|
+
type: 'number',
|
|
882
|
+
description: 'Maximum period slots to inspect (default: 52, max: 260)',
|
|
883
|
+
},
|
|
884
|
+
week: {
|
|
885
|
+
type: 'number',
|
|
886
|
+
description: 'Week number 1-53 (for single periodic note with period=week)',
|
|
887
|
+
},
|
|
888
|
+
month: {
|
|
889
|
+
type: 'number',
|
|
890
|
+
description: 'Month number 1-12 (for single periodic note with period=month)',
|
|
891
|
+
},
|
|
892
|
+
quarter: {
|
|
893
|
+
type: 'number',
|
|
894
|
+
description: 'Quarter 1-4 (for single periodic note with period=quarter)',
|
|
895
|
+
},
|
|
896
|
+
year: {
|
|
897
|
+
type: 'number',
|
|
898
|
+
description: 'Year (e.g., 2025). Defaults to current year.',
|
|
899
|
+
},
|
|
900
|
+
// Date range params
|
|
901
|
+
rangePeriod: {
|
|
902
|
+
type: 'string',
|
|
903
|
+
enum: ['today', 'yesterday', 'this-week', 'last-week', 'this-month', 'last-month', 'custom'],
|
|
904
|
+
description: 'Predefined date range period or "custom" with startDate/endDate',
|
|
905
|
+
},
|
|
906
|
+
startDate: {
|
|
907
|
+
type: 'string',
|
|
908
|
+
description: 'Start date for custom range (YYYY-MM-DD)',
|
|
909
|
+
},
|
|
910
|
+
endDate: {
|
|
911
|
+
type: 'string',
|
|
912
|
+
description: 'End date for custom range (YYYY-MM-DD)',
|
|
913
|
+
},
|
|
914
|
+
maxDays: {
|
|
915
|
+
type: 'number',
|
|
916
|
+
description: 'Maximum days to scan for date range (default: 90, max: 366)',
|
|
917
|
+
},
|
|
918
|
+
// List/folder params
|
|
919
|
+
folder: {
|
|
920
|
+
type: 'string',
|
|
921
|
+
description: 'Folder path filter (e.g., "20 - Areas" or "Notes/20 - Areas")',
|
|
922
|
+
},
|
|
923
|
+
types: {
|
|
924
|
+
type: 'array',
|
|
925
|
+
items: { type: 'string', enum: ['calendar', 'note', 'trash'] },
|
|
926
|
+
description: 'Filter by note types',
|
|
927
|
+
},
|
|
928
|
+
query: {
|
|
929
|
+
type: 'string',
|
|
930
|
+
description: 'Filter by title/filename/folder substring (list mode) or resolve query',
|
|
931
|
+
},
|
|
932
|
+
// Pagination
|
|
933
|
+
limit: {
|
|
934
|
+
type: 'number',
|
|
935
|
+
description: 'Maximum results to return',
|
|
936
|
+
},
|
|
937
|
+
offset: {
|
|
938
|
+
type: 'number',
|
|
939
|
+
description: 'Pagination offset (default: 0)',
|
|
940
|
+
},
|
|
941
|
+
cursor: {
|
|
942
|
+
type: 'string',
|
|
943
|
+
description: 'Cursor token from previous page (preferred over offset)',
|
|
944
|
+
},
|
|
945
|
+
},
|
|
946
|
+
},
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
name: 'noteplan_manage_note',
|
|
950
|
+
description: 'Manage notes: create, update, delete, move, restore, rename, or manage frontmatter properties.\n\nActions:\n- create: Create a project note (requires title)\n- update: Replace note content (requires filename, content, fullReplace + confirmationToken)\n- delete/move/restore/rename: Lifecycle ops (requires id or filename + dryRun/confirmationToken)\n- set_property/remove_property: Frontmatter (requires filename + key)',
|
|
951
|
+
inputSchema: {
|
|
952
|
+
type: 'object',
|
|
953
|
+
properties: {
|
|
954
|
+
action: {
|
|
955
|
+
type: 'string',
|
|
956
|
+
enum: ['create', 'update', 'delete', 'move', 'restore', 'rename', 'set_property', 'remove_property'],
|
|
957
|
+
description: 'Action to perform',
|
|
958
|
+
},
|
|
959
|
+
id: {
|
|
960
|
+
type: 'string',
|
|
961
|
+
description: 'Note ID — used by delete, move, rename, restore (preferred for TeamSpace notes)',
|
|
962
|
+
},
|
|
963
|
+
filename: {
|
|
964
|
+
type: 'string',
|
|
965
|
+
description: 'Filename/path — used by update, delete, move, rename, restore, set_property, remove_property',
|
|
966
|
+
},
|
|
967
|
+
title: {
|
|
968
|
+
type: 'string',
|
|
969
|
+
description: 'Note title — required for create',
|
|
970
|
+
},
|
|
971
|
+
content: {
|
|
972
|
+
type: 'string',
|
|
973
|
+
description: 'Note content — used by create (initial content) and update (replacement content)',
|
|
974
|
+
},
|
|
975
|
+
folder: {
|
|
976
|
+
type: 'string',
|
|
977
|
+
description: 'Folder path — used by create (smart matching built in)',
|
|
978
|
+
},
|
|
979
|
+
create_new_folder: {
|
|
980
|
+
type: 'boolean',
|
|
981
|
+
description: 'Bypass smart matching and create exact folder name — used by create',
|
|
982
|
+
},
|
|
983
|
+
space: {
|
|
984
|
+
type: 'string',
|
|
985
|
+
description: 'Space name or ID scope',
|
|
986
|
+
},
|
|
987
|
+
fullReplace: {
|
|
988
|
+
type: 'boolean',
|
|
989
|
+
description: 'Required safety confirmation for whole-note rewrite — used by update',
|
|
990
|
+
},
|
|
991
|
+
dryRun: {
|
|
992
|
+
type: 'boolean',
|
|
993
|
+
description: 'Preview impact and get confirmationToken — used by update, delete, move, rename, restore',
|
|
994
|
+
},
|
|
995
|
+
confirmationToken: {
|
|
996
|
+
type: 'string',
|
|
997
|
+
description: 'Token from dryRun for execution — used by update, delete, move, rename, restore',
|
|
998
|
+
},
|
|
999
|
+
allowEmptyContent: {
|
|
1000
|
+
type: 'boolean',
|
|
1001
|
+
description: 'Allow empty content — used by update',
|
|
1002
|
+
},
|
|
1003
|
+
destinationFolder: {
|
|
1004
|
+
type: 'string',
|
|
1005
|
+
description: 'Target folder — used by move, restore',
|
|
1006
|
+
},
|
|
1007
|
+
newFilename: {
|
|
1008
|
+
type: 'string',
|
|
1009
|
+
description: 'New filename for local notes — used by rename',
|
|
1010
|
+
},
|
|
1011
|
+
newTitle: {
|
|
1012
|
+
type: 'string',
|
|
1013
|
+
description: 'New title for TeamSpace notes — used by rename',
|
|
1014
|
+
},
|
|
1015
|
+
keepExtension: {
|
|
1016
|
+
type: 'boolean',
|
|
1017
|
+
description: 'Keep current extension on rename (default: true) — used by rename',
|
|
1018
|
+
},
|
|
1019
|
+
key: {
|
|
1020
|
+
type: 'string',
|
|
1021
|
+
description: 'Property key — used by set_property, remove_property',
|
|
1022
|
+
},
|
|
1023
|
+
value: {
|
|
1024
|
+
type: 'string',
|
|
1025
|
+
description: 'Property value — used by set_property',
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
required: ['action'],
|
|
1029
|
+
},
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
name: 'noteplan_edit_content',
|
|
1033
|
+
description: 'Edit note content: insert, append, delete lines, edit a line, or replace a range of lines.\n\nActions:\n- insert: Insert at position (start/end/after-heading/in-section/at-line)\n- append: Append to end (shorthand for insert at end). Use date="today" to append to today\'s daily note (replaces noteplan_add_to_today).\n- delete_lines: Delete line range (requires startLine, endLine + dryRun/confirmationToken)\n- edit_line: Edit one line (requires line + content)\n- replace_lines: Replace line range (requires startLine, endLine, content + dryRun/confirmationToken)\n\nTarget note via id, filename, title, date, or query. Calendar notes (date param) are auto-created if they don\'t exist yet — no need to create them first. Always use tab characters for indentation.\n\nNotePlan syntax: Tasks use "- [ ] text" (open), "- [x]" (done), "- [-]" (cancelled), "- [>]" (scheduled). The task marker (*/- with or without checkbox) follows user settings — prefer noteplan_paragraphs(action=add) for auto-formatted tasks. Schedule tasks to dates with >YYYY-MM-DD. Link to notes with [[Note Name]]. Never add block IDs (^id) — only the NotePlan app creates these.\n\nUse scheduleDate to auto-append >YYYY-MM-DD scheduling to content.',
|
|
1034
|
+
inputSchema: {
|
|
1035
|
+
type: 'object',
|
|
1036
|
+
properties: {
|
|
1037
|
+
action: {
|
|
1038
|
+
type: 'string',
|
|
1039
|
+
enum: ['insert', 'append', 'delete_lines', 'edit_line', 'replace_lines'],
|
|
1040
|
+
description: 'Action to perform',
|
|
1041
|
+
},
|
|
1042
|
+
id: {
|
|
1043
|
+
type: 'string',
|
|
1044
|
+
description: 'Note ID (preferred for space notes)',
|
|
1045
|
+
},
|
|
1046
|
+
filename: {
|
|
1047
|
+
type: 'string',
|
|
1048
|
+
description: 'Filename/path of the note',
|
|
1049
|
+
},
|
|
1050
|
+
title: {
|
|
1051
|
+
type: 'string',
|
|
1052
|
+
description: 'Note title target',
|
|
1053
|
+
},
|
|
1054
|
+
date: {
|
|
1055
|
+
type: 'string',
|
|
1056
|
+
description: 'Calendar note date (auto-creates if missing)',
|
|
1057
|
+
},
|
|
1058
|
+
query: {
|
|
1059
|
+
type: 'string',
|
|
1060
|
+
description: 'Fuzzy note query',
|
|
1061
|
+
},
|
|
1062
|
+
space: {
|
|
1063
|
+
type: 'string',
|
|
1064
|
+
description: 'Space name or ID scope',
|
|
1065
|
+
},
|
|
1066
|
+
content: {
|
|
1067
|
+
type: 'string',
|
|
1068
|
+
description: 'Content to insert/append/replace, or new line content for edit_line',
|
|
1069
|
+
},
|
|
1070
|
+
position: {
|
|
1071
|
+
type: 'string',
|
|
1072
|
+
enum: ['start', 'end', 'after-heading', 'at-line', 'in-section'],
|
|
1073
|
+
description: 'Where to insert: start (after frontmatter), end, after-heading (right after heading/marker line), in-section (at end of section, before next heading/marker), or at-line — used by insert',
|
|
1074
|
+
},
|
|
1075
|
+
heading: {
|
|
1076
|
+
type: 'string',
|
|
1077
|
+
description: 'Heading or section marker text (required for after-heading and in-section; matches both ## headings and **bold:** section markers) — used by insert',
|
|
1078
|
+
},
|
|
1079
|
+
line: {
|
|
1080
|
+
type: 'number',
|
|
1081
|
+
description: 'Line number (1-indexed) — used by insert (at-line) and edit_line',
|
|
1082
|
+
},
|
|
1083
|
+
startLine: {
|
|
1084
|
+
type: 'number',
|
|
1085
|
+
description: 'First line (1-indexed) — used by delete_lines, replace_lines',
|
|
1086
|
+
},
|
|
1087
|
+
endLine: {
|
|
1088
|
+
type: 'number',
|
|
1089
|
+
description: 'Last line (1-indexed) — used by delete_lines, replace_lines',
|
|
1090
|
+
},
|
|
1091
|
+
indentationStyle: {
|
|
1092
|
+
type: 'string',
|
|
1093
|
+
enum: ['tabs', 'preserve'],
|
|
1094
|
+
description: 'Indentation normalization (default: tabs) — used by insert, append, edit_line, replace_lines',
|
|
1095
|
+
},
|
|
1096
|
+
type: {
|
|
1097
|
+
type: 'string',
|
|
1098
|
+
enum: ['title', 'heading', 'task', 'checklist', 'bullet', 'quote', 'separator', 'empty', 'text'],
|
|
1099
|
+
description: 'Paragraph type for auto-formatting — used by insert',
|
|
1100
|
+
},
|
|
1101
|
+
taskStatus: {
|
|
1102
|
+
type: 'string',
|
|
1103
|
+
enum: ['open', 'done', 'cancelled', 'scheduled'],
|
|
1104
|
+
description: 'Task status (default: open) — used by insert with type=task/checklist',
|
|
1105
|
+
},
|
|
1106
|
+
headingLevel: {
|
|
1107
|
+
type: 'number',
|
|
1108
|
+
description: 'Heading level 1-6 — used by insert with type=heading/title',
|
|
1109
|
+
},
|
|
1110
|
+
priority: {
|
|
1111
|
+
type: 'number',
|
|
1112
|
+
description: 'Priority 1-3 — used by insert with type=task/checklist',
|
|
1113
|
+
},
|
|
1114
|
+
indentLevel: {
|
|
1115
|
+
type: 'number',
|
|
1116
|
+
description: 'Tab indent level — used by insert with type=task/checklist/bullet',
|
|
1117
|
+
},
|
|
1118
|
+
dryRun: {
|
|
1119
|
+
type: 'boolean',
|
|
1120
|
+
description: 'Preview impact and get confirmationToken — used by delete_lines, replace_lines',
|
|
1121
|
+
},
|
|
1122
|
+
confirmationToken: {
|
|
1123
|
+
type: 'string',
|
|
1124
|
+
description: 'Token from dryRun — used by delete_lines, replace_lines',
|
|
1125
|
+
},
|
|
1126
|
+
allowEmptyContent: {
|
|
1127
|
+
type: 'boolean',
|
|
1128
|
+
description: 'Allow empty content — used by edit_line, replace_lines',
|
|
1129
|
+
},
|
|
1130
|
+
scheduleDate: {
|
|
1131
|
+
type: 'string',
|
|
1132
|
+
description: 'Auto-append >YYYY-MM-DD scheduling date to content. Accepts: YYYY-MM-DD, YYYYMMDD, today, tomorrow, yesterday.',
|
|
1133
|
+
},
|
|
1134
|
+
},
|
|
1135
|
+
required: ['action'],
|
|
1136
|
+
},
|
|
1137
|
+
},
|
|
1138
|
+
{
|
|
1139
|
+
name: 'noteplan_paragraphs',
|
|
1140
|
+
description: 'Paragraph and task operations on notes.\n\nParagraph actions:\n- get: Get note lines with metadata (requires filename). Returns line, lineIndex, content, type, etc.\n- search: Search for matching lines in a note (requires query + note ref via id/filename/title/date)\n\nTask actions:\n- search_global: Search tasks across all notes (requires query, supports "*" wildcard)\n- add: Add a task (requires target + content). Task marker format auto-matches user settings. Use scheduleDate to auto-append >YYYY-MM-DD scheduling to content, [[Note Name]] to link, #tag for tags, @person for mentions.\n- complete: Mark task done (requires filename + lineIndex or line)\n- update: Update task content/status (requires filename + lineIndex or line)',
|
|
1141
|
+
inputSchema: {
|
|
1142
|
+
type: 'object',
|
|
1143
|
+
properties: {
|
|
1144
|
+
action: {
|
|
1145
|
+
type: 'string',
|
|
1146
|
+
enum: ['get', 'search', 'search_global', 'add', 'complete', 'update'],
|
|
1147
|
+
description: 'Action to perform',
|
|
1148
|
+
},
|
|
1149
|
+
id: {
|
|
1150
|
+
type: 'string',
|
|
1151
|
+
description: 'Note ID — used by search',
|
|
1152
|
+
},
|
|
1153
|
+
filename: {
|
|
1154
|
+
type: 'string',
|
|
1155
|
+
description: 'Filename/path of the note',
|
|
1156
|
+
},
|
|
1157
|
+
title: {
|
|
1158
|
+
type: 'string',
|
|
1159
|
+
description: 'Note title — used by search',
|
|
1160
|
+
},
|
|
1161
|
+
date: {
|
|
1162
|
+
type: 'string',
|
|
1163
|
+
description: 'Calendar date — used by search',
|
|
1164
|
+
},
|
|
1165
|
+
space: {
|
|
1166
|
+
type: 'string',
|
|
1167
|
+
description: 'Space name or ID scope',
|
|
1168
|
+
},
|
|
1169
|
+
query: {
|
|
1170
|
+
type: 'string',
|
|
1171
|
+
description: 'Search text — required for search, search_global. Use "*" for wildcard in search_global.',
|
|
1172
|
+
},
|
|
1173
|
+
caseSensitive: {
|
|
1174
|
+
type: 'boolean',
|
|
1175
|
+
description: 'Case-sensitive match — used by search, search_global',
|
|
1176
|
+
},
|
|
1177
|
+
wholeWord: {
|
|
1178
|
+
type: 'boolean',
|
|
1179
|
+
description: 'Whole-word match — used by search, search_global',
|
|
1180
|
+
},
|
|
1181
|
+
startLine: {
|
|
1182
|
+
type: 'number',
|
|
1183
|
+
description: 'First line (1-indexed) — used by get',
|
|
1184
|
+
},
|
|
1185
|
+
endLine: {
|
|
1186
|
+
type: 'number',
|
|
1187
|
+
description: 'Last line (1-indexed) — used by get',
|
|
1188
|
+
},
|
|
1189
|
+
contextLines: {
|
|
1190
|
+
type: 'number',
|
|
1191
|
+
description: 'Context lines around matches — used by search',
|
|
1192
|
+
},
|
|
1193
|
+
paragraphMaxChars: {
|
|
1194
|
+
type: 'number',
|
|
1195
|
+
description: 'Max paragraph chars per match — used by search',
|
|
1196
|
+
},
|
|
1197
|
+
// Task-specific params
|
|
1198
|
+
status: {
|
|
1199
|
+
type: 'string',
|
|
1200
|
+
enum: ['open', 'done', 'cancelled', 'scheduled'],
|
|
1201
|
+
description: 'Filter by or set task status — used by search_global, update',
|
|
1202
|
+
},
|
|
1203
|
+
content: {
|
|
1204
|
+
type: 'string',
|
|
1205
|
+
description: 'Task content — used by add, update (without marker prefix)',
|
|
1206
|
+
},
|
|
1207
|
+
target: {
|
|
1208
|
+
type: 'string',
|
|
1209
|
+
description: 'Target for add: date (today/tomorrow/YYYY-MM-DD) for daily notes or filename for project notes',
|
|
1210
|
+
},
|
|
1211
|
+
position: {
|
|
1212
|
+
type: 'string',
|
|
1213
|
+
enum: ['start', 'end', 'after-heading', 'in-section'],
|
|
1214
|
+
description: 'Where to add task (default: end) — used by add',
|
|
1215
|
+
},
|
|
1216
|
+
heading: {
|
|
1217
|
+
type: 'string',
|
|
1218
|
+
description: 'Heading or section marker text (matches both ## headings and **bold:** section markers) — used by add',
|
|
1219
|
+
},
|
|
1220
|
+
lineIndex: {
|
|
1221
|
+
type: 'number',
|
|
1222
|
+
description: 'Task line index (0-based) — used by complete, update',
|
|
1223
|
+
},
|
|
1224
|
+
line: {
|
|
1225
|
+
type: 'number',
|
|
1226
|
+
description: 'Task line number (1-based) — used by complete, update',
|
|
1227
|
+
},
|
|
1228
|
+
priority: {
|
|
1229
|
+
type: 'number',
|
|
1230
|
+
description: 'Priority 1-3 — used by add',
|
|
1231
|
+
},
|
|
1232
|
+
indentLevel: {
|
|
1233
|
+
type: 'number',
|
|
1234
|
+
description: 'Tab indent level — used by add',
|
|
1235
|
+
},
|
|
1236
|
+
allowEmptyContent: {
|
|
1237
|
+
type: 'boolean',
|
|
1238
|
+
description: 'Allow empty task content — used by update',
|
|
1239
|
+
},
|
|
1240
|
+
folder: {
|
|
1241
|
+
type: 'string',
|
|
1242
|
+
description: 'Folder filter — used by search_global',
|
|
1243
|
+
},
|
|
1244
|
+
noteQuery: {
|
|
1245
|
+
type: 'string',
|
|
1246
|
+
description: 'Filter candidate notes — used by search_global',
|
|
1247
|
+
},
|
|
1248
|
+
noteTypes: {
|
|
1249
|
+
type: 'array',
|
|
1250
|
+
items: { type: 'string', enum: ['calendar', 'note', 'trash'] },
|
|
1251
|
+
description: 'Note type filter — used by search_global',
|
|
1252
|
+
},
|
|
1253
|
+
preferCalendar: {
|
|
1254
|
+
type: 'boolean',
|
|
1255
|
+
description: 'Prioritize calendar notes — used by search_global',
|
|
1256
|
+
},
|
|
1257
|
+
periodicOnly: {
|
|
1258
|
+
type: 'boolean',
|
|
1259
|
+
description: 'Only periodic calendar notes — used by search_global',
|
|
1260
|
+
},
|
|
1261
|
+
maxNotes: {
|
|
1262
|
+
type: 'number',
|
|
1263
|
+
description: 'Max notes to scan — used by search_global',
|
|
1264
|
+
},
|
|
1265
|
+
scheduleDate: {
|
|
1266
|
+
type: 'string',
|
|
1267
|
+
description: 'Auto-append >YYYY-MM-DD scheduling date to content. Accepts: YYYY-MM-DD, YYYYMMDD, today, tomorrow, yesterday.',
|
|
1268
|
+
},
|
|
1269
|
+
limit: {
|
|
1270
|
+
type: 'number',
|
|
1271
|
+
description: 'Max results to return',
|
|
1272
|
+
},
|
|
1273
|
+
offset: {
|
|
1274
|
+
type: 'number',
|
|
1275
|
+
description: 'Pagination offset',
|
|
1276
|
+
},
|
|
1277
|
+
cursor: {
|
|
1278
|
+
type: 'string',
|
|
1279
|
+
description: 'Cursor from previous page',
|
|
1280
|
+
},
|
|
1281
|
+
},
|
|
1282
|
+
required: ['action'],
|
|
1283
|
+
},
|
|
1284
|
+
},
|
|
1285
|
+
{
|
|
1286
|
+
name: 'noteplan_folders',
|
|
1287
|
+
description: 'Folder and space operations: list, find, resolve, create, move, rename, delete folders, or list spaces.\n\nActions:\n- list: List folders with optional filtering\n- find: Find folder matches for exploration\n- resolve: Resolve to one canonical folder path\n- create: Create a folder (local: path, TeamSpace: space + name)\n- move: Move a folder (requires dryRun/confirmationToken)\n- rename: Rename a folder (requires dryRun/confirmationToken)\n- delete: Delete folder to trash (requires dryRun/confirmationToken)\n- list_spaces: List spaces/workspaces with optional filtering',
|
|
1288
|
+
inputSchema: {
|
|
1289
|
+
type: 'object',
|
|
1290
|
+
properties: {
|
|
1291
|
+
action: {
|
|
1292
|
+
type: 'string',
|
|
1293
|
+
enum: ['list', 'find', 'resolve', 'create', 'move', 'rename', 'delete', 'list_spaces'],
|
|
1294
|
+
description: 'Action to perform',
|
|
1295
|
+
},
|
|
1296
|
+
path: {
|
|
1297
|
+
type: 'string',
|
|
1298
|
+
description: 'Local folder path — used by create, delete',
|
|
1299
|
+
},
|
|
1300
|
+
query: {
|
|
1301
|
+
type: 'string',
|
|
1302
|
+
description: 'Search query — used by list, find, resolve',
|
|
1303
|
+
},
|
|
1304
|
+
space: {
|
|
1305
|
+
type: 'string',
|
|
1306
|
+
description: 'Space name or ID scope',
|
|
1307
|
+
},
|
|
1308
|
+
name: {
|
|
1309
|
+
type: 'string',
|
|
1310
|
+
description: 'Folder name — used by create (TeamSpace)',
|
|
1311
|
+
},
|
|
1312
|
+
parent: {
|
|
1313
|
+
type: 'string',
|
|
1314
|
+
description: 'Parent folder ref — used by create (TeamSpace)',
|
|
1315
|
+
},
|
|
1316
|
+
parentPath: {
|
|
1317
|
+
type: 'string',
|
|
1318
|
+
description: 'Parent folder path — used by list',
|
|
1319
|
+
},
|
|
1320
|
+
recursive: {
|
|
1321
|
+
type: 'boolean',
|
|
1322
|
+
description: 'Include descendants — used by list',
|
|
1323
|
+
},
|
|
1324
|
+
includeLocal: {
|
|
1325
|
+
type: 'boolean',
|
|
1326
|
+
description: 'Include local folders — used by list, find, resolve',
|
|
1327
|
+
},
|
|
1328
|
+
includeSpaces: {
|
|
1329
|
+
type: 'boolean',
|
|
1330
|
+
description: 'Include space folders — used by list, find, resolve',
|
|
1331
|
+
},
|
|
1332
|
+
maxDepth: {
|
|
1333
|
+
type: 'number',
|
|
1334
|
+
description: 'Max folder depth — used by list, find, resolve',
|
|
1335
|
+
},
|
|
1336
|
+
sourcePath: {
|
|
1337
|
+
type: 'string',
|
|
1338
|
+
description: 'Local source folder path — used by move, rename',
|
|
1339
|
+
},
|
|
1340
|
+
source: {
|
|
1341
|
+
type: 'string',
|
|
1342
|
+
description: 'TeamSpace source ref — used by move, rename, delete',
|
|
1343
|
+
},
|
|
1344
|
+
destinationFolder: {
|
|
1345
|
+
type: 'string',
|
|
1346
|
+
description: 'Local destination folder — used by move',
|
|
1347
|
+
},
|
|
1348
|
+
destination: {
|
|
1349
|
+
type: 'string',
|
|
1350
|
+
description: 'TeamSpace destination ref — used by move',
|
|
1351
|
+
},
|
|
1352
|
+
newName: {
|
|
1353
|
+
type: 'string',
|
|
1354
|
+
description: 'New folder name — used by rename',
|
|
1355
|
+
},
|
|
1356
|
+
minScore: {
|
|
1357
|
+
type: 'number',
|
|
1358
|
+
description: 'Min auto-resolve score — used by resolve',
|
|
1359
|
+
},
|
|
1360
|
+
ambiguityDelta: {
|
|
1361
|
+
type: 'number',
|
|
1362
|
+
description: 'Ambiguity delta — used by resolve',
|
|
1363
|
+
},
|
|
1364
|
+
dryRun: {
|
|
1365
|
+
type: 'boolean',
|
|
1366
|
+
description: 'Preview impact — used by move, rename, delete',
|
|
1367
|
+
},
|
|
1368
|
+
confirmationToken: {
|
|
1369
|
+
type: 'string',
|
|
1370
|
+
description: 'Token from dryRun — used by move, rename, delete',
|
|
1371
|
+
},
|
|
1372
|
+
limit: {
|
|
1373
|
+
type: 'number',
|
|
1374
|
+
description: 'Max results to return',
|
|
1375
|
+
},
|
|
1376
|
+
offset: {
|
|
1377
|
+
type: 'number',
|
|
1378
|
+
description: 'Pagination offset',
|
|
1379
|
+
},
|
|
1380
|
+
cursor: {
|
|
1381
|
+
type: 'string',
|
|
1382
|
+
description: 'Cursor from previous page',
|
|
1383
|
+
},
|
|
1384
|
+
},
|
|
1385
|
+
required: ['action'],
|
|
1386
|
+
},
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
name: 'noteplan_filters',
|
|
1390
|
+
description: 'Saved filter operations: list, get, get_tasks, list_parameters, save, rename.\n\nActions:\n- list: List saved filters\n- get: Get one filter with parsed params (requires name)\n- get_tasks: Execute a filter against tasks (requires name)\n- list_parameters: List supported filter parameter keys\n- save: Create or update a filter (requires name + items)\n- rename: Rename a filter (requires oldName + newName)',
|
|
1391
|
+
inputSchema: {
|
|
1392
|
+
type: 'object',
|
|
1393
|
+
properties: {
|
|
1394
|
+
action: {
|
|
1395
|
+
type: 'string',
|
|
1396
|
+
enum: ['list', 'get', 'get_tasks', 'list_parameters', 'save', 'rename'],
|
|
1397
|
+
description: 'Action to perform',
|
|
1398
|
+
},
|
|
1399
|
+
name: {
|
|
1400
|
+
type: 'string',
|
|
1401
|
+
description: 'Filter name — used by get, get_tasks, save',
|
|
1402
|
+
},
|
|
1403
|
+
oldName: {
|
|
1404
|
+
type: 'string',
|
|
1405
|
+
description: 'Current filter name — used by rename',
|
|
1406
|
+
},
|
|
1407
|
+
newName: {
|
|
1408
|
+
type: 'string',
|
|
1409
|
+
description: 'New filter name — used by rename',
|
|
1410
|
+
},
|
|
1411
|
+
query: {
|
|
1412
|
+
type: 'string',
|
|
1413
|
+
description: 'Filter names by substring — used by list',
|
|
1414
|
+
},
|
|
1415
|
+
overwrite: {
|
|
1416
|
+
type: 'boolean',
|
|
1417
|
+
description: 'Overwrite existing — used by save, rename',
|
|
1418
|
+
},
|
|
1419
|
+
items: {
|
|
1420
|
+
type: 'array',
|
|
1421
|
+
items: {
|
|
1422
|
+
type: 'object',
|
|
1423
|
+
properties: {
|
|
1424
|
+
param: { type: 'string', description: 'Filter parameter key' },
|
|
1425
|
+
value: {
|
|
1426
|
+
oneOf: [
|
|
1427
|
+
{ type: 'string' },
|
|
1428
|
+
{ type: 'boolean' },
|
|
1429
|
+
{ type: 'number' },
|
|
1430
|
+
{ type: 'array', items: { type: 'string' } },
|
|
1431
|
+
],
|
|
1432
|
+
description: 'Filter parameter value',
|
|
1433
|
+
},
|
|
1434
|
+
display: { type: 'boolean', description: 'UI display flag' },
|
|
1435
|
+
},
|
|
1436
|
+
required: ['param', 'value'],
|
|
1437
|
+
},
|
|
1438
|
+
description: 'Filter items — used by save',
|
|
1439
|
+
},
|
|
1440
|
+
maxNotes: {
|
|
1441
|
+
type: 'number',
|
|
1442
|
+
description: 'Max notes to scan — used by get_tasks',
|
|
1443
|
+
},
|
|
1444
|
+
space: {
|
|
1445
|
+
type: 'string',
|
|
1446
|
+
description: 'Space ID scope — used by get_tasks',
|
|
1447
|
+
},
|
|
1448
|
+
folder: {
|
|
1449
|
+
type: 'string',
|
|
1450
|
+
description: 'Folder scope — used by get_tasks',
|
|
1451
|
+
},
|
|
1452
|
+
limit: {
|
|
1453
|
+
type: 'number',
|
|
1454
|
+
description: 'Max results to return',
|
|
1455
|
+
},
|
|
1456
|
+
offset: {
|
|
1457
|
+
type: 'number',
|
|
1458
|
+
description: 'Pagination offset',
|
|
1459
|
+
},
|
|
1460
|
+
cursor: {
|
|
1461
|
+
type: 'string',
|
|
1462
|
+
description: 'Cursor from previous page',
|
|
1463
|
+
},
|
|
1464
|
+
},
|
|
1465
|
+
required: ['action'],
|
|
1466
|
+
},
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
name: 'noteplan_eventkit',
|
|
1470
|
+
description: 'macOS Calendar and Reminders operations.\n\nCalendar actions (source="calendar"):\n- get_events: Get events for a date/range\n- list_calendars: List all calendars\n- create_event: Create event (requires title + startDate)\n- update_event: Update event (requires eventId)\n- delete_event: Delete event (requires eventId + dryRun/confirmationToken)\n\nReminder actions (source="reminders"):\n- get: Get reminders (optional list/query filter)\n- list_lists: List reminder lists\n- create: Create reminder (requires title)\n- complete: Mark reminder done (requires reminderId)\n- update: Update reminder (requires reminderId)\n- delete: Delete reminder (requires reminderId + dryRun/confirmationToken)',
|
|
1471
|
+
inputSchema: {
|
|
1472
|
+
type: 'object',
|
|
1473
|
+
properties: {
|
|
1474
|
+
source: {
|
|
1475
|
+
type: 'string',
|
|
1476
|
+
enum: ['calendar', 'reminders'],
|
|
1477
|
+
description: 'EventKit source: "calendar" for Calendar.app, "reminders" for Reminders.app',
|
|
1478
|
+
},
|
|
1479
|
+
action: {
|
|
1480
|
+
type: 'string',
|
|
1481
|
+
enum: ['get_events', 'list_calendars', 'create_event', 'update_event', 'delete_event', 'get', 'list_lists', 'create', 'complete', 'update', 'delete'],
|
|
1482
|
+
description: 'Action to perform',
|
|
1483
|
+
},
|
|
1484
|
+
// Calendar params
|
|
1485
|
+
eventId: {
|
|
1486
|
+
type: 'string',
|
|
1487
|
+
description: 'Event ID — calendar: update_event, delete_event',
|
|
1488
|
+
},
|
|
1489
|
+
date: {
|
|
1490
|
+
type: 'string',
|
|
1491
|
+
description: 'Date (YYYY-MM-DD, "today", "tomorrow") — calendar: get_events',
|
|
1492
|
+
},
|
|
1493
|
+
days: {
|
|
1494
|
+
type: 'number',
|
|
1495
|
+
description: 'Days to fetch — calendar: get_events',
|
|
1496
|
+
},
|
|
1497
|
+
startDate: {
|
|
1498
|
+
type: 'string',
|
|
1499
|
+
description: 'Start date/time — calendar: create_event, update_event',
|
|
1500
|
+
},
|
|
1501
|
+
endDate: {
|
|
1502
|
+
type: 'string',
|
|
1503
|
+
description: 'End date/time — calendar: create_event, update_event',
|
|
1504
|
+
},
|
|
1505
|
+
calendar: {
|
|
1506
|
+
type: 'string',
|
|
1507
|
+
description: 'Calendar name — calendar: get_events, create_event',
|
|
1508
|
+
},
|
|
1509
|
+
location: {
|
|
1510
|
+
type: 'string',
|
|
1511
|
+
description: 'Event location — calendar: create_event, update_event',
|
|
1512
|
+
},
|
|
1513
|
+
allDay: {
|
|
1514
|
+
type: 'boolean',
|
|
1515
|
+
description: 'All-day event — calendar: create_event',
|
|
1516
|
+
},
|
|
1517
|
+
// Reminders params
|
|
1518
|
+
reminderId: {
|
|
1519
|
+
type: 'string',
|
|
1520
|
+
description: 'Reminder ID — reminders: complete, update, delete',
|
|
1521
|
+
},
|
|
1522
|
+
list: {
|
|
1523
|
+
type: 'string',
|
|
1524
|
+
description: 'Reminder list name — reminders: get, create',
|
|
1525
|
+
},
|
|
1526
|
+
dueDate: {
|
|
1527
|
+
type: 'string',
|
|
1528
|
+
description: 'Due date — reminders: create, update',
|
|
1529
|
+
},
|
|
1530
|
+
priority: {
|
|
1531
|
+
type: 'number',
|
|
1532
|
+
description: 'Priority: 0 (none), 1 (high), 5 (medium), 9 (low) — reminders: create, update',
|
|
1533
|
+
},
|
|
1534
|
+
includeCompleted: {
|
|
1535
|
+
type: 'boolean',
|
|
1536
|
+
description: 'Include completed — reminders: get',
|
|
1537
|
+
},
|
|
1538
|
+
// Shared params
|
|
1539
|
+
title: {
|
|
1540
|
+
type: 'string',
|
|
1541
|
+
description: 'Title — calendar: create_event, update_event; reminders: create, update',
|
|
1542
|
+
},
|
|
1543
|
+
notes: {
|
|
1544
|
+
type: 'string',
|
|
1545
|
+
description: 'Notes — calendar: create_event, update_event; reminders: create, update',
|
|
1546
|
+
},
|
|
1547
|
+
query: {
|
|
1548
|
+
type: 'string',
|
|
1549
|
+
description: 'Filter by substring — reminders: get, list_lists',
|
|
1550
|
+
},
|
|
1551
|
+
dryRun: {
|
|
1552
|
+
type: 'boolean',
|
|
1553
|
+
description: 'Preview impact — calendar: delete_event; reminders: delete',
|
|
1554
|
+
},
|
|
1555
|
+
confirmationToken: {
|
|
1556
|
+
type: 'string',
|
|
1557
|
+
description: 'Token from dryRun — calendar: delete_event; reminders: delete',
|
|
1558
|
+
},
|
|
1559
|
+
limit: {
|
|
1560
|
+
type: 'number',
|
|
1561
|
+
description: 'Max results to return',
|
|
1562
|
+
},
|
|
1563
|
+
offset: {
|
|
1564
|
+
type: 'number',
|
|
1565
|
+
description: 'Pagination offset',
|
|
1566
|
+
},
|
|
1567
|
+
cursor: {
|
|
1568
|
+
type: 'string',
|
|
1569
|
+
description: 'Cursor from previous page',
|
|
1570
|
+
},
|
|
1571
|
+
},
|
|
1572
|
+
required: ['source', 'action'],
|
|
1573
|
+
},
|
|
1574
|
+
},
|
|
1575
|
+
{
|
|
1576
|
+
name: 'noteplan_memory',
|
|
1577
|
+
description: 'User preference memory operations.\n\nActions:\n- list: List/search stored memories\n- save: Save a new memory (requires content)\n- update: Update memory content/tags (requires id)\n- delete: Delete a memory (requires id)',
|
|
1578
|
+
inputSchema: {
|
|
1579
|
+
type: 'object',
|
|
1580
|
+
properties: {
|
|
1581
|
+
action: {
|
|
1582
|
+
type: 'string',
|
|
1583
|
+
enum: ['list', 'save', 'update', 'delete'],
|
|
1584
|
+
description: 'Action to perform',
|
|
1585
|
+
},
|
|
1586
|
+
id: {
|
|
1587
|
+
type: 'string',
|
|
1588
|
+
description: 'Memory ID — used by update, delete',
|
|
1589
|
+
},
|
|
1590
|
+
content: {
|
|
1591
|
+
type: 'string',
|
|
1592
|
+
description: 'Memory content — used by save, update',
|
|
1593
|
+
minLength: 1,
|
|
1594
|
+
maxLength: 2000,
|
|
1595
|
+
},
|
|
1596
|
+
tags: {
|
|
1597
|
+
type: 'array',
|
|
1598
|
+
items: { type: 'string' },
|
|
1599
|
+
maxItems: 10,
|
|
1600
|
+
description: 'Tags — used by save, update. Suggested: style, formatting, workflow, correction, naming, structure, preference',
|
|
1601
|
+
},
|
|
1602
|
+
tag: {
|
|
1603
|
+
type: 'string',
|
|
1604
|
+
description: 'Filter by tag — used by list',
|
|
1605
|
+
},
|
|
1606
|
+
query: {
|
|
1607
|
+
type: 'string',
|
|
1608
|
+
description: 'Search content — used by list',
|
|
1609
|
+
},
|
|
1610
|
+
limit: {
|
|
1611
|
+
type: 'number',
|
|
1612
|
+
description: 'Max results — used by list',
|
|
1613
|
+
},
|
|
1614
|
+
offset: {
|
|
1615
|
+
type: 'number',
|
|
1616
|
+
description: 'Pagination offset — used by list',
|
|
1617
|
+
},
|
|
1618
|
+
},
|
|
1619
|
+
required: ['action'],
|
|
1620
|
+
},
|
|
1621
|
+
},
|
|
1622
|
+
{
|
|
1623
|
+
name: 'noteplan_search',
|
|
1624
|
+
description: 'Search across notes or list tags.\n\nActions:\n- search (default): Full-text or metadata search across notes. Use searchField, queryMode, propertyFilters, etc.\n- list_tags: List all tags/hashtags with optional filtering.\n\nSearch: discover notes by content/keywords/phrases and optional frontmatter property filters (e.g. {"category":"marketing"}). Use queryMode=smart/any/all for multi-word token matching, and query="*" for browse mode. Folder filters accept canonical paths from noteplan_folders (action: list/resolve), with or without "Notes/" prefix.',
|
|
1625
|
+
inputSchema: {
|
|
1626
|
+
type: 'object',
|
|
1627
|
+
properties: {
|
|
1628
|
+
action: {
|
|
1629
|
+
type: 'string',
|
|
1630
|
+
enum: ['search', 'list_tags'],
|
|
1631
|
+
description: 'Action to perform (default: search)',
|
|
1632
|
+
},
|
|
1633
|
+
query: {
|
|
1634
|
+
type: 'string',
|
|
1635
|
+
description: 'Search query (required for search). Supports OR patterns like "meeting|standup". For list_tags, filters tags by substring.',
|
|
1636
|
+
},
|
|
1637
|
+
space: {
|
|
1638
|
+
type: 'string',
|
|
1639
|
+
description: 'Space name or ID — used by search, list_tags',
|
|
1640
|
+
},
|
|
1641
|
+
searchField: {
|
|
1642
|
+
type: 'string',
|
|
1643
|
+
enum: ['content', 'title', 'filename', 'title_or_filename'],
|
|
1644
|
+
description: 'Search scope. Use "title" or "title_or_filename" for fast note discovery by version/name. Default: content',
|
|
1645
|
+
},
|
|
1646
|
+
queryMode: {
|
|
1647
|
+
type: 'string',
|
|
1648
|
+
enum: ['phrase', 'smart', 'any', 'all'],
|
|
1649
|
+
description: 'Multi-word behavior for content search: phrase (exact phrase), smart (token OR + relevance threshold), any (any token), all (all tokens). Default: smart',
|
|
1650
|
+
},
|
|
1651
|
+
minTokenMatches: {
|
|
1652
|
+
type: 'number',
|
|
1653
|
+
description: 'When queryMode is smart/any/all, minimum token matches required per note (auto by default)',
|
|
1654
|
+
},
|
|
1655
|
+
types: {
|
|
1656
|
+
type: 'array',
|
|
1657
|
+
items: { type: 'string', enum: ['calendar', 'note', 'trash'] },
|
|
1658
|
+
description: 'Filter by note types',
|
|
1659
|
+
},
|
|
1660
|
+
folders: {
|
|
1661
|
+
type: 'array',
|
|
1662
|
+
items: { type: 'string' },
|
|
1663
|
+
description: 'Filter by folders (canonical path, e.g. "20 - Areas"; "Notes/20 - Areas" is also accepted). If multiple folders are provided, the first is used for full-text scope.',
|
|
1664
|
+
},
|
|
1665
|
+
limit: {
|
|
1666
|
+
type: 'number',
|
|
1667
|
+
description: 'Maximum number of results (default: 20, max: 200)',
|
|
1668
|
+
},
|
|
1669
|
+
fuzzy: {
|
|
1670
|
+
type: 'boolean',
|
|
1671
|
+
description: 'Enable fuzzy/typo-tolerant matching (default: false)',
|
|
1672
|
+
},
|
|
1673
|
+
caseSensitive: {
|
|
1674
|
+
type: 'boolean',
|
|
1675
|
+
description: 'Case-sensitive search (default: false)',
|
|
1676
|
+
},
|
|
1677
|
+
contextLines: {
|
|
1678
|
+
type: 'number',
|
|
1679
|
+
description: 'Lines of context around matches (0-5, default: 0)',
|
|
1680
|
+
},
|
|
1681
|
+
propertyFilters: {
|
|
1682
|
+
type: 'object',
|
|
1683
|
+
additionalProperties: { type: 'string' },
|
|
1684
|
+
description: 'Exact frontmatter property filters (all must match), e.g. {"category":"marketing"}',
|
|
1685
|
+
},
|
|
1686
|
+
propertyCaseSensitive: {
|
|
1687
|
+
type: 'boolean',
|
|
1688
|
+
description: 'Case-sensitive frontmatter property matching (default: false)',
|
|
1689
|
+
},
|
|
1690
|
+
modifiedAfter: {
|
|
1691
|
+
type: 'string',
|
|
1692
|
+
description: 'Filter notes modified after date (ISO date or "today", "yesterday", "this week", "this month")',
|
|
1693
|
+
},
|
|
1694
|
+
modifiedBefore: {
|
|
1695
|
+
type: 'string',
|
|
1696
|
+
description: 'Filter notes modified before date',
|
|
1697
|
+
},
|
|
1698
|
+
createdAfter: {
|
|
1699
|
+
type: 'string',
|
|
1700
|
+
description: 'Filter notes created after date',
|
|
1701
|
+
},
|
|
1702
|
+
createdBefore: {
|
|
1703
|
+
type: 'string',
|
|
1704
|
+
description: 'Filter notes created before date',
|
|
1705
|
+
},
|
|
1706
|
+
},
|
|
1707
|
+
},
|
|
1708
|
+
},
|
|
1709
|
+
];
|
|
1710
|
+
if (embeddingsToolsEnabled) {
|
|
1711
|
+
toolDefinitions.push({
|
|
1712
|
+
name: 'noteplan_embeddings',
|
|
1713
|
+
description: 'Embeddings/vector search operations.\n\nActions:\n- status: Get embeddings config and index status\n- search: Semantic search over index (requires query)\n- sync: Build/refresh embeddings index\n- reset: Delete index rows (requires dryRun/confirmationToken)',
|
|
1714
|
+
inputSchema: {
|
|
1715
|
+
type: 'object',
|
|
1716
|
+
properties: {
|
|
1717
|
+
action: {
|
|
1718
|
+
type: 'string',
|
|
1719
|
+
enum: ['status', 'search', 'sync', 'reset'],
|
|
1720
|
+
description: 'Action to perform',
|
|
1721
|
+
},
|
|
1722
|
+
query: {
|
|
1723
|
+
type: 'string',
|
|
1724
|
+
description: 'Search query text — used by search',
|
|
1725
|
+
},
|
|
1726
|
+
space: {
|
|
1727
|
+
type: 'string',
|
|
1728
|
+
description: 'Space name or ID scope',
|
|
1729
|
+
},
|
|
1730
|
+
types: {
|
|
1731
|
+
type: 'array',
|
|
1732
|
+
items: { type: 'string', enum: ['calendar', 'note', 'trash'] },
|
|
1733
|
+
description: 'Note type filter — used by search, sync',
|
|
1734
|
+
},
|
|
1735
|
+
source: {
|
|
1736
|
+
type: 'string',
|
|
1737
|
+
enum: ['local', 'space'],
|
|
1738
|
+
description: 'Source filter — used by search',
|
|
1739
|
+
},
|
|
1740
|
+
limit: {
|
|
1741
|
+
type: 'number',
|
|
1742
|
+
description: 'Max results — used by search, sync',
|
|
1743
|
+
},
|
|
1744
|
+
offset: {
|
|
1745
|
+
type: 'number',
|
|
1746
|
+
description: 'Pagination offset — used by sync',
|
|
1747
|
+
},
|
|
1748
|
+
minScore: {
|
|
1749
|
+
type: 'number',
|
|
1750
|
+
description: 'Min cosine similarity — used by search',
|
|
1751
|
+
},
|
|
1752
|
+
includeText: {
|
|
1753
|
+
type: 'boolean',
|
|
1754
|
+
description: 'Include full chunk text — used by search',
|
|
1755
|
+
},
|
|
1756
|
+
previewChars: {
|
|
1757
|
+
type: 'number',
|
|
1758
|
+
description: 'Preview length — used by search',
|
|
1759
|
+
},
|
|
1760
|
+
maxChunks: {
|
|
1761
|
+
type: 'number',
|
|
1762
|
+
description: 'Max chunks to scan — used by search',
|
|
1763
|
+
},
|
|
1764
|
+
noteQuery: {
|
|
1765
|
+
type: 'string',
|
|
1766
|
+
description: 'Note filter substring — used by sync',
|
|
1767
|
+
},
|
|
1768
|
+
forceReembed: {
|
|
1769
|
+
type: 'boolean',
|
|
1770
|
+
description: 'Force recompute — used by sync',
|
|
1771
|
+
},
|
|
1772
|
+
pruneMissing: {
|
|
1773
|
+
type: 'boolean',
|
|
1774
|
+
description: 'Remove stale rows — used by sync',
|
|
1775
|
+
},
|
|
1776
|
+
batchSize: {
|
|
1777
|
+
type: 'number',
|
|
1778
|
+
description: 'API batch size — used by sync',
|
|
1779
|
+
},
|
|
1780
|
+
maxChunksPerNote: {
|
|
1781
|
+
type: 'number',
|
|
1782
|
+
description: 'Max chunks per note — used by sync',
|
|
1783
|
+
},
|
|
1784
|
+
dryRun: {
|
|
1785
|
+
type: 'boolean',
|
|
1786
|
+
description: 'Preview impact — used by reset',
|
|
1787
|
+
},
|
|
1788
|
+
confirmationToken: {
|
|
1789
|
+
type: 'string',
|
|
1790
|
+
description: 'Token from dryRun — used by reset',
|
|
1791
|
+
},
|
|
1792
|
+
},
|
|
1793
|
+
required: ['action'],
|
|
1794
|
+
},
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
if (advancedFeaturesEnabled) {
|
|
1798
|
+
toolDefinitions.push({
|
|
1799
|
+
name: 'noteplan_ui',
|
|
1800
|
+
description: 'NotePlan UI control via AppleScript.\n\nActions:\n- open_note: Open a note (title or filename)\n- open_today: Open today\'s note\n- search: Search in UI\n- run_plugin: Run a plugin command (requires pluginId + command)\n- open_view: Open a named view\n- toggle_sidebar: Toggle sidebar visibility\n- close_plugin_window: Close plugin window (by windowID/title, or omit both to close all)\n- list_plugin_windows: List open plugin windows',
|
|
1801
|
+
inputSchema: {
|
|
1802
|
+
type: 'object',
|
|
1803
|
+
properties: {
|
|
1804
|
+
action: {
|
|
1805
|
+
type: 'string',
|
|
1806
|
+
enum: ['open_note', 'open_today', 'search', 'run_plugin', 'open_view', 'toggle_sidebar', 'close_plugin_window', 'list_plugin_windows'],
|
|
1807
|
+
description: 'Action to perform',
|
|
1808
|
+
},
|
|
1809
|
+
title: {
|
|
1810
|
+
type: 'string',
|
|
1811
|
+
description: 'Note title — used by open_note; window title — used by close_plugin_window',
|
|
1812
|
+
},
|
|
1813
|
+
filename: {
|
|
1814
|
+
type: 'string',
|
|
1815
|
+
description: 'Filename — used by open_note',
|
|
1816
|
+
},
|
|
1817
|
+
inNewWindow: {
|
|
1818
|
+
type: 'boolean',
|
|
1819
|
+
description: 'Open in new window — used by open_note',
|
|
1820
|
+
},
|
|
1821
|
+
inSplitView: {
|
|
1822
|
+
type: 'boolean',
|
|
1823
|
+
description: 'Open in split view — used by open_note',
|
|
1824
|
+
},
|
|
1825
|
+
query: {
|
|
1826
|
+
type: 'string',
|
|
1827
|
+
description: 'Search text — used by search',
|
|
1828
|
+
},
|
|
1829
|
+
pluginId: {
|
|
1830
|
+
type: 'string',
|
|
1831
|
+
description: 'Plugin ID — used by run_plugin',
|
|
1832
|
+
},
|
|
1833
|
+
command: {
|
|
1834
|
+
type: 'string',
|
|
1835
|
+
description: 'Command name — used by run_plugin',
|
|
1836
|
+
},
|
|
1837
|
+
arguments: {
|
|
1838
|
+
type: 'string',
|
|
1839
|
+
description: 'JSON arguments string — used by run_plugin',
|
|
1840
|
+
},
|
|
1841
|
+
name: {
|
|
1842
|
+
type: 'string',
|
|
1843
|
+
description: 'View name — used by open_view',
|
|
1844
|
+
},
|
|
1845
|
+
windowID: {
|
|
1846
|
+
type: 'string',
|
|
1847
|
+
description: 'Window ID — used by close_plugin_window',
|
|
1848
|
+
},
|
|
1849
|
+
},
|
|
1850
|
+
required: ['action'],
|
|
1851
|
+
},
|
|
1852
|
+
}, {
|
|
1853
|
+
name: 'noteplan_plugins',
|
|
1854
|
+
description: 'Plugin management: list, create, delete, install, read source/log, update HTML, screenshot.\n\nActions:\n- list: List installed plugins\n- list_available: List plugins from online repository\n- create: Create plugin with HTML view (requires pluginId, pluginName, commandName, html)\n- delete: Delete plugin (requires pluginId + confirmationToken)\n- install: Install from repository (requires pluginId)\n- log: Read plugin console log (requires pluginId)\n- source: Read plugin source (requires pluginId)\n- update_html: Apply find/replace patches (requires pluginId + patches)\n- screenshot: Capture plugin WebView screenshot (requires pluginId)',
|
|
1855
|
+
inputSchema: {
|
|
1856
|
+
type: 'object',
|
|
1857
|
+
properties: {
|
|
1858
|
+
action: {
|
|
1859
|
+
type: 'string',
|
|
1860
|
+
enum: ['list', 'list_available', 'create', 'delete', 'install', 'log', 'source', 'update_html', 'screenshot'],
|
|
1861
|
+
description: 'Action to perform',
|
|
1862
|
+
},
|
|
1863
|
+
pluginId: {
|
|
1864
|
+
type: 'string',
|
|
1865
|
+
description: 'Plugin ID — used by create, delete, install, log, source, update_html, screenshot',
|
|
1866
|
+
},
|
|
1867
|
+
pluginName: {
|
|
1868
|
+
type: 'string',
|
|
1869
|
+
description: 'Display name — used by create',
|
|
1870
|
+
},
|
|
1871
|
+
commandName: {
|
|
1872
|
+
type: 'string',
|
|
1873
|
+
description: 'Command name — used by create',
|
|
1874
|
+
},
|
|
1875
|
+
html: {
|
|
1876
|
+
type: 'string',
|
|
1877
|
+
description: 'HTML content — used by create',
|
|
1878
|
+
},
|
|
1879
|
+
icon: {
|
|
1880
|
+
type: 'string',
|
|
1881
|
+
description: 'Font Awesome icon name — used by create',
|
|
1882
|
+
},
|
|
1883
|
+
iconColor: {
|
|
1884
|
+
type: 'string',
|
|
1885
|
+
description: 'Tailwind color — used by create',
|
|
1886
|
+
},
|
|
1887
|
+
displayMode: {
|
|
1888
|
+
type: 'string',
|
|
1889
|
+
enum: ['main', 'split', 'window'],
|
|
1890
|
+
description: 'Display mode (default: main) — used by create',
|
|
1891
|
+
},
|
|
1892
|
+
autoLaunch: {
|
|
1893
|
+
type: 'boolean',
|
|
1894
|
+
description: 'Auto-reload and run — used by create, update_html',
|
|
1895
|
+
},
|
|
1896
|
+
patches: {
|
|
1897
|
+
type: 'array',
|
|
1898
|
+
items: {
|
|
1899
|
+
type: 'object',
|
|
1900
|
+
properties: {
|
|
1901
|
+
find: { type: 'string' },
|
|
1902
|
+
replace: { type: 'string' },
|
|
1903
|
+
},
|
|
1904
|
+
required: ['find', 'replace'],
|
|
1905
|
+
},
|
|
1906
|
+
description: 'Find/replace patches — used by update_html',
|
|
1907
|
+
},
|
|
1908
|
+
query: {
|
|
1909
|
+
type: 'string',
|
|
1910
|
+
description: 'Filter/search — used by list, list_available, source',
|
|
1911
|
+
},
|
|
1912
|
+
includeBeta: {
|
|
1913
|
+
type: 'boolean',
|
|
1914
|
+
description: 'Include beta plugins — used by list_available',
|
|
1915
|
+
},
|
|
1916
|
+
tail: {
|
|
1917
|
+
type: 'integer',
|
|
1918
|
+
description: 'Return last N lines — used by log',
|
|
1919
|
+
},
|
|
1920
|
+
clear: {
|
|
1921
|
+
type: 'boolean',
|
|
1922
|
+
description: 'Clear log after reading — used by log',
|
|
1923
|
+
},
|
|
1924
|
+
startLine: {
|
|
1925
|
+
type: 'integer',
|
|
1926
|
+
description: 'Start line (1-based) — used by source',
|
|
1927
|
+
},
|
|
1928
|
+
endLine: {
|
|
1929
|
+
type: 'integer',
|
|
1930
|
+
description: 'End line (1-based) — used by source',
|
|
1931
|
+
},
|
|
1932
|
+
contextLines: {
|
|
1933
|
+
type: 'integer',
|
|
1934
|
+
description: 'Context lines around matches — used by source',
|
|
1935
|
+
},
|
|
1936
|
+
confirmationToken: {
|
|
1937
|
+
type: 'string',
|
|
1938
|
+
description: 'Token for confirmation — used by delete',
|
|
1939
|
+
},
|
|
1940
|
+
},
|
|
1941
|
+
required: ['action'],
|
|
1942
|
+
},
|
|
1943
|
+
}, {
|
|
1944
|
+
name: 'noteplan_themes',
|
|
1945
|
+
description: 'Theme management: list, get, save, set active.\n\nActions:\n- list: List all themes and active theme names\n- get: Read a custom theme JSON (requires filename)\n- save: Create/update a custom theme (requires filename + theme)\n- set_active: Activate a theme (requires name)',
|
|
1946
|
+
inputSchema: {
|
|
1947
|
+
type: 'object',
|
|
1948
|
+
properties: {
|
|
1949
|
+
action: {
|
|
1950
|
+
type: 'string',
|
|
1951
|
+
enum: ['list', 'get', 'save', 'set_active'],
|
|
1952
|
+
description: 'Action to perform',
|
|
1953
|
+
},
|
|
1954
|
+
filename: {
|
|
1955
|
+
type: 'string',
|
|
1956
|
+
description: 'Theme filename — used by get, save',
|
|
1957
|
+
},
|
|
1958
|
+
name: {
|
|
1959
|
+
type: 'string',
|
|
1960
|
+
description: 'Theme name — used by set_active',
|
|
1961
|
+
},
|
|
1962
|
+
theme: {
|
|
1963
|
+
type: 'object',
|
|
1964
|
+
description: 'Theme object — used by save',
|
|
1965
|
+
properties: {
|
|
1966
|
+
name: { type: 'string' },
|
|
1967
|
+
style: { type: 'string', enum: ['Light', 'Dark'] },
|
|
1968
|
+
author: { type: 'object', properties: { name: { type: 'string' }, email: { type: 'string' } } },
|
|
1969
|
+
editor: { type: 'object' },
|
|
1970
|
+
styles: { type: 'object' },
|
|
1971
|
+
},
|
|
1972
|
+
},
|
|
1973
|
+
setActive: {
|
|
1974
|
+
type: 'boolean',
|
|
1975
|
+
description: 'Apply theme immediately — used by save (default: true)',
|
|
1976
|
+
},
|
|
1977
|
+
mode: {
|
|
1978
|
+
type: 'string',
|
|
1979
|
+
enum: ['light', 'dark', 'auto'],
|
|
1980
|
+
description: 'Mode to apply for — used by save, set_active',
|
|
1981
|
+
},
|
|
1982
|
+
},
|
|
1983
|
+
required: ['action'],
|
|
1984
|
+
},
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
const annotatedToolDefinitions = toolDefinitions.map((tool) => ({
|
|
1988
|
+
...tool,
|
|
1989
|
+
inputSchema: withDebugTimingsInputSchema(tool.inputSchema),
|
|
1990
|
+
annotations: getToolAnnotations(tool.name),
|
|
1991
|
+
outputSchema: getToolOutputSchema(tool.name),
|
|
1992
|
+
}));
|
|
1993
|
+
const toolDefinitionByName = new Map(annotatedToolDefinitions.map((tool) => [tool.name, tool]));
|
|
1994
|
+
const registeredToolNames = annotatedToolDefinitions.map((tool) => tool.name);
|
|
1995
|
+
const registeredToolNameSet = new Set(registeredToolNames);
|
|
1996
|
+
const compactToolDefinitions = annotatedToolDefinitions.map((tool) => compactToolDefinition(tool));
|
|
1997
|
+
// Register tool listing handler — all 12 tools returned directly (no pagination needed)
|
|
1998
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
1999
|
+
return { tools: compactToolDefinitions };
|
|
2000
|
+
});
|
|
2001
|
+
// Register resource listing handler
|
|
2002
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
2003
|
+
return {
|
|
2004
|
+
resources: PLUGIN_API_RESOURCES.map((r) => ({
|
|
2005
|
+
uri: `noteplan://plugin-api/${r.file}`,
|
|
2006
|
+
name: r.name,
|
|
2007
|
+
description: r.desc,
|
|
2008
|
+
mimeType: r.file.endsWith('.md') ? 'text/markdown' : r.file.endsWith('.json') ? 'application/json' : 'text/javascript',
|
|
2009
|
+
})),
|
|
2010
|
+
};
|
|
2011
|
+
});
|
|
2012
|
+
// Register resource read handler
|
|
2013
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
2014
|
+
const uri = request.params.uri;
|
|
2015
|
+
const prefix = 'noteplan://plugin-api/';
|
|
2016
|
+
if (!uri.startsWith(prefix)) {
|
|
2017
|
+
throw new Error(`Unknown resource URI: ${uri}`);
|
|
2018
|
+
}
|
|
2019
|
+
const filename = uri.slice(prefix.length);
|
|
2020
|
+
const entry = PLUGIN_API_RESOURCES.find((r) => r.file === filename);
|
|
2021
|
+
if (!entry) {
|
|
2022
|
+
throw new Error(`Unknown resource: ${filename}. Available: ${PLUGIN_API_RESOURCES.map((r) => r.file).join(', ')}`);
|
|
2023
|
+
}
|
|
2024
|
+
const filePath = path.join(PLUGIN_API_DOCS_DIR, entry.file);
|
|
2025
|
+
if (!fs.existsSync(filePath)) {
|
|
2026
|
+
throw new Error(`Resource file not found on disk: ${filePath}`);
|
|
2027
|
+
}
|
|
2028
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
2029
|
+
return {
|
|
2030
|
+
contents: [
|
|
2031
|
+
{
|
|
2032
|
+
uri,
|
|
2033
|
+
mimeType: entry.file.endsWith('.md') ? 'text/markdown' : entry.file.endsWith('.json') ? 'application/json' : 'text/javascript',
|
|
2034
|
+
text: content,
|
|
2035
|
+
},
|
|
2036
|
+
],
|
|
2037
|
+
};
|
|
2038
|
+
});
|
|
2039
|
+
// Register tool call handler
|
|
2040
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2041
|
+
const { name, arguments: args } = request.params;
|
|
2042
|
+
const normalizedName = normalizeToolName(name);
|
|
2043
|
+
const includeTiming = isDebugTimingsEnabled(args);
|
|
2044
|
+
const startTime = Date.now();
|
|
2045
|
+
try {
|
|
2046
|
+
let result;
|
|
2047
|
+
switch (normalizedName) {
|
|
2048
|
+
// ── Primary consolidated tools ──
|
|
2049
|
+
case 'noteplan_get_notes':
|
|
2050
|
+
result = dispatchGetNotes((args ?? {}));
|
|
2051
|
+
break;
|
|
2052
|
+
case 'noteplan_search': {
|
|
2053
|
+
const searchAction = args?.action;
|
|
2054
|
+
if (searchAction === 'list_tags') {
|
|
2055
|
+
result = spaceTools.listTags(args);
|
|
2056
|
+
}
|
|
2057
|
+
else {
|
|
2058
|
+
result = await searchTools.searchNotes(args);
|
|
2059
|
+
}
|
|
2060
|
+
break;
|
|
2061
|
+
}
|
|
2062
|
+
case 'noteplan_manage_note': {
|
|
2063
|
+
const action = args?.action;
|
|
2064
|
+
const spaceWriteActions = new Set(['create', 'update', 'delete', 'move']);
|
|
2065
|
+
if (args?.space && spaceWriteActions.has(action) && !advancedFeaturesEnabled) {
|
|
2066
|
+
result = { success: false, error: upgradeMessage(`space write (${action})`), code: 'ERR_VERSION_GATE' };
|
|
2067
|
+
break;
|
|
2068
|
+
}
|
|
2069
|
+
switch (action) {
|
|
2070
|
+
case 'create':
|
|
2071
|
+
result = noteTools.createNote(args);
|
|
2072
|
+
break;
|
|
2073
|
+
case 'update':
|
|
2074
|
+
result = noteTools.updateNote(args);
|
|
2075
|
+
break;
|
|
2076
|
+
case 'delete':
|
|
2077
|
+
result = noteTools.deleteNote(args);
|
|
2078
|
+
break;
|
|
2079
|
+
case 'move':
|
|
2080
|
+
result = noteTools.moveNote(args);
|
|
2081
|
+
break;
|
|
2082
|
+
case 'restore':
|
|
2083
|
+
result = noteTools.restoreNote(args);
|
|
2084
|
+
break;
|
|
2085
|
+
case 'rename':
|
|
2086
|
+
result = noteTools.renameNoteFile(args);
|
|
2087
|
+
break;
|
|
2088
|
+
case 'set_property':
|
|
2089
|
+
result = noteTools.setProperty(args);
|
|
2090
|
+
break;
|
|
2091
|
+
case 'remove_property':
|
|
2092
|
+
result = noteTools.removeProperty(args);
|
|
2093
|
+
break;
|
|
2094
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2095
|
+
}
|
|
2096
|
+
break;
|
|
2097
|
+
}
|
|
2098
|
+
case 'noteplan_edit_content': {
|
|
2099
|
+
const a = args;
|
|
2100
|
+
if (a.space && !advancedFeaturesEnabled) {
|
|
2101
|
+
const editAction = a?.action ?? 'edit';
|
|
2102
|
+
result = { success: false, error: upgradeMessage(`space write (${editAction})`), code: 'ERR_VERSION_GATE' };
|
|
2103
|
+
break;
|
|
2104
|
+
}
|
|
2105
|
+
if (a.scheduleDate && a.content) {
|
|
2106
|
+
a.content = appendScheduleDate(a.content, a.scheduleDate);
|
|
2107
|
+
}
|
|
2108
|
+
const action = a?.action;
|
|
2109
|
+
switch (action) {
|
|
2110
|
+
case 'insert':
|
|
2111
|
+
result = noteTools.insertContent(a);
|
|
2112
|
+
break;
|
|
2113
|
+
case 'append':
|
|
2114
|
+
result = noteTools.appendContent(a);
|
|
2115
|
+
break;
|
|
2116
|
+
case 'delete_lines':
|
|
2117
|
+
result = noteTools.deleteLines(a);
|
|
2118
|
+
break;
|
|
2119
|
+
case 'edit_line':
|
|
2120
|
+
result = noteTools.editLine(a);
|
|
2121
|
+
break;
|
|
2122
|
+
case 'replace_lines':
|
|
2123
|
+
result = noteTools.replaceLines(a);
|
|
2124
|
+
break;
|
|
2125
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2126
|
+
}
|
|
2127
|
+
break;
|
|
2128
|
+
}
|
|
2129
|
+
case 'noteplan_paragraphs': {
|
|
2130
|
+
const a = args;
|
|
2131
|
+
const paragraphWriteActions = new Set(['add', 'complete', 'update']);
|
|
2132
|
+
if (a.space && paragraphWriteActions.has(a.action) && !advancedFeaturesEnabled) {
|
|
2133
|
+
result = { success: false, error: upgradeMessage(`space write (${a.action})`), code: 'ERR_VERSION_GATE' };
|
|
2134
|
+
break;
|
|
2135
|
+
}
|
|
2136
|
+
if (a.scheduleDate && a.content) {
|
|
2137
|
+
a.content = appendScheduleDate(a.content, a.scheduleDate);
|
|
2138
|
+
}
|
|
2139
|
+
const action = a?.action;
|
|
2140
|
+
switch (action) {
|
|
2141
|
+
case 'get':
|
|
2142
|
+
result = noteTools.getParagraphs(a);
|
|
2143
|
+
break;
|
|
2144
|
+
case 'search':
|
|
2145
|
+
result = noteTools.searchParagraphs(a);
|
|
2146
|
+
break;
|
|
2147
|
+
case 'search_global':
|
|
2148
|
+
result = taskTools.searchTasksGlobal(a);
|
|
2149
|
+
break;
|
|
2150
|
+
case 'add':
|
|
2151
|
+
result = taskTools.addTaskToNote(a);
|
|
2152
|
+
break;
|
|
2153
|
+
case 'complete':
|
|
2154
|
+
result = taskTools.completeTask(a);
|
|
2155
|
+
break;
|
|
2156
|
+
case 'update':
|
|
2157
|
+
result = taskTools.updateTask(a);
|
|
2158
|
+
break;
|
|
2159
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2160
|
+
}
|
|
2161
|
+
break;
|
|
2162
|
+
}
|
|
2163
|
+
case 'noteplan_folders': {
|
|
2164
|
+
const action = args?.action;
|
|
2165
|
+
const folderWriteActions = new Set(['create', 'move', 'rename', 'delete']);
|
|
2166
|
+
if (args?.space && folderWriteActions.has(action) && !advancedFeaturesEnabled) {
|
|
2167
|
+
result = { success: false, error: upgradeMessage(`space folder (${action})`), code: 'ERR_VERSION_GATE' };
|
|
2168
|
+
break;
|
|
2169
|
+
}
|
|
2170
|
+
switch (action) {
|
|
2171
|
+
case 'list':
|
|
2172
|
+
result = spaceTools.listFolders(args);
|
|
2173
|
+
break;
|
|
2174
|
+
case 'find':
|
|
2175
|
+
result = spaceTools.findFolders(args);
|
|
2176
|
+
break;
|
|
2177
|
+
case 'resolve':
|
|
2178
|
+
result = spaceTools.resolveFolder(args);
|
|
2179
|
+
break;
|
|
2180
|
+
case 'create':
|
|
2181
|
+
result = spaceTools.createFolder(args);
|
|
2182
|
+
break;
|
|
2183
|
+
case 'move':
|
|
2184
|
+
result = spaceTools.moveFolder(args);
|
|
2185
|
+
break;
|
|
2186
|
+
case 'rename':
|
|
2187
|
+
result = spaceTools.renameFolder(args);
|
|
2188
|
+
break;
|
|
2189
|
+
case 'delete':
|
|
2190
|
+
result = spaceTools.deleteFolder(args);
|
|
2191
|
+
break;
|
|
2192
|
+
case 'list_spaces':
|
|
2193
|
+
result = spaceTools.listSpaces(args);
|
|
2194
|
+
break;
|
|
2195
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2196
|
+
}
|
|
2197
|
+
break;
|
|
2198
|
+
}
|
|
2199
|
+
case 'noteplan_filters': {
|
|
2200
|
+
const action = args?.action;
|
|
2201
|
+
switch (action) {
|
|
2202
|
+
case 'list':
|
|
2203
|
+
result = filterTools.listFilters(args);
|
|
2204
|
+
break;
|
|
2205
|
+
case 'get':
|
|
2206
|
+
result = filterTools.getFilter(args);
|
|
2207
|
+
break;
|
|
2208
|
+
case 'get_tasks':
|
|
2209
|
+
result = filterTools.getFilterTasks(args);
|
|
2210
|
+
break;
|
|
2211
|
+
case 'list_parameters':
|
|
2212
|
+
result = filterTools.listFilterParameters();
|
|
2213
|
+
break;
|
|
2214
|
+
case 'save':
|
|
2215
|
+
result = filterTools.saveFilter(args);
|
|
2216
|
+
break;
|
|
2217
|
+
case 'rename':
|
|
2218
|
+
result = filterTools.renameFilter(args);
|
|
2219
|
+
break;
|
|
2220
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2221
|
+
}
|
|
2222
|
+
break;
|
|
2223
|
+
}
|
|
2224
|
+
case 'noteplan_eventkit': {
|
|
2225
|
+
const a = args;
|
|
2226
|
+
const source = a?.source;
|
|
2227
|
+
const action = a?.action;
|
|
2228
|
+
if (source === 'reminders') {
|
|
2229
|
+
switch (action) {
|
|
2230
|
+
case 'get':
|
|
2231
|
+
result = reminderTools.getReminders(a);
|
|
2232
|
+
break;
|
|
2233
|
+
case 'list_lists':
|
|
2234
|
+
result = reminderTools.listReminderLists(a);
|
|
2235
|
+
break;
|
|
2236
|
+
case 'create':
|
|
2237
|
+
result = reminderTools.createReminder(a);
|
|
2238
|
+
break;
|
|
2239
|
+
case 'complete':
|
|
2240
|
+
result = reminderTools.completeReminder(a);
|
|
2241
|
+
break;
|
|
2242
|
+
case 'update':
|
|
2243
|
+
result = reminderTools.updateReminder(a);
|
|
2244
|
+
break;
|
|
2245
|
+
case 'delete':
|
|
2246
|
+
result = reminderTools.deleteReminder(a);
|
|
2247
|
+
break;
|
|
2248
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
else {
|
|
2252
|
+
switch (action) {
|
|
2253
|
+
case 'get_events':
|
|
2254
|
+
result = eventTools.getEvents(a);
|
|
2255
|
+
break;
|
|
2256
|
+
case 'list_calendars':
|
|
2257
|
+
result = eventTools.listCalendars(a);
|
|
2258
|
+
break;
|
|
2259
|
+
case 'create_event':
|
|
2260
|
+
result = eventTools.createEvent(a);
|
|
2261
|
+
break;
|
|
2262
|
+
case 'update_event':
|
|
2263
|
+
result = eventTools.updateEvent(a);
|
|
2264
|
+
break;
|
|
2265
|
+
case 'delete_event':
|
|
2266
|
+
result = eventTools.deleteEvent(a);
|
|
2267
|
+
break;
|
|
2268
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
break;
|
|
2272
|
+
}
|
|
2273
|
+
case 'noteplan_memory': {
|
|
2274
|
+
const action = args?.action;
|
|
2275
|
+
switch (action) {
|
|
2276
|
+
case 'list':
|
|
2277
|
+
result = memoryTools.listMemories(args);
|
|
2278
|
+
break;
|
|
2279
|
+
case 'save':
|
|
2280
|
+
result = memoryTools.saveMemory(args);
|
|
2281
|
+
break;
|
|
2282
|
+
case 'update':
|
|
2283
|
+
result = memoryTools.updateMemory(args);
|
|
2284
|
+
break;
|
|
2285
|
+
case 'delete':
|
|
2286
|
+
result = memoryTools.deleteMemory(args);
|
|
2287
|
+
break;
|
|
2288
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2289
|
+
}
|
|
2290
|
+
break;
|
|
2291
|
+
}
|
|
2292
|
+
case 'noteplan_ui': {
|
|
2293
|
+
const action = args?.action;
|
|
2294
|
+
switch (action) {
|
|
2295
|
+
case 'open_note':
|
|
2296
|
+
result = uiTools.openNote(args);
|
|
2297
|
+
break;
|
|
2298
|
+
case 'open_today':
|
|
2299
|
+
result = uiTools.openToday(args);
|
|
2300
|
+
break;
|
|
2301
|
+
case 'search':
|
|
2302
|
+
result = uiTools.searchNotes(args);
|
|
2303
|
+
break;
|
|
2304
|
+
case 'run_plugin':
|
|
2305
|
+
result = uiTools.runPlugin(args);
|
|
2306
|
+
break;
|
|
2307
|
+
case 'open_view':
|
|
2308
|
+
result = uiTools.openView(args);
|
|
2309
|
+
break;
|
|
2310
|
+
case 'toggle_sidebar':
|
|
2311
|
+
result = uiTools.toggleSidebar(args);
|
|
2312
|
+
break;
|
|
2313
|
+
case 'close_plugin_window':
|
|
2314
|
+
result = uiTools.closePluginWindow(args);
|
|
2315
|
+
break;
|
|
2316
|
+
case 'list_plugin_windows':
|
|
2317
|
+
result = uiTools.listPluginWindows(args);
|
|
2318
|
+
break;
|
|
2319
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2320
|
+
}
|
|
2321
|
+
break;
|
|
2322
|
+
}
|
|
2323
|
+
case 'noteplan_plugins': {
|
|
2324
|
+
const action = args?.action;
|
|
2325
|
+
switch (action) {
|
|
2326
|
+
case 'list':
|
|
2327
|
+
result = pluginTools.listPlugins(args);
|
|
2328
|
+
break;
|
|
2329
|
+
case 'list_available':
|
|
2330
|
+
result = pluginTools.listAvailablePlugins(args);
|
|
2331
|
+
break;
|
|
2332
|
+
case 'create':
|
|
2333
|
+
result = pluginTools.createPlugin(args);
|
|
2334
|
+
break;
|
|
2335
|
+
case 'delete':
|
|
2336
|
+
result = pluginTools.deletePlugin(args);
|
|
2337
|
+
break;
|
|
2338
|
+
case 'install':
|
|
2339
|
+
result = pluginTools.installPlugin(args);
|
|
2340
|
+
break;
|
|
2341
|
+
case 'log':
|
|
2342
|
+
result = pluginTools.getPluginLog(args);
|
|
2343
|
+
break;
|
|
2344
|
+
case 'source':
|
|
2345
|
+
result = pluginTools.getPluginSource(args);
|
|
2346
|
+
break;
|
|
2347
|
+
case 'update_html':
|
|
2348
|
+
result = pluginTools.updatePluginHtml(args);
|
|
2349
|
+
break;
|
|
2350
|
+
case 'screenshot':
|
|
2351
|
+
result = pluginTools.screenshotPlugin(args);
|
|
2352
|
+
break;
|
|
2353
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2354
|
+
}
|
|
2355
|
+
break;
|
|
2356
|
+
}
|
|
2357
|
+
case 'noteplan_themes': {
|
|
2358
|
+
const action = args?.action;
|
|
2359
|
+
switch (action) {
|
|
2360
|
+
case 'list':
|
|
2361
|
+
result = themeTools.listThemes(args);
|
|
2362
|
+
break;
|
|
2363
|
+
case 'get':
|
|
2364
|
+
result = themeTools.getTheme(args);
|
|
2365
|
+
break;
|
|
2366
|
+
case 'save':
|
|
2367
|
+
result = themeTools.saveTheme(args);
|
|
2368
|
+
break;
|
|
2369
|
+
case 'set_active':
|
|
2370
|
+
result = themeTools.setTheme(args);
|
|
2371
|
+
break;
|
|
2372
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2373
|
+
}
|
|
2374
|
+
break;
|
|
2375
|
+
}
|
|
2376
|
+
case 'noteplan_embeddings': {
|
|
2377
|
+
const action = args?.action;
|
|
2378
|
+
switch (action) {
|
|
2379
|
+
case 'status':
|
|
2380
|
+
result = embeddingsTools.embeddingsStatus(args);
|
|
2381
|
+
break;
|
|
2382
|
+
case 'search':
|
|
2383
|
+
result = await embeddingsTools.embeddingsSearch(args);
|
|
2384
|
+
break;
|
|
2385
|
+
case 'sync':
|
|
2386
|
+
result = await embeddingsTools.embeddingsSync(args);
|
|
2387
|
+
break;
|
|
2388
|
+
case 'reset':
|
|
2389
|
+
result = embeddingsTools.embeddingsReset(args);
|
|
2390
|
+
break;
|
|
2391
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
2392
|
+
}
|
|
2393
|
+
break;
|
|
2394
|
+
}
|
|
2395
|
+
default:
|
|
2396
|
+
throw new Error(`Unknown tool: ${name} (normalized: ${normalizedName})`);
|
|
2397
|
+
}
|
|
2398
|
+
const enrichedResult = enrichErrorResult(result, normalizedName, registeredToolNames);
|
|
2399
|
+
const resultWithSuggestions = withSuggestedNextTools(enrichedResult, normalizedName, registeredToolNameSet);
|
|
2400
|
+
const resultWithMemory = withMemoryHints(resultWithSuggestions, normalizedName);
|
|
2401
|
+
const resultWithDuration = withDuration(resultWithMemory, Date.now() - startTime, includeTiming);
|
|
2402
|
+
const hasOutputSchema = Boolean(toolDefinitionByName.get(normalizedName)?.outputSchema);
|
|
2403
|
+
// If the result contains image data, return it as an MCP image content block
|
|
2404
|
+
const typedResult = resultWithDuration;
|
|
2405
|
+
if (typedResult._imageData && typedResult._imageMimeType) {
|
|
2406
|
+
const imageData = typedResult._imageData;
|
|
2407
|
+
const imageMimeType = typedResult._imageMimeType;
|
|
2408
|
+
// Strip image data from the text response to avoid bloating it
|
|
2409
|
+
const { _imageData: _, _imageMimeType: __, ...textResult } = typedResult;
|
|
2410
|
+
return {
|
|
2411
|
+
content: [
|
|
2412
|
+
{
|
|
2413
|
+
type: 'image',
|
|
2414
|
+
data: imageData,
|
|
2415
|
+
mimeType: imageMimeType,
|
|
2416
|
+
},
|
|
2417
|
+
{
|
|
2418
|
+
type: 'text',
|
|
2419
|
+
text: JSON.stringify(textResult),
|
|
2420
|
+
},
|
|
2421
|
+
],
|
|
2422
|
+
};
|
|
2423
|
+
}
|
|
2424
|
+
return {
|
|
2425
|
+
content: [
|
|
2426
|
+
{
|
|
2427
|
+
type: 'text',
|
|
2428
|
+
text: JSON.stringify(resultWithDuration),
|
|
2429
|
+
},
|
|
2430
|
+
],
|
|
2431
|
+
...(hasOutputSchema ? { structuredContent: resultWithDuration } : {}),
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
catch (error) {
|
|
2435
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
2436
|
+
const meta = inferToolErrorMeta(normalizedName, errorMessage, registeredToolNames);
|
|
2437
|
+
const errorResult = {
|
|
2438
|
+
success: false,
|
|
2439
|
+
error: errorMessage,
|
|
2440
|
+
code: meta.code,
|
|
2441
|
+
hint: meta.hint,
|
|
2442
|
+
suggestedTool: meta.suggestedTool,
|
|
2443
|
+
retryable: meta.retryable,
|
|
2444
|
+
};
|
|
2445
|
+
const errorWithDuration = withDuration(errorResult, Date.now() - startTime, includeTiming);
|
|
2446
|
+
const hasOutputSchema = Boolean(toolDefinitionByName.get(normalizedName)?.outputSchema);
|
|
2447
|
+
return {
|
|
2448
|
+
content: [
|
|
2449
|
+
{
|
|
2450
|
+
type: 'text',
|
|
2451
|
+
text: JSON.stringify(errorWithDuration),
|
|
2452
|
+
},
|
|
2453
|
+
],
|
|
2454
|
+
...(hasOutputSchema ? { structuredContent: errorWithDuration } : {}),
|
|
2455
|
+
isError: true,
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2458
|
+
});
|
|
2459
|
+
return server;
|
|
2460
|
+
}
|
|
2461
|
+
// Start the server with stdio transport
|
|
2462
|
+
export async function startServer() {
|
|
2463
|
+
const server = createServer();
|
|
2464
|
+
const transport = new StdioServerTransport();
|
|
2465
|
+
await server.connect(transport);
|
|
2466
|
+
console.error('NotePlan MCP server running on stdio');
|
|
2467
|
+
}
|
|
2468
|
+
//# sourceMappingURL=server.js.map
|