virlow-mcp 3.11.7 → 3.11.8
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/dist/cli.js +30 -4
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -435,9 +435,7 @@ var NotesService = class {
|
|
|
435
435
|
const key = this.requireSession();
|
|
436
436
|
const row = await this.api.getNote(id);
|
|
437
437
|
const exposure = await this.exposure();
|
|
438
|
-
|
|
439
|
-
throw new Error(`Note ${id} is in a folder that is not exposed to MCP. Turn on "Expose to MCP" in that folder's settings in the Virlow app to read it here.`);
|
|
440
|
-
}
|
|
438
|
+
this.requireExposed(exposure, row.folderId, id);
|
|
441
439
|
const { title, content } = await this.decryptRow(key, row);
|
|
442
440
|
return { id: row.id, title, content, folderId: row.folderId };
|
|
443
441
|
}
|
|
@@ -464,6 +462,8 @@ var NotesService = class {
|
|
|
464
462
|
return this.enqueue(async () => {
|
|
465
463
|
const key = this.requireSession();
|
|
466
464
|
const existingRow = await this.api.getNote(id);
|
|
465
|
+
const exposure = await this.exposure();
|
|
466
|
+
this.requireExposed(exposure, existingRow.folderId, id);
|
|
467
467
|
const current = await this.decryptRow(key, existingRow);
|
|
468
468
|
const title = changes.title ?? current.title;
|
|
469
469
|
const content = changes.content ?? current.content;
|
|
@@ -482,6 +482,7 @@ var NotesService = class {
|
|
|
482
482
|
async searchNotes(query, limit = 20) {
|
|
483
483
|
const key = this.requireSession();
|
|
484
484
|
const q = query.toLowerCase();
|
|
485
|
+
const exposure = await this.exposure();
|
|
485
486
|
const results = [];
|
|
486
487
|
let scanned = 0;
|
|
487
488
|
let total = 0;
|
|
@@ -492,6 +493,8 @@ var NotesService = class {
|
|
|
492
493
|
for (const row of notes) {
|
|
493
494
|
if (row.hidden === true)
|
|
494
495
|
continue;
|
|
496
|
+
if (!exposure.allows(row.folderId))
|
|
497
|
+
continue;
|
|
495
498
|
if (scanned >= SEARCH_SCAN_CAP)
|
|
496
499
|
break scan;
|
|
497
500
|
scanned++;
|
|
@@ -512,18 +515,33 @@ var NotesService = class {
|
|
|
512
515
|
}
|
|
513
516
|
async moveNote(id, folderId) {
|
|
514
517
|
this.requireSession();
|
|
518
|
+
const existingRow = await this.api.getNote(id);
|
|
519
|
+
const exposure = await this.exposure();
|
|
520
|
+
this.requireExposed(exposure, existingRow.folderId, id);
|
|
521
|
+
if (folderId !== null) {
|
|
522
|
+
this.requireExposed(exposure, folderId, id);
|
|
523
|
+
}
|
|
515
524
|
await this.api.updateNote(id, { folderId });
|
|
516
525
|
}
|
|
517
526
|
async setStar(id, starred) {
|
|
518
527
|
this.requireSession();
|
|
528
|
+
const existingRow = await this.api.getNote(id);
|
|
529
|
+
const exposure = await this.exposure();
|
|
530
|
+
this.requireExposed(exposure, existingRow.folderId, id);
|
|
519
531
|
await this.api.updateNote(id, { starred });
|
|
520
532
|
}
|
|
521
533
|
async archiveNote(id, archived) {
|
|
522
534
|
this.requireSession();
|
|
535
|
+
const existingRow = await this.api.getNote(id);
|
|
536
|
+
const exposure = await this.exposure();
|
|
537
|
+
this.requireExposed(exposure, existingRow.folderId, id);
|
|
523
538
|
await this.api.updateNote(id, { archived });
|
|
524
539
|
}
|
|
525
540
|
async trashNote(id) {
|
|
526
541
|
this.requireSession();
|
|
542
|
+
const existingRow = await this.api.getNote(id);
|
|
543
|
+
const exposure = await this.exposure();
|
|
544
|
+
this.requireExposed(exposure, existingRow.folderId, id);
|
|
527
545
|
await this.api.updateNote(id, { deleted: true });
|
|
528
546
|
}
|
|
529
547
|
async listFolders() {
|
|
@@ -545,6 +563,14 @@ var NotesService = class {
|
|
|
545
563
|
const { folders } = await this.api.listFolders();
|
|
546
564
|
return computeExposure(folders);
|
|
547
565
|
}
|
|
566
|
+
/** Throws unless `folderId` is exposed to MCP. Every method that reads or
|
|
567
|
+
* mutates a specific note (by id) must call this — knowing a note's id is
|
|
568
|
+
* not consent to bypass the "Expose to MCP" folder switch. */
|
|
569
|
+
requireExposed(exposure, folderId, id) {
|
|
570
|
+
if (!exposure.allows(folderId)) {
|
|
571
|
+
throw new Error(`Note ${id} is in a folder that is not exposed to MCP. Turn on "Expose to MCP" in that folder's settings in the Virlow app to access it here.`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
548
574
|
async createFolder(name, parentId) {
|
|
549
575
|
this.requireSession();
|
|
550
576
|
const folder = await this.api.createFolder(name, parentId);
|
|
@@ -1535,7 +1561,7 @@ function startUnlockServer(api, vault, opts = {}) {
|
|
|
1535
1561
|
}
|
|
1536
1562
|
|
|
1537
1563
|
// src/version.ts
|
|
1538
|
-
var VERSION = true ? "3.11.
|
|
1564
|
+
var VERSION = true ? "3.11.8" : "dev";
|
|
1539
1565
|
|
|
1540
1566
|
// src/server.ts
|
|
1541
1567
|
function textResult(text) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "virlow-mcp",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.8",
|
|
4
4
|
"description": "Local MCP server for Virlow Secure Notes: end-to-end-encrypted AI memories and notes for Cursor, Claude, Codex, and any MCP client.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"esbuild": "^0.25.0",
|
|
35
35
|
"typescript": "^5.8.0",
|
|
36
36
|
"vitest": "^3.0.0",
|
|
37
|
-
"@batalabs/virlow-crypto": "3.11.
|
|
38
|
-
"@batalabs/virlow-memory": "3.11.
|
|
39
|
-
"@batalabs/virlow-mcp-core": "3.11.
|
|
37
|
+
"@batalabs/virlow-crypto": "3.11.8",
|
|
38
|
+
"@batalabs/virlow-memory": "3.11.8",
|
|
39
|
+
"@batalabs/virlow-mcp-core": "3.11.8"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "node build.mjs",
|