apple-notes-mcp 2.9.17 → 2.9.19
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 +14 -2
- package/build/index.js +90 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1355,7 +1355,7 @@ Lists all folders in an account with full hierarchical paths.
|
|
|
1355
1355
|
{}
|
|
1356
1356
|
```
|
|
1357
1357
|
|
|
1358
|
-
**Returns:** List of folders with IDs, paths, account names, and shared state, plus `identifier`, `parentIdentifier`, and `accountIdentifier` when Full Disk Access is granted. Nested folders are shown as full paths (e.g., `Work/Clients/Omnia`). Duplicate folder names are disambiguated by their full path. Literal slashes in folder names are escaped as `\/` (e.g., `Spain\/Portugal 2023`).
|
|
1358
|
+
**Returns:** List of folders with IDs, paths, account names, and shared state, plus `identifier`, `parentIdentifier`, and `accountIdentifier` when Full Disk Access is granted. Nested folders are shown as full paths (e.g., `Work/Clients/Omnia`). Duplicate folder names are disambiguated by their full path. Literal slashes in folder names are escaped as `\/` (e.g., `Spain\/Portugal 2023`). Smart folders are listed too, because Notes' AppleScript lists them like ordinary folders; with Full Disk Access they carry `smartFolder: true` (and `(smart folder)` in the text list). A smart folder cannot hold notes or folders.
|
|
1359
1359
|
|
|
1360
1360
|
---
|
|
1361
1361
|
|
|
@@ -2016,7 +2016,8 @@ Each take gets a deadline of 1.5 times its length plus a minute (at most 30 minu
|
|
|
2016
2016
|
Adds one nonempty local file of at most 64 MiB to an exact note using `id`, the
|
|
2017
2017
|
latest `expectedContentHash`, and an absolute `path`. The server never retries
|
|
2018
2018
|
the insertion. It verifies that existing rich content survived and compares the
|
|
2019
|
-
|
|
2019
|
+
size and streamed SHA-256 of Notes' saved copy with the source before reporting
|
|
2020
|
+
success, with no read cap below the 64 MiB write limit.
|
|
2020
2021
|
|
|
2021
2022
|
| Parameter | Type | Required | Description |
|
|
2022
2023
|
|-----------|------|----------|-------------|
|
|
@@ -2353,6 +2354,17 @@ distinctive existing `scopeText` so the Shortcut and server can independently
|
|
|
2353
2354
|
resolve the same note. Creating a note from Markdown is
|
|
2354
2355
|
[`create-note`](#create-note) with `format: "markdown"`.
|
|
2355
2356
|
|
|
2357
|
+
When the Shortcut refuses a request (its Find Notes step did not return
|
|
2358
|
+
exactly one note with that exact title and `scopeText`) or stops with its own
|
|
2359
|
+
action error, and the note reads back unchanged, the tool reports the
|
|
2360
|
+
Shortcut's reason with `code: "operation_failed"`, `committed: false` and
|
|
2361
|
+
`indeterminate: false`: nothing was written, so a retry is safe once the cause
|
|
2362
|
+
is fixed. Notes search can lag behind a note created or edited moments ago, so
|
|
2363
|
+
a refusal on a brand-new note may clear after a minute. A timeout, or a failed
|
|
2364
|
+
readback on a note that did change, is still reported as indeterminate.
|
|
2365
|
+
If the Shortcut is not installed, the error is `code: "shortcut_not_installed"`
|
|
2366
|
+
with `committed: false`.
|
|
2367
|
+
|
|
2356
2368
|
#### `get-capabilities`
|
|
2357
2369
|
|
|
2358
2370
|
Reports which background operations are implemented, live-verified, installed,
|
package/build/index.js
CHANGED
|
@@ -42435,7 +42435,7 @@ function readSmartFolderIds(read = readSmartFolders) {
|
|
|
42435
42435
|
}
|
|
42436
42436
|
function smartFolderDestinationError(folderPath) {
|
|
42437
42437
|
return new CodedError(
|
|
42438
|
-
`Refused: "${folderPath}" is a smart folder. Smart folders only gather notes by their rules and cannot hold notes or folders; choose an ordinary folder (list-folders). Nothing was changed`,
|
|
42438
|
+
`Refused: "${folderPath}" is a smart folder. Smart folders only gather notes by their rules and cannot hold notes or folders; choose an ordinary folder (list-folders marks smart folders smartFolder: true). Nothing was changed`,
|
|
42439
42439
|
{
|
|
42440
42440
|
code: "unsupported",
|
|
42441
42441
|
committed: false,
|
|
@@ -43881,6 +43881,9 @@ var AppleNotesManager = class {
|
|
|
43881
43881
|
/**
|
|
43882
43882
|
* Lists all folders in an account with full hierarchical paths.
|
|
43883
43883
|
*
|
|
43884
|
+
* Smart folders are included (AppleScript lists them like ordinary folders)
|
|
43885
|
+
* and carry `smartFolder: true` when the NoteStore database is readable.
|
|
43886
|
+
*
|
|
43884
43887
|
* Each folder's `name` field contains the full path (e.g., "Work/Clients/Omnia")
|
|
43885
43888
|
* so that duplicate folder names (e.g., multiple "Archive" folders) are
|
|
43886
43889
|
* distinguishable and can be used directly in other operations.
|
|
@@ -43939,11 +43942,13 @@ var AppleNotesManager = class {
|
|
|
43939
43942
|
}
|
|
43940
43943
|
return safeName;
|
|
43941
43944
|
};
|
|
43945
|
+
const smart = new Set(entries2.some((entry) => entry.id) ? this.smartFolderIds() : []);
|
|
43942
43946
|
return entries2.map((entry) => ({
|
|
43943
43947
|
id: entry.id,
|
|
43944
43948
|
name: buildPath(entry),
|
|
43945
43949
|
account: entry.account || targetAccount || "",
|
|
43946
|
-
shared: entry.shared
|
|
43950
|
+
shared: entry.shared,
|
|
43951
|
+
...smart.has(entry.id) ? { smartFolder: true } : {}
|
|
43947
43952
|
}));
|
|
43948
43953
|
}
|
|
43949
43954
|
/**
|
|
@@ -48265,6 +48270,7 @@ function comparableVisibleText(html) {
|
|
|
48265
48270
|
}
|
|
48266
48271
|
|
|
48267
48272
|
// src/services/backgroundNotes.ts
|
|
48273
|
+
var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
48268
48274
|
var BACKGROUND_SHORTCUT = "Apple Notes MCP - Background Operations v5";
|
|
48269
48275
|
var backgroundShortcutName = () => process.env.APPLE_NOTES_MCP_BACKGROUND_SHORTCUT || BACKGROUND_SHORTCUT;
|
|
48270
48276
|
var backgroundStatus = () => nativeTagsStatus(backgroundShortcutName());
|
|
@@ -48375,10 +48381,14 @@ function validateAppendContent(content, format, options = {}) {
|
|
|
48375
48381
|
);
|
|
48376
48382
|
}
|
|
48377
48383
|
}
|
|
48384
|
+
var BRIDGE_REFUSED = "refused the request without running it: its Find Notes step did not find exactly one note with this exact title whose body contains the scope text. Notes search can lag behind a note created or edited moments ago, so wait a minute and retry, or pass a longer, more distinctive scopeText";
|
|
48378
48385
|
function runBackgroundShortcut(input, status = backgroundStatus()) {
|
|
48379
48386
|
if (!status.installed)
|
|
48380
|
-
throw
|
|
48381
|
-
|
|
48387
|
+
throw Object.assign(
|
|
48388
|
+
new Error(
|
|
48389
|
+
`Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
|
|
48390
|
+
),
|
|
48391
|
+
{ shortcut: status.shortcut, notInstalled: true }
|
|
48382
48392
|
);
|
|
48383
48393
|
const directory = mkdtempSync4(join17(tmpdir4(), "apple-notes-background-"));
|
|
48384
48394
|
try {
|
|
@@ -48401,16 +48411,31 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
|
|
|
48401
48411
|
}),
|
|
48402
48412
|
{ mode: 384 }
|
|
48403
48413
|
);
|
|
48414
|
+
let output;
|
|
48404
48415
|
try {
|
|
48405
|
-
execFileSync16(
|
|
48406
|
-
|
|
48407
|
-
|
|
48408
|
-
|
|
48409
|
-
|
|
48410
|
-
|
|
48416
|
+
output = execFileSync16(
|
|
48417
|
+
"/usr/bin/shortcuts",
|
|
48418
|
+
["run", status.identifier, "--input-path", file],
|
|
48419
|
+
{
|
|
48420
|
+
encoding: "utf8",
|
|
48421
|
+
timeout: callTimeoutMs() ?? 6e4,
|
|
48422
|
+
maxBuffer: 1024 * 1024,
|
|
48423
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
48424
|
+
}
|
|
48425
|
+
);
|
|
48411
48426
|
} catch (error2) {
|
|
48412
48427
|
throw Object.assign(error2, { shortcut: status.shortcut });
|
|
48413
48428
|
}
|
|
48429
|
+
if (/_REFUSED\b/.test(String(output ?? "")))
|
|
48430
|
+
throw Object.assign(
|
|
48431
|
+
new Error(
|
|
48432
|
+
status.shortcut === markdownShortcutName() ? "refused the request without running it" : BRIDGE_REFUSED
|
|
48433
|
+
),
|
|
48434
|
+
{
|
|
48435
|
+
shortcut: status.shortcut,
|
|
48436
|
+
refused: true
|
|
48437
|
+
}
|
|
48438
|
+
);
|
|
48414
48439
|
} finally {
|
|
48415
48440
|
rmSync4(directory, { recursive: true, force: true });
|
|
48416
48441
|
}
|
|
@@ -48480,6 +48505,7 @@ function assertPreserved(before, after, options = {}) {
|
|
|
48480
48505
|
function describeTransportFailure(error2) {
|
|
48481
48506
|
const detail = error2;
|
|
48482
48507
|
const named = detail?.shortcut ? `the "${detail.shortcut}" Shortcut` : "the background Shortcut";
|
|
48508
|
+
if (detail?.refused) return `${named} ${detail.message}`;
|
|
48483
48509
|
return detail?.code === "ETIMEDOUT" ? `Shortcuts timed out waiting for ${named}. ${shortcutConsentHint(detail.shortcut)}` : `${named} failed: ${String(detail?.stderr || detail?.message || "no output").trim().slice(0, 400)}`;
|
|
48484
48510
|
}
|
|
48485
48511
|
function mutateBackground(request, operation, data, verify, deps) {
|
|
@@ -48497,16 +48523,30 @@ function mutateBackground(request, operation, data, verify, deps) {
|
|
|
48497
48523
|
throw new Error("Note revision changed during preflight");
|
|
48498
48524
|
let transportUncertain = false;
|
|
48499
48525
|
let transportMessage = "";
|
|
48526
|
+
let transportError;
|
|
48500
48527
|
try {
|
|
48501
48528
|
deps.run({ ...data, operation, title: before.title, scopeText: request.scopeText });
|
|
48502
48529
|
} catch (error2) {
|
|
48503
48530
|
transportUncertain = true;
|
|
48531
|
+
transportError = error2 ?? {};
|
|
48504
48532
|
transportMessage = describeTransportFailure(error2);
|
|
48505
48533
|
}
|
|
48506
48534
|
const after = deps.read(request.id);
|
|
48507
48535
|
try {
|
|
48508
48536
|
verify(before, after);
|
|
48509
48537
|
} catch (error2) {
|
|
48538
|
+
const unchanged = after.hash === before.hash && after.pinned === before.pinned;
|
|
48539
|
+
if (transportError?.notInstalled && unchanged)
|
|
48540
|
+
throw new CodedError(
|
|
48541
|
+
`${transportError.message}. The Shortcut never ran, so nothing was written; run apple-notes-mcp setup, then retry.`,
|
|
48542
|
+
{ code: "shortcut_not_installed", committed: false, indeterminate: false }
|
|
48543
|
+
);
|
|
48544
|
+
const exitedWithError = typeof transportError?.status === "number" && transportError.status !== 0 && !transportError.signal && transportError.code !== "ETIMEDOUT";
|
|
48545
|
+
if (transportError && (transportError.refused || exitedWithError) && unchanged)
|
|
48546
|
+
throw new CodedError(
|
|
48547
|
+
`${capitalize(transportMessage)}. The note is unchanged, so nothing was written; it is safe to retry once the cause is fixed.`,
|
|
48548
|
+
{ code: "operation_failed", committed: false, indeterminate: false }
|
|
48549
|
+
);
|
|
48510
48550
|
throw new Error(
|
|
48511
48551
|
`Operation outcome uncertain; read exact note before any retry: ${error2 instanceof Error ? error2.message : "readback failed"}${transportMessage ? "; " + transportMessage : ""}`
|
|
48512
48552
|
);
|
|
@@ -53063,6 +53103,7 @@ import {
|
|
|
53063
53103
|
mkdtempSync as mkdtempSync6,
|
|
53064
53104
|
openSync as openSync7,
|
|
53065
53105
|
readFileSync as readFileSync4,
|
|
53106
|
+
readSync as readSync5,
|
|
53066
53107
|
rmSync as rmSync6,
|
|
53067
53108
|
writeFileSync as writeFileSync5
|
|
53068
53109
|
} from "node:fs";
|
|
@@ -53344,7 +53385,7 @@ function localAttachment(path10) {
|
|
|
53344
53385
|
const descriptor = openSync7(path10, constants7.O_RDONLY | constants7.O_NOFOLLOW);
|
|
53345
53386
|
try {
|
|
53346
53387
|
const stat = fstatSync7(descriptor);
|
|
53347
|
-
if (!stat.isFile() || stat.size === 0 || stat.size >
|
|
53388
|
+
if (!stat.isFile() || stat.size === 0 || stat.size > MAX_ADD_ATTACHMENT_BYTES)
|
|
53348
53389
|
throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
|
|
53349
53390
|
const bytes = readFileSync4(descriptor);
|
|
53350
53391
|
if (bytes.length !== stat.size)
|
|
@@ -53354,6 +53395,30 @@ function localAttachment(path10) {
|
|
|
53354
53395
|
closeSync7(descriptor);
|
|
53355
53396
|
}
|
|
53356
53397
|
}
|
|
53398
|
+
var MAX_ADD_ATTACHMENT_BYTES = 64 * 1024 * 1024;
|
|
53399
|
+
function fileMatches(path10, size, expected) {
|
|
53400
|
+
let descriptor;
|
|
53401
|
+
try {
|
|
53402
|
+
descriptor = openSync7(path10, constants7.O_RDONLY | constants7.O_NOFOLLOW);
|
|
53403
|
+
const stat = fstatSync7(descriptor);
|
|
53404
|
+
if (!stat.isFile() || stat.size !== size) return false;
|
|
53405
|
+
const hash = createHash3("sha256");
|
|
53406
|
+
const chunk = Buffer.allocUnsafe(1024 * 1024);
|
|
53407
|
+
let total = 0;
|
|
53408
|
+
for (; ; ) {
|
|
53409
|
+
const read = readSync5(descriptor, chunk, 0, chunk.length, null);
|
|
53410
|
+
if (read === 0) break;
|
|
53411
|
+
total += read;
|
|
53412
|
+
if (total > size) return false;
|
|
53413
|
+
hash.update(chunk.subarray(0, read));
|
|
53414
|
+
}
|
|
53415
|
+
return total === size && hash.digest("hex") === expected;
|
|
53416
|
+
} catch {
|
|
53417
|
+
return false;
|
|
53418
|
+
} finally {
|
|
53419
|
+
if (descriptor !== void 0) closeSync7(descriptor);
|
|
53420
|
+
}
|
|
53421
|
+
}
|
|
53357
53422
|
function registerDirectOperations(server2, manager) {
|
|
53358
53423
|
function tool(name, description, inputSchema, handler, readOnly = false) {
|
|
53359
53424
|
server2.registerTool(
|
|
@@ -53560,18 +53625,7 @@ function storedInsertion(manager, id2, before, bytes, returnedId) {
|
|
|
53560
53625
|
if (returnedId && /\/ICAttachment\/p\d+$/.test(returnedId) && returnedId !== attachmentId)
|
|
53561
53626
|
throw new Error(UNCERTAIN);
|
|
53562
53627
|
const expected = sha256(bytes);
|
|
53563
|
-
const matches = row.assetPaths.some((path10) =>
|
|
53564
|
-
let descriptor;
|
|
53565
|
-
try {
|
|
53566
|
-
descriptor = openSync7(path10, constants7.O_RDONLY | constants7.O_NOFOLLOW);
|
|
53567
|
-
const stat = fstatSync7(descriptor);
|
|
53568
|
-
return stat.isFile() && stat.size === bytes.length && sha256(readFileSync4(descriptor)) === expected;
|
|
53569
|
-
} catch {
|
|
53570
|
-
return false;
|
|
53571
|
-
} finally {
|
|
53572
|
-
if (descriptor !== void 0) closeSync7(descriptor);
|
|
53573
|
-
}
|
|
53574
|
-
});
|
|
53628
|
+
const matches = row.assetPaths.some((path10) => fileMatches(path10, bytes.length, expected));
|
|
53575
53629
|
if (!matches)
|
|
53576
53630
|
throw new Error(
|
|
53577
53631
|
`Notes' database shows new attachment ${attachmentId} on this note, but its file bytes could not be verified; read the exact note and do not attach the file again`
|
|
@@ -53615,9 +53669,9 @@ function attachFile(manager, args, checked) {
|
|
|
53615
53669
|
if (inserted.length === 1 && !(persistentReturnedId && returnedId !== inserted[0].id)) {
|
|
53616
53670
|
attachmentId = inserted[0].id;
|
|
53617
53671
|
reportedName = inserted[0].name;
|
|
53618
|
-
const
|
|
53619
|
-
const
|
|
53620
|
-
if (!
|
|
53672
|
+
const verifyPath = join24(directory, "verify", "attachment.bin");
|
|
53673
|
+
const saved = manager.saveAttachmentById(id2, attachmentId, verifyPath);
|
|
53674
|
+
if (!saved.success || !fileMatches(saved.savedPath ?? verifyPath, bytes.length, sha256(bytes)))
|
|
53621
53675
|
throw new Error("Attachment bytes were not verified; read the exact note before retrying");
|
|
53622
53676
|
} else {
|
|
53623
53677
|
const stored = inserted.length === 0 && beforeStored ? storedInsertion(manager, id2, beforeStored, bytes, returnedId) : null;
|
|
@@ -53987,7 +54041,7 @@ import {
|
|
|
53987
54041
|
mkdirSync as mkdirSync7,
|
|
53988
54042
|
openSync as openSync8,
|
|
53989
54043
|
readdirSync as readdirSync4,
|
|
53990
|
-
readSync as
|
|
54044
|
+
readSync as readSync6,
|
|
53991
54045
|
renameSync,
|
|
53992
54046
|
unlinkSync as unlinkSync3,
|
|
53993
54047
|
writeSync as writeSync5
|
|
@@ -54078,7 +54132,7 @@ var TemplateStore = class {
|
|
|
54078
54132
|
const data = Buffer.alloc(stat.size);
|
|
54079
54133
|
let read = 0;
|
|
54080
54134
|
while (read < stat.size) {
|
|
54081
|
-
const n =
|
|
54135
|
+
const n = readSync6(fd, data, read, stat.size - read, read);
|
|
54082
54136
|
if (n <= 0) break;
|
|
54083
54137
|
read += n;
|
|
54084
54138
|
}
|
|
@@ -54395,7 +54449,7 @@ function registerMarkdownTemplates(server2, store = () => new TemplateStore()) {
|
|
|
54395
54449
|
|
|
54396
54450
|
// src/utils/svgAnalyzer.ts
|
|
54397
54451
|
import { createHash as createHash5 } from "node:crypto";
|
|
54398
|
-
import { closeSync as closeSync9, constants as constants9, fstatSync as fstatSync9, openSync as openSync9, readSync as
|
|
54452
|
+
import { closeSync as closeSync9, constants as constants9, fstatSync as fstatSync9, openSync as openSync9, readSync as readSync7 } from "node:fs";
|
|
54399
54453
|
|
|
54400
54454
|
// src/utils/svgColor.ts
|
|
54401
54455
|
var NAMED = {
|
|
@@ -56382,7 +56436,7 @@ function readSvgSource(path10) {
|
|
|
56382
56436
|
const buffer = Buffer.alloc(SVG_LIMITS.maxSourceBytes + 1);
|
|
56383
56437
|
let total = 0;
|
|
56384
56438
|
for (; ; ) {
|
|
56385
|
-
const n =
|
|
56439
|
+
const n = readSync7(fd, buffer, total, buffer.length - total, null);
|
|
56386
56440
|
if (n === 0) break;
|
|
56387
56441
|
total += n;
|
|
56388
56442
|
if (total > SVG_LIMITS.maxSourceBytes)
|
|
@@ -56633,7 +56687,9 @@ function appendChecklistItems(args, deps, readRich) {
|
|
|
56633
56687
|
stoppedAt: {
|
|
56634
56688
|
index,
|
|
56635
56689
|
text: text2,
|
|
56636
|
-
|
|
56690
|
+
// A bridge refusal or failure with an unchanged readback is
|
|
56691
|
+
// reported as not written even though verification ran (#248).
|
|
56692
|
+
outcome: wrote && !(error2 instanceof CodedError && error2.envelope.committed === false) ? "uncertain" : "not-written",
|
|
56637
56693
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
56638
56694
|
},
|
|
56639
56695
|
notAttempted: args.items.slice(index + 1),
|
|
@@ -60581,7 +60637,7 @@ ${noteList}`, {
|
|
|
60581
60637
|
registerTool(
|
|
60582
60638
|
"list-folders",
|
|
60583
60639
|
{
|
|
60584
|
-
description: "Use when: listing all folders, with full nested paths, for an account.\nReturns: folder names/paths.\nDo not use when: listing notes (list-notes).\nNote:
|
|
60640
|
+
description: "Use when: listing all folders, with full nested paths, for an account.\nReturns: folder names/paths.\nDo not use when: listing notes (list-notes).\nNote: smart folders are listed too (AppleScript lists them like ordinary folders) and are marked smartFolder: true when Full Disk Access lets the server read the Notes database; they cannot hold notes. Warns if iCloud sync is active.",
|
|
60585
60641
|
inputSchema: {
|
|
60586
60642
|
account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account to list folders from")
|
|
60587
60643
|
},
|
|
@@ -60611,7 +60667,7 @@ ${syncWarnings.join(" ")}` : "";
|
|
|
60611
60667
|
return successResponse(`No folders found${acct}${syncNote}`, { folders: [], count: 0 });
|
|
60612
60668
|
}
|
|
60613
60669
|
const resolvedAcct = folders[0]?.account ? ` (${folders[0].account})` : acct;
|
|
60614
|
-
const folderList = folders.map((f) => ` - ${f.name}`).join("\n");
|
|
60670
|
+
const folderList = folders.map((f) => ` - ${f.name}${f.smartFolder ? " (smart folder)" : ""}`).join("\n");
|
|
60615
60671
|
return successResponse(
|
|
60616
60672
|
`Found ${folders.length} folders${resolvedAcct}:
|
|
60617
60673
|
${folderList}${syncNote}`,
|
|
@@ -60627,7 +60683,7 @@ registerTool(
|
|
|
60627
60683
|
{
|
|
60628
60684
|
description: `Use when: listing Smart Folders and the rules that define them.
|
|
60629
60685
|
Returns: each smart folder's name, ids, account, and parent, its rules decoded as match ("all"/"any"/"none") plus filters (each with a readable description), the stored query with the outer deleted wrapper removed, and the raw stored query JSON. With includeMatchingNotes, also the notes Notes.app currently shows in each folder.
|
|
60630
|
-
Do not use when: listing
|
|
60686
|
+
Do not use when: listing all folders with paths (list-folders, which lists smart folders alongside ordinary ones) or searching notes (search-notes).
|
|
60631
60687
|
Safety: read-only; reads the NoteStore database and requires Full Disk Access. includeMatchingNotes asks Notes.app (Automation permission) for each folder's current contents rather than re-evaluating the rules. Unrecognized rules are kept as "unknown" filters and set fullyDecoded false.`,
|
|
60632
60688
|
inputSchema: {
|
|
60633
60689
|
includeMatchingNotes: external_exports.boolean().optional().describe(
|
package/package.json
CHANGED