@noteplanco/noteplan-mcp 1.1.23 → 1.1.25
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 +7 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/noteplan/attachments-paths.d.ts +13 -0
- package/dist/noteplan/attachments-paths.d.ts.map +1 -0
- package/dist/noteplan/attachments-paths.js +27 -0
- package/dist/noteplan/attachments-paths.js.map +1 -0
- package/dist/noteplan/embeddings.js +1 -1
- package/dist/noteplan/embeddings.js.map +1 -1
- package/dist/noteplan/file-reader.d.ts +37 -46
- package/dist/noteplan/file-reader.d.ts.map +1 -1
- package/dist/noteplan/file-reader.js +200 -202
- package/dist/noteplan/file-reader.js.map +1 -1
- package/dist/noteplan/file-reader.test.d.ts +2 -0
- package/dist/noteplan/file-reader.test.d.ts.map +1 -0
- package/dist/noteplan/file-reader.test.js +67 -0
- package/dist/noteplan/file-reader.test.js.map +1 -0
- package/dist/noteplan/file-writer.d.ts +35 -31
- package/dist/noteplan/file-writer.d.ts.map +1 -1
- package/dist/noteplan/file-writer.js +280 -164
- package/dist/noteplan/file-writer.js.map +1 -1
- package/dist/noteplan/file-writer.test.js +704 -191
- package/dist/noteplan/file-writer.test.js.map +1 -1
- package/dist/noteplan/filter-store.d.ts +5 -5
- package/dist/noteplan/filter-store.d.ts.map +1 -1
- package/dist/noteplan/filter-store.js +94 -79
- package/dist/noteplan/filter-store.js.map +1 -1
- package/dist/noteplan/ripgrep-search.d.ts +25 -2
- package/dist/noteplan/ripgrep-search.d.ts.map +1 -1
- package/dist/noteplan/ripgrep-search.js +75 -2
- package/dist/noteplan/ripgrep-search.js.map +1 -1
- package/dist/noteplan/space-row-utils.d.ts +20 -0
- package/dist/noteplan/space-row-utils.d.ts.map +1 -0
- package/dist/noteplan/space-row-utils.js +78 -0
- package/dist/noteplan/space-row-utils.js.map +1 -0
- package/dist/noteplan/space-row-utils.test.d.ts +2 -0
- package/dist/noteplan/space-row-utils.test.d.ts.map +1 -0
- package/dist/noteplan/space-row-utils.test.js +123 -0
- package/dist/noteplan/space-row-utils.test.js.map +1 -0
- package/dist/noteplan/sqlite-reader.d.ts +12 -27
- package/dist/noteplan/sqlite-reader.d.ts.map +1 -1
- package/dist/noteplan/sqlite-reader.js +315 -221
- package/dist/noteplan/sqlite-reader.js.map +1 -1
- package/dist/noteplan/sqlite-writer.d.ts +1 -1
- package/dist/noteplan/sqlite-writer.d.ts.map +1 -1
- package/dist/noteplan/sqlite-writer.js +2 -2
- package/dist/noteplan/sqlite-writer.js.map +1 -1
- package/dist/noteplan/unified-store.d.ts +41 -30
- package/dist/noteplan/unified-store.d.ts.map +1 -1
- package/dist/noteplan/unified-store.js +257 -159
- package/dist/noteplan/unified-store.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +142 -61
- package/dist/server.js.map +1 -1
- package/dist/tools/attachments.d.ts +9 -9
- package/dist/tools/attachments.d.ts.map +1 -1
- package/dist/tools/attachments.js +74 -83
- package/dist/tools/attachments.js.map +1 -1
- package/dist/tools/attachments.test.js +170 -129
- package/dist/tools/attachments.test.js.map +1 -1
- package/dist/tools/calendar.d.ts +16 -13
- package/dist/tools/calendar.d.ts.map +1 -1
- package/dist/tools/calendar.js +17 -16
- package/dist/tools/calendar.js.map +1 -1
- package/dist/tools/embeddings.d.ts +6 -6
- package/dist/tools/embeddings.d.ts.map +1 -1
- package/dist/tools/embeddings.js +6 -6
- package/dist/tools/embeddings.js.map +1 -1
- package/dist/tools/events.d.ts +7 -3
- package/dist/tools/events.d.ts.map +1 -1
- package/dist/tools/events.js +51 -16
- package/dist/tools/events.js.map +1 -1
- package/dist/tools/filters.d.ts +28 -33
- package/dist/tools/filters.d.ts.map +1 -1
- package/dist/tools/filters.js +42 -105
- package/dist/tools/filters.js.map +1 -1
- package/dist/tools/notes.d.ts +80 -218
- package/dist/tools/notes.d.ts.map +1 -1
- package/dist/tools/notes.js +180 -177
- package/dist/tools/notes.js.map +1 -1
- package/dist/tools/notes.test.js +242 -21
- package/dist/tools/notes.test.js.map +1 -1
- package/dist/tools/search.d.ts +4 -3
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +9 -5
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/search.test.d.ts +2 -0
- package/dist/tools/search.test.d.ts.map +1 -0
- package/dist/tools/search.test.js +37 -0
- package/dist/tools/search.test.js.map +1 -0
- package/dist/tools/spaces.d.ts +20 -20
- package/dist/tools/spaces.d.ts.map +1 -1
- package/dist/tools/spaces.js +28 -28
- package/dist/tools/spaces.js.map +1 -1
- package/dist/tools/tasks.d.ts +22 -22
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +22 -22
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/templates.d.ts +7 -7
- package/dist/tools/templates.d.ts.map +1 -1
- package/dist/tools/templates.js +4 -4
- package/dist/tools/templates.js.map +1 -1
- package/dist/tools/themes.d.ts.map +1 -1
- package/dist/tools/themes.js +26 -35
- package/dist/tools/themes.js.map +1 -1
- package/dist/transport/bridge-availability.d.ts +5 -0
- package/dist/transport/bridge-availability.d.ts.map +1 -0
- package/dist/transport/bridge-availability.js +92 -0
- package/dist/transport/bridge-availability.js.map +1 -0
- package/dist/transport/bridge-cascade.d.ts +18 -0
- package/dist/transport/bridge-cascade.d.ts.map +1 -0
- package/dist/transport/bridge-cascade.js +78 -0
- package/dist/transport/bridge-cascade.js.map +1 -0
- package/dist/transport/bridge-cascade.test.d.ts +2 -0
- package/dist/transport/bridge-cascade.test.d.ts.map +1 -0
- package/dist/transport/bridge-cascade.test.js +160 -0
- package/dist/transport/bridge-cascade.test.js.map +1 -0
- package/dist/transport/bridge-client.d.ts +197 -0
- package/dist/transport/bridge-client.d.ts.map +1 -0
- package/dist/transport/bridge-client.js +288 -0
- package/dist/transport/bridge-client.js.map +1 -0
- package/dist/transport/bridge-client.test.d.ts +2 -0
- package/dist/transport/bridge-client.test.d.ts.map +1 -0
- package/dist/transport/bridge-client.test.js +384 -0
- package/dist/transport/bridge-client.test.js.map +1 -0
- package/dist/transport/bridge-context.d.ts +10 -0
- package/dist/transport/bridge-context.d.ts.map +1 -0
- package/dist/transport/bridge-context.js +18 -0
- package/dist/transport/bridge-context.js.map +1 -0
- package/dist/transport/bridge-fs.d.ts +25 -0
- package/dist/transport/bridge-fs.d.ts.map +1 -0
- package/dist/transport/bridge-fs.js +129 -0
- package/dist/transport/bridge-fs.js.map +1 -0
- package/dist/utils/date-utils.d.ts +24 -0
- package/dist/utils/date-utils.d.ts.map +1 -1
- package/dist/utils/date-utils.js +55 -0
- package/dist/utils/date-utils.js.map +1 -1
- package/dist/utils/date-utils.test.d.ts +2 -0
- package/dist/utils/date-utils.test.d.ts.map +1 -0
- package/dist/utils/date-utils.test.js +109 -0
- package/dist/utils/date-utils.test.js.map +1 -0
- package/dist/utils/folder-access.d.ts +23 -0
- package/dist/utils/folder-access.d.ts.map +1 -0
- package/dist/utils/folder-access.js +131 -0
- package/dist/utils/folder-access.js.map +1 -0
- package/dist/utils/folder-access.test.d.ts +2 -0
- package/dist/utils/folder-access.test.d.ts.map +1 -0
- package/dist/utils/folder-access.test.js +182 -0
- package/dist/utils/folder-access.test.js.map +1 -0
- package/dist/utils/folder-matcher.d.ts.map +1 -1
- package/dist/utils/folder-matcher.js +16 -0
- package/dist/utils/folder-matcher.js.map +1 -1
- package/dist/utils/folder-matcher.test.js +42 -0
- package/dist/utils/folder-matcher.test.js.map +1 -1
- package/dist/utils/server-config.d.ts +10 -2
- package/dist/utils/server-config.d.ts.map +1 -1
- package/dist/utils/server-config.js +16 -2
- package/dist/utils/server-config.js.map +1 -1
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +5 -1
- package/dist/utils/version.js.map +1 -1
- package/package.json +4 -3
- package/scripts/calendar-helper +0 -0
- package/scripts/reminders-helper +0 -0
package/dist/server.js
CHANGED
|
@@ -24,9 +24,11 @@ import * as templateTools from './tools/templates.js';
|
|
|
24
24
|
import * as attachmentTools from './tools/attachments.js';
|
|
25
25
|
import { parseFlexibleDate } from './utils/date-utils.js';
|
|
26
26
|
import { upgradeMessage, getNotePlanVersion, getMcpServerVersion, MIN_BUILD_ADVANCED_FEATURES, MIN_BUILD_CREATE_BACKUP } from './utils/version.js';
|
|
27
|
-
import { isReadOnly, isSkipDryRun } from './utils/server-config.js';
|
|
27
|
+
import { isReadOnly, isSkipDryRun, shouldAutoLaunchNotePlan } from './utils/server-config.js';
|
|
28
28
|
import { initSqlite } from './noteplan/sqlite-loader.js';
|
|
29
29
|
import { getDatabase, getDatabasePath, listSpaces as listSpacesFromDb } from './noteplan/sqlite-reader.js';
|
|
30
|
+
import { getBridgeClient } from './transport/bridge-availability.js';
|
|
31
|
+
import { withBackendTracking, getCurrentBackends } from './transport/bridge-context.js';
|
|
30
32
|
const __filename = fileURLToPath(import.meta.url);
|
|
31
33
|
const __dirname = path.dirname(__filename);
|
|
32
34
|
const PLUGIN_API_DOCS_DIR = path.join(__dirname, '../docs/plugin-api');
|
|
@@ -236,7 +238,7 @@ const PERIOD_TYPE_MAP = {
|
|
|
236
238
|
quarter: 'quarterly',
|
|
237
239
|
year: 'yearly',
|
|
238
240
|
};
|
|
239
|
-
function dispatchGetNotes(args) {
|
|
241
|
+
async function dispatchGetNotes(args) {
|
|
240
242
|
const { resolve, resolveQuery, id, title, filename, date, period, count, rangePeriod, startDate, endDate, folder, space, types, query, limit, offset, cursor, minScore, ambiguityDelta,
|
|
241
243
|
// periodic note params
|
|
242
244
|
week, month, quarter, year, fromDate, includeContent, includeMissing, maxLookback,
|
|
@@ -839,19 +841,35 @@ function withDuration(result, durationMs, includeTiming) {
|
|
|
839
841
|
durationMs,
|
|
840
842
|
};
|
|
841
843
|
}
|
|
842
|
-
|
|
844
|
+
/** Attach `backends` (e.g. `["bridge"]` or `["fallback"]` or both) to a tool
|
|
845
|
+
* response when the tool's work passed through bridgeOrFallback. Reads the
|
|
846
|
+
* request-scoped tracker set up by withBackendTracking in the dispatcher.
|
|
847
|
+
* No-op for results that aren't plain objects. */
|
|
848
|
+
function withBackend(result) {
|
|
849
|
+
const backends = getCurrentBackends();
|
|
850
|
+
if (backends.length === 0)
|
|
851
|
+
return result;
|
|
852
|
+
if (result && typeof result === 'object' && !Array.isArray(result)) {
|
|
853
|
+
return {
|
|
854
|
+
...result,
|
|
855
|
+
backends,
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
return result;
|
|
859
|
+
}
|
|
843
860
|
// Create the server
|
|
844
861
|
export function createServer() {
|
|
862
|
+
const mcpServerVersion = getMcpServerVersion();
|
|
845
863
|
const server = new Server({
|
|
846
864
|
name: 'NotePlan',
|
|
847
|
-
version:
|
|
865
|
+
version: mcpServerVersion,
|
|
848
866
|
}, {
|
|
849
867
|
capabilities: {
|
|
850
868
|
tools: { listChanged: true },
|
|
851
869
|
resources: {},
|
|
852
870
|
},
|
|
853
871
|
instructions: [
|
|
854
|
-
`You have access to NotePlan — a markdown-based note-taking and task management app for macOS/iOS. (MCP server v${
|
|
872
|
+
`You have access to NotePlan — a markdown-based note-taking and task management app for macOS/iOS. (MCP server v${mcpServerVersion})`,
|
|
855
873
|
'All tools use action-based dispatch: one tool per domain, with an `action` parameter to select the operation.',
|
|
856
874
|
'',
|
|
857
875
|
'## Workflow',
|
|
@@ -923,8 +941,9 @@ export function createServer() {
|
|
|
923
941
|
const database = getDatabase();
|
|
924
942
|
const writable = database ? 'read-write' : 'unavailable';
|
|
925
943
|
console.error(`[noteplan-mcp] Space database: ${dbPath} (${writable})`);
|
|
926
|
-
|
|
927
|
-
|
|
944
|
+
listSpacesFromDb()
|
|
945
|
+
.then((spaces) => console.error(`[noteplan-mcp] Spaces discovered: ${spaces.length}`))
|
|
946
|
+
.catch((err) => console.error('[noteplan-mcp] Failed to list spaces:', err));
|
|
928
947
|
}
|
|
929
948
|
else {
|
|
930
949
|
console.error('[noteplan-mcp] Space database: not found');
|
|
@@ -938,6 +957,9 @@ export function createServer() {
|
|
|
938
957
|
if (skipDryRun) {
|
|
939
958
|
console.error('[noteplan-mcp] Skip dry-run: ENABLED (confirmation tokens not required)');
|
|
940
959
|
}
|
|
960
|
+
if (!shouldAutoLaunchNotePlan()) {
|
|
961
|
+
console.error('[noteplan-mcp] Auto-launch: DISABLED (NOTEPLAN_MCP_AUTOLAUNCH=false; bridge probe stays passive when NotePlan is closed)');
|
|
962
|
+
}
|
|
941
963
|
const toolDefinitions = [
|
|
942
964
|
// ── Consolidated tools (16 — action/param-based dispatch) ──
|
|
943
965
|
{
|
|
@@ -2472,7 +2494,7 @@ export function createServer() {
|
|
|
2472
2494
|
],
|
|
2473
2495
|
};
|
|
2474
2496
|
// Register tool call handler
|
|
2475
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2497
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => withBackendTracking(async () => {
|
|
2476
2498
|
const { name, arguments: args } = request.params;
|
|
2477
2499
|
const normalizedName = normalizeToolName(name);
|
|
2478
2500
|
const includeTiming = isDebugTimingsEnabled(args);
|
|
@@ -2485,7 +2507,8 @@ export function createServer() {
|
|
|
2485
2507
|
if (args?.action === 'list_actions' && TOOL_ACTIONS[normalizedName]) {
|
|
2486
2508
|
result = { success: true, tool: normalizedName, actions: TOOL_ACTIONS[normalizedName] };
|
|
2487
2509
|
const resultWithDuration = withDuration(result, Date.now() - startTime, includeTiming);
|
|
2488
|
-
|
|
2510
|
+
const finalResult = withBackend(resultWithDuration);
|
|
2511
|
+
return { content: [{ type: 'text', text: JSON.stringify(finalResult, null, 2) }] };
|
|
2489
2512
|
}
|
|
2490
2513
|
// ── Read-only mode: reject write actions ──
|
|
2491
2514
|
if (readOnly) {
|
|
@@ -2495,9 +2518,10 @@ export function createServer() {
|
|
|
2495
2518
|
const errorResult = { success: false, error: `Read-only mode is enabled (NOTEPLAN_READ_ONLY=true). Write action "${action}" on ${normalizedName} is not allowed.`, code: 'ERR_READ_ONLY' };
|
|
2496
2519
|
const hasOutputSchema = !!toolDefinitions.find(t => t.name === normalizedName)?.outputSchema;
|
|
2497
2520
|
const resultWithDuration = withDuration(errorResult, Date.now() - startTime, includeTiming);
|
|
2521
|
+
const finalResult = withBackend(resultWithDuration);
|
|
2498
2522
|
return {
|
|
2499
|
-
content: [{ type: 'text', text: JSON.stringify(
|
|
2500
|
-
...(hasOutputSchema ? { structuredContent:
|
|
2523
|
+
content: [{ type: 'text', text: JSON.stringify(finalResult, null, 2) }],
|
|
2524
|
+
...(hasOutputSchema ? { structuredContent: finalResult } : {}),
|
|
2501
2525
|
isError: true,
|
|
2502
2526
|
};
|
|
2503
2527
|
}
|
|
@@ -2505,12 +2529,12 @@ export function createServer() {
|
|
|
2505
2529
|
switch (normalizedName) {
|
|
2506
2530
|
// ── Primary consolidated tools ──
|
|
2507
2531
|
case 'noteplan_get_notes':
|
|
2508
|
-
result = dispatchGetNotes((args ?? {}));
|
|
2532
|
+
result = await dispatchGetNotes((args ?? {}));
|
|
2509
2533
|
break;
|
|
2510
2534
|
case 'noteplan_search': {
|
|
2511
2535
|
const searchAction = args?.action;
|
|
2512
2536
|
if (searchAction === 'list_tags') {
|
|
2513
|
-
result = spaceTools.listTags(args);
|
|
2537
|
+
result = await spaceTools.listTags(args);
|
|
2514
2538
|
}
|
|
2515
2539
|
else {
|
|
2516
2540
|
result = await searchTools.searchNotes(args);
|
|
@@ -2526,28 +2550,28 @@ export function createServer() {
|
|
|
2526
2550
|
}
|
|
2527
2551
|
switch (action) {
|
|
2528
2552
|
case 'create':
|
|
2529
|
-
result = noteTools.createNote(args);
|
|
2553
|
+
result = await noteTools.createNote(args);
|
|
2530
2554
|
break;
|
|
2531
2555
|
case 'update':
|
|
2532
|
-
result = noteTools.updateNote(args);
|
|
2556
|
+
result = await noteTools.updateNote(args);
|
|
2533
2557
|
break;
|
|
2534
2558
|
case 'delete':
|
|
2535
|
-
result = noteTools.deleteNote(args);
|
|
2559
|
+
result = await noteTools.deleteNote(args);
|
|
2536
2560
|
break;
|
|
2537
2561
|
case 'move':
|
|
2538
|
-
result = noteTools.moveNote(args);
|
|
2562
|
+
result = await noteTools.moveNote(args);
|
|
2539
2563
|
break;
|
|
2540
2564
|
case 'restore':
|
|
2541
|
-
result = noteTools.restoreNote(args);
|
|
2565
|
+
result = await noteTools.restoreNote(args);
|
|
2542
2566
|
break;
|
|
2543
2567
|
case 'rename':
|
|
2544
|
-
result = noteTools.renameNoteFile(args);
|
|
2568
|
+
result = await noteTools.renameNoteFile(args);
|
|
2545
2569
|
break;
|
|
2546
2570
|
case 'set_property':
|
|
2547
|
-
result = noteTools.setProperty(args);
|
|
2571
|
+
result = await noteTools.setProperty(args);
|
|
2548
2572
|
break;
|
|
2549
2573
|
case 'remove_property':
|
|
2550
|
-
result = noteTools.removeProperty(args);
|
|
2574
|
+
result = await noteTools.removeProperty(args);
|
|
2551
2575
|
break;
|
|
2552
2576
|
default: throw new Error(`Unknown action: "${action}". Valid actions: create, update, delete, move, restore, rename, set_property, remove_property`);
|
|
2553
2577
|
}
|
|
@@ -2566,19 +2590,19 @@ export function createServer() {
|
|
|
2566
2590
|
const action = a?.action;
|
|
2567
2591
|
switch (action) {
|
|
2568
2592
|
case 'insert':
|
|
2569
|
-
result = noteTools.insertContent(a);
|
|
2593
|
+
result = await noteTools.insertContent(a);
|
|
2570
2594
|
break;
|
|
2571
2595
|
case 'append':
|
|
2572
|
-
result = noteTools.appendContent(a);
|
|
2596
|
+
result = await noteTools.appendContent(a);
|
|
2573
2597
|
break;
|
|
2574
2598
|
case 'delete_lines':
|
|
2575
|
-
result = noteTools.deleteLines(a);
|
|
2599
|
+
result = await noteTools.deleteLines(a);
|
|
2576
2600
|
break;
|
|
2577
2601
|
case 'edit_line':
|
|
2578
|
-
result = noteTools.editLine(a);
|
|
2602
|
+
result = await noteTools.editLine(a);
|
|
2579
2603
|
break;
|
|
2580
2604
|
case 'replace_lines':
|
|
2581
|
-
result = noteTools.replaceLines(a);
|
|
2605
|
+
result = await noteTools.replaceLines(a);
|
|
2582
2606
|
break;
|
|
2583
2607
|
default: throw new Error(`Unknown action: "${action}". Valid actions: insert, append, delete_lines, edit_line, replace_lines (snake_case required)`);
|
|
2584
2608
|
}
|
|
@@ -2601,25 +2625,25 @@ export function createServer() {
|
|
|
2601
2625
|
const action = a?.action;
|
|
2602
2626
|
switch (action) {
|
|
2603
2627
|
case 'get':
|
|
2604
|
-
result = noteTools.getParagraphs(a);
|
|
2628
|
+
result = await noteTools.getParagraphs(a);
|
|
2605
2629
|
break;
|
|
2606
2630
|
case 'search':
|
|
2607
|
-
result = noteTools.searchParagraphs(a);
|
|
2631
|
+
result = await noteTools.searchParagraphs(a);
|
|
2608
2632
|
break;
|
|
2609
2633
|
case 'search_global':
|
|
2610
|
-
result = noteTools.searchParagraphsGlobal(a);
|
|
2634
|
+
result = await noteTools.searchParagraphsGlobal(a);
|
|
2611
2635
|
break;
|
|
2612
2636
|
case 'add':
|
|
2613
|
-
result = taskTools.addTaskToNote(a);
|
|
2637
|
+
result = await taskTools.addTaskToNote(a);
|
|
2614
2638
|
break;
|
|
2615
2639
|
case 'complete':
|
|
2616
|
-
result = taskTools.completeTask(a);
|
|
2640
|
+
result = await taskTools.completeTask(a);
|
|
2617
2641
|
break;
|
|
2618
2642
|
case 'update':
|
|
2619
|
-
result = taskTools.updateTask(a);
|
|
2643
|
+
result = await taskTools.updateTask(a);
|
|
2620
2644
|
break;
|
|
2621
2645
|
case 'delete_recurring':
|
|
2622
|
-
result = taskTools.deleteRecurringTask(a);
|
|
2646
|
+
result = await taskTools.deleteRecurringTask(a);
|
|
2623
2647
|
break;
|
|
2624
2648
|
default: throw new Error(`Unknown action: ${action}`);
|
|
2625
2649
|
}
|
|
@@ -2634,28 +2658,28 @@ export function createServer() {
|
|
|
2634
2658
|
}
|
|
2635
2659
|
switch (action) {
|
|
2636
2660
|
case 'list':
|
|
2637
|
-
result = spaceTools.listFolders(args);
|
|
2661
|
+
result = await spaceTools.listFolders(args);
|
|
2638
2662
|
break;
|
|
2639
2663
|
case 'find':
|
|
2640
|
-
result = spaceTools.findFolders(args);
|
|
2664
|
+
result = await spaceTools.findFolders(args);
|
|
2641
2665
|
break;
|
|
2642
2666
|
case 'resolve':
|
|
2643
|
-
result = spaceTools.resolveFolder(args);
|
|
2667
|
+
result = await spaceTools.resolveFolder(args);
|
|
2644
2668
|
break;
|
|
2645
2669
|
case 'create':
|
|
2646
|
-
result = spaceTools.createFolder(args);
|
|
2670
|
+
result = await spaceTools.createFolder(args);
|
|
2647
2671
|
break;
|
|
2648
2672
|
case 'move':
|
|
2649
|
-
result = spaceTools.moveFolder(args);
|
|
2673
|
+
result = await spaceTools.moveFolder(args);
|
|
2650
2674
|
break;
|
|
2651
2675
|
case 'rename':
|
|
2652
|
-
result = spaceTools.renameFolder(args);
|
|
2676
|
+
result = await spaceTools.renameFolder(args);
|
|
2653
2677
|
break;
|
|
2654
2678
|
case 'delete':
|
|
2655
|
-
result = spaceTools.deleteFolder(args);
|
|
2679
|
+
result = await spaceTools.deleteFolder(args);
|
|
2656
2680
|
break;
|
|
2657
2681
|
case 'list_spaces':
|
|
2658
|
-
result = spaceTools.listSpaces(args);
|
|
2682
|
+
result = await spaceTools.listSpaces(args);
|
|
2659
2683
|
break;
|
|
2660
2684
|
default: throw new Error(`Unknown action: ${action}`);
|
|
2661
2685
|
}
|
|
@@ -2665,22 +2689,22 @@ export function createServer() {
|
|
|
2665
2689
|
const action = args?.action;
|
|
2666
2690
|
switch (action) {
|
|
2667
2691
|
case 'list':
|
|
2668
|
-
result = filterTools.listFilters(args);
|
|
2692
|
+
result = await filterTools.listFilters(args);
|
|
2669
2693
|
break;
|
|
2670
2694
|
case 'get':
|
|
2671
|
-
result = filterTools.getFilter(args);
|
|
2695
|
+
result = await filterTools.getFilter(args);
|
|
2672
2696
|
break;
|
|
2673
2697
|
case 'get_tasks':
|
|
2674
|
-
result = filterTools.getFilterTasks(args);
|
|
2698
|
+
result = await filterTools.getFilterTasks(args);
|
|
2675
2699
|
break;
|
|
2676
2700
|
case 'list_parameters':
|
|
2677
|
-
result = filterTools.listFilterParameters();
|
|
2701
|
+
result = await filterTools.listFilterParameters();
|
|
2678
2702
|
break;
|
|
2679
2703
|
case 'save':
|
|
2680
|
-
result = filterTools.saveFilter(args);
|
|
2704
|
+
result = await filterTools.saveFilter(args);
|
|
2681
2705
|
break;
|
|
2682
2706
|
case 'rename':
|
|
2683
|
-
result = filterTools.renameFilter(args);
|
|
2707
|
+
result = await filterTools.renameFilter(args);
|
|
2684
2708
|
break;
|
|
2685
2709
|
default: throw new Error(`Unknown action: ${action}`);
|
|
2686
2710
|
}
|
|
@@ -2764,7 +2788,7 @@ export function createServer() {
|
|
|
2764
2788
|
result = uiTools.openToday(args);
|
|
2765
2789
|
break;
|
|
2766
2790
|
case 'search':
|
|
2767
|
-
result = uiTools.searchNotes(args);
|
|
2791
|
+
result = await uiTools.searchNotes(args);
|
|
2768
2792
|
break;
|
|
2769
2793
|
case 'run_plugin':
|
|
2770
2794
|
result = uiTools.runPlugin(args);
|
|
@@ -2815,7 +2839,7 @@ export function createServer() {
|
|
|
2815
2839
|
result = uiTools.openToday(args);
|
|
2816
2840
|
break;
|
|
2817
2841
|
case 'search':
|
|
2818
|
-
result = uiTools.searchNotes(args);
|
|
2842
|
+
result = await uiTools.searchNotes(args);
|
|
2819
2843
|
break;
|
|
2820
2844
|
case 'run_plugin':
|
|
2821
2845
|
result = uiTools.runPlugin(args);
|
|
@@ -2943,16 +2967,16 @@ export function createServer() {
|
|
|
2943
2967
|
const action = args?.action;
|
|
2944
2968
|
switch (action) {
|
|
2945
2969
|
case 'add':
|
|
2946
|
-
result = attachmentTools.addAttachment(args);
|
|
2970
|
+
result = await attachmentTools.addAttachment(args);
|
|
2947
2971
|
break;
|
|
2948
2972
|
case 'list':
|
|
2949
|
-
result = attachmentTools.listAttachments(args);
|
|
2973
|
+
result = await attachmentTools.listAttachments(args);
|
|
2950
2974
|
break;
|
|
2951
2975
|
case 'get':
|
|
2952
|
-
result = attachmentTools.getAttachment(args);
|
|
2976
|
+
result = await attachmentTools.getAttachment(args);
|
|
2953
2977
|
break;
|
|
2954
2978
|
case 'move':
|
|
2955
|
-
result = attachmentTools.moveAttachment(args);
|
|
2979
|
+
result = await attachmentTools.moveAttachment(args);
|
|
2956
2980
|
break;
|
|
2957
2981
|
default: throw new Error(`Unknown action: ${action}. Valid actions: add, list, get, move`);
|
|
2958
2982
|
}
|
|
@@ -2965,15 +2989,16 @@ export function createServer() {
|
|
|
2965
2989
|
const resultWithSuggestions = withSuggestedNextTools(enrichedResult, normalizedName, registeredToolNameSet);
|
|
2966
2990
|
const resultWithMemory = withMemoryHints(resultWithSuggestions, normalizedName);
|
|
2967
2991
|
const resultWithDuration = withDuration(resultWithMemory, Date.now() - startTime, includeTiming);
|
|
2992
|
+
const finalResult = withBackend(resultWithDuration);
|
|
2968
2993
|
// Log non-throwing errors (success: false returned without an exception)
|
|
2969
|
-
if (
|
|
2994
|
+
if (finalResult && typeof finalResult === 'object' && finalResult.success === false) {
|
|
2970
2995
|
const duration = Date.now() - startTime;
|
|
2971
|
-
const errMsg =
|
|
2996
|
+
const errMsg = finalResult.error || 'unknown';
|
|
2972
2997
|
console.error(`[noteplan-mcp] Tool failed: ${actionLabel} (${duration}ms): ${errMsg}`);
|
|
2973
2998
|
}
|
|
2974
2999
|
const hasOutputSchema = Boolean(toolDefinitionByName.get(normalizedName)?.outputSchema);
|
|
2975
3000
|
// If the result contains image data, return it as an MCP image content block
|
|
2976
|
-
const typedResult =
|
|
3001
|
+
const typedResult = finalResult;
|
|
2977
3002
|
if (typedResult._imageData && typedResult._imageMimeType) {
|
|
2978
3003
|
const imageData = typedResult._imageData;
|
|
2979
3004
|
const imageMimeType = typedResult._imageMimeType;
|
|
@@ -2997,10 +3022,10 @@ export function createServer() {
|
|
|
2997
3022
|
content: [
|
|
2998
3023
|
{
|
|
2999
3024
|
type: 'text',
|
|
3000
|
-
text: JSON.stringify(
|
|
3025
|
+
text: JSON.stringify(finalResult),
|
|
3001
3026
|
},
|
|
3002
3027
|
],
|
|
3003
|
-
...(hasOutputSchema ? { structuredContent:
|
|
3028
|
+
...(hasOutputSchema ? { structuredContent: finalResult } : {}),
|
|
3004
3029
|
};
|
|
3005
3030
|
}
|
|
3006
3031
|
catch (error) {
|
|
@@ -3022,26 +3047,82 @@ export function createServer() {
|
|
|
3022
3047
|
retryable: meta.retryable,
|
|
3023
3048
|
};
|
|
3024
3049
|
const errorWithDuration = withDuration(errorResult, Date.now() - startTime, includeTiming);
|
|
3050
|
+
const finalErrorResult = withBackend(errorWithDuration);
|
|
3025
3051
|
const hasOutputSchema = Boolean(toolDefinitionByName.get(normalizedName)?.outputSchema);
|
|
3026
3052
|
return {
|
|
3027
3053
|
content: [
|
|
3028
3054
|
{
|
|
3029
3055
|
type: 'text',
|
|
3030
|
-
text: JSON.stringify(
|
|
3056
|
+
text: JSON.stringify(finalErrorResult),
|
|
3031
3057
|
},
|
|
3032
3058
|
],
|
|
3033
|
-
...(hasOutputSchema ? { structuredContent:
|
|
3059
|
+
...(hasOutputSchema ? { structuredContent: finalErrorResult } : {}),
|
|
3034
3060
|
isError: true,
|
|
3035
3061
|
};
|
|
3036
3062
|
}
|
|
3037
|
-
|
|
3063
|
+
finally {
|
|
3064
|
+
// Per-call backend summary so support reading the log linearly can tell
|
|
3065
|
+
// whether the call used the HTTP bridge or the SQLite/FS fallback. Mixed
|
|
3066
|
+
// calls (multiple bridge ops where one fell back) show "bridge+fallback".
|
|
3067
|
+
const backends = getCurrentBackends();
|
|
3068
|
+
if (backends.length > 0) {
|
|
3069
|
+
console.error(`[noteplan-mcp] ↳ backend: ${backends.join('+')}`);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
}));
|
|
3038
3073
|
return server;
|
|
3039
3074
|
}
|
|
3075
|
+
// Discover the bridge and run one cheap search call so NotePlan's
|
|
3076
|
+
// SearchHelper / NoteCache is hot before the first user request lands.
|
|
3077
|
+
// Bounded so a hung bridge can't wedge MCP startup. Errors are logged
|
|
3078
|
+
// but never fatal: if the bridge is unreachable, the cascade falls
|
|
3079
|
+
// through to ripgrep on the first request just like before.
|
|
3080
|
+
const BRIDGE_WARMUP_TIMEOUT_MS = 5_000;
|
|
3081
|
+
async function probeAndWarmBridge() {
|
|
3082
|
+
const deadline = Date.now() + BRIDGE_WARMUP_TIMEOUT_MS;
|
|
3083
|
+
const remaining = () => Math.max(0, deadline - Date.now());
|
|
3084
|
+
const withTimeout = (promise, label) => new Promise((resolve, reject) => {
|
|
3085
|
+
const timer = setTimeout(() => reject(new Error(`${label} timeout`)), remaining());
|
|
3086
|
+
promise.then((value) => {
|
|
3087
|
+
clearTimeout(timer);
|
|
3088
|
+
resolve(value);
|
|
3089
|
+
}, (err) => {
|
|
3090
|
+
clearTimeout(timer);
|
|
3091
|
+
reject(err);
|
|
3092
|
+
});
|
|
3093
|
+
});
|
|
3094
|
+
try {
|
|
3095
|
+
const client = await withTimeout(getBridgeClient(), 'bridge discover');
|
|
3096
|
+
if (!client) {
|
|
3097
|
+
console.error('[noteplan-mcp] Bridge unavailable (NotePlan not running, old build, or Automation denied)');
|
|
3098
|
+
return;
|
|
3099
|
+
}
|
|
3100
|
+
const config = await withTimeout(client.config(), 'bridge config');
|
|
3101
|
+
console.error(`[noteplan-mcp] Bridge OK on 127.0.0.1:${client.port} — storage: ${config.storagePath}`);
|
|
3102
|
+
try {
|
|
3103
|
+
await withTimeout(client.search('__np_mcp_warmup_no_match__', { limit: 1 }), 'bridge warmup');
|
|
3104
|
+
}
|
|
3105
|
+
catch (err) {
|
|
3106
|
+
// Warm-up is best-effort: a failure here means the first user
|
|
3107
|
+
// search may still take the cold path. Don't escalate — the
|
|
3108
|
+
// cascade in `searchWithRipgrep` already handles bridge errors.
|
|
3109
|
+
console.error(`[noteplan-mcp] Bridge warmup skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
catch (err) {
|
|
3113
|
+
console.error(`[noteplan-mcp] Bridge probe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3040
3116
|
// Start the server with stdio transport
|
|
3041
3117
|
export async function startServer() {
|
|
3042
3118
|
console.error(`[noteplan-mcp] Starting v${getMcpServerVersion()} (Node ${process.version}, ${process.platform} ${process.arch}, pid ${process.pid})`);
|
|
3043
3119
|
await initSqlite();
|
|
3044
3120
|
const server = createServer();
|
|
3121
|
+
// Bridge probe + SearchHelper / NoteCache warm-up. AWAIT this before
|
|
3122
|
+
// accepting requests so the user's first search hits the warm bridge
|
|
3123
|
+
// instead of racing it and falling back to ripgrep. Bounded by a
|
|
3124
|
+
// short overall timeout so a wedged bridge can't block startup.
|
|
3125
|
+
await probeAndWarmBridge();
|
|
3045
3126
|
const transport = new StdioServerTransport();
|
|
3046
3127
|
await server.connect(transport);
|
|
3047
3128
|
console.error('[noteplan-mcp] Server running on stdio');
|