apple-notes-mcp 2.8.43 → 2.8.45
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 +87 -5
- package/build/index.js +754 -140
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -763,6 +763,7 @@ Updates an existing note's content and/or title.
|
|
|
763
763
|
| `newContent` | string | Yes | New content for the note body |
|
|
764
764
|
| `format` | string | No | Content format: `"plaintext"` (default) or `"html"`. When `"html"`, content replaces the entire note body as raw HTML and `newTitle` is ignored (the first HTML element serves as the title) |
|
|
765
765
|
| `allowLinkChanges` | boolean | No | Set to `true` only when intentionally changing or removing existing links |
|
|
766
|
+
| `ifFolderId`, `ifAncestorFolderId`, `forbiddenAncestorFolderIds` | string, string, string[] | No | Folder preconditions; see [Folder scope guards](#folder-scope-guards) |
|
|
766
767
|
|
|
767
768
|
Title-only updates are rejected because Apple Notes titles are not unique.
|
|
768
769
|
|
|
@@ -807,6 +808,7 @@ Deletes a note (moves to Recently Deleted in Notes.app).
|
|
|
807
808
|
|-----------|------|----------|-------------|
|
|
808
809
|
| `id` | string | Yes | Exact CoreData note ID returned by a read or search |
|
|
809
810
|
| `expectedContentHash` | string | Yes | `contentHash` from the exact note version being deleted |
|
|
811
|
+
| `ifFolderId`, `ifAncestorFolderId`, `forbiddenAncestorFolderIds` | string, string, string[] | No | Folder preconditions; see [Folder scope guards](#folder-scope-guards) |
|
|
810
812
|
|
|
811
813
|
Title-only deletion is rejected. If the note changed after the supplied hash
|
|
812
814
|
was read, deletion is also rejected.
|
|
@@ -842,6 +844,7 @@ Moves a note to a different folder. The note is relocated in place via Notes.app
|
|
|
842
844
|
|-----------|------|----------|-------------|
|
|
843
845
|
| `id` | string | Yes | Exact CoreData note ID returned by a read or search |
|
|
844
846
|
| `folder` | string | Yes | Destination folder name or nested path (e.g., `"Work/Clients"`) |
|
|
847
|
+
| `ifFolderId`, `ifAncestorFolderId`, `forbiddenAncestorFolderIds` | string, string, string[] | No | Folder preconditions; see [Folder scope guards](#folder-scope-guards) |
|
|
845
848
|
|
|
846
849
|
Title-only moves are rejected.
|
|
847
850
|
|
|
@@ -858,6 +861,35 @@ actual destination folder ID matches the requested folder.
|
|
|
858
861
|
|
|
859
862
|
---
|
|
860
863
|
|
|
864
|
+
#### Folder scope guards
|
|
865
|
+
|
|
866
|
+
`update-note`, `append-to-note`, `delete-note`, and `move-note` accept three
|
|
867
|
+
optional folder preconditions. Use exact folder ids from `list-folders`.
|
|
868
|
+
|
|
869
|
+
- `ifFolderId`: the note must currently be in exactly this folder.
|
|
870
|
+
- `ifAncestorFolderId`: the note must be inside this folder or any of its
|
|
871
|
+
subfolders.
|
|
872
|
+
- `forbiddenAncestorFolderIds` (up to 50): the note must not be inside any of
|
|
873
|
+
these folders or their subfolders. For `move-note`, the destination must not
|
|
874
|
+
be either.
|
|
875
|
+
|
|
876
|
+
The checks read Notes.app's live folders inside the same AppleScript as the
|
|
877
|
+
write, immediately before it, so a note moved after you reviewed it is left
|
|
878
|
+
alone and the call fails with `Scope guard failed: …`. The one exception is a
|
|
879
|
+
native append to a protected note (it runs through Shortcuts): there the check
|
|
880
|
+
is a separate read just before the append, so it is not atomic.
|
|
881
|
+
|
|
882
|
+
**Example - retire a note only while it is still in the inbox:**
|
|
883
|
+
```json
|
|
884
|
+
{
|
|
885
|
+
"id": "x-coredata://ABC123/ICNote/p456",
|
|
886
|
+
"expectedContentHash": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
887
|
+
"ifFolderId": "x-coredata://ABC123/ICFolder/p12"
|
|
888
|
+
}
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
861
893
|
#### `append-to-note`
|
|
862
894
|
|
|
863
895
|
Appends or prepends content to an existing note without replacing it. Always reads and writes as HTML, preserving all existing rich formatting.
|
|
@@ -870,6 +902,7 @@ Appends or prepends content to an existing note without replacing it. Always rea
|
|
|
870
902
|
| `position` | string | No | `"after"` (default) appends to the end; `"before"` inserts directly below the note's title line, so the title stays first |
|
|
871
903
|
| `separator` | string | No | String placed between existing content and new content (default: two newlines → `<div><br></div>` in HTML) |
|
|
872
904
|
| `format` | string | No | Format of the content being appended: `"plaintext"` (default) or `"html"` |
|
|
905
|
+
| `ifFolderId`, `ifAncestorFolderId`, `forbiddenAncestorFolderIds` | string, string, string[] | No | Folder preconditions; see [Folder scope guards](#folder-scope-guards) |
|
|
873
906
|
|
|
874
907
|
Title-only appends are rejected.
|
|
875
908
|
|
|
@@ -1145,11 +1178,12 @@ Creates a new folder, including a whole nested hierarchy in one call.
|
|
|
1145
1178
|
|
|
1146
1179
|
#### `get-folder-by-id`
|
|
1147
1180
|
|
|
1148
|
-
Reads one exact folder's current name
|
|
1149
|
-
`
|
|
1150
|
-
`
|
|
1151
|
-
|
|
1152
|
-
|
|
1181
|
+
Reads one exact folder's current name, parent ID, and account ID (`accountId`,
|
|
1182
|
+
plus `isRoot`, true when the folder sits at the account root). Use these values
|
|
1183
|
+
with `rename-folder` or `delete-folder-by-id`; this avoids relying on ambiguous
|
|
1184
|
+
folder names or paths. The `id` may also be the folder's Notes UUID or numeric
|
|
1185
|
+
key, and the result adds `identifier`, `parentIdentifier`, and
|
|
1186
|
+
`accountIdentifier` when Full Disk Access is granted.
|
|
1153
1187
|
|
|
1154
1188
|
---
|
|
1155
1189
|
|
|
@@ -1161,6 +1195,54 @@ and descendants. It refuses stale metadata and a conflicting sibling name.
|
|
|
1161
1195
|
|
|
1162
1196
|
---
|
|
1163
1197
|
|
|
1198
|
+
#### `delete-folder-by-id`
|
|
1199
|
+
|
|
1200
|
+
Deletes one exact, empty, ordinary folder through a plan-then-apply handshake.
|
|
1201
|
+
Read the folder first with `get-folder-by-id`, call once with `dryRun: true`,
|
|
1202
|
+
then repeat the same guards with `dryRun: false` and the returned `revision`.
|
|
1203
|
+
|
|
1204
|
+
| Parameter | Type | Required | Description |
|
|
1205
|
+
|-----------|------|----------|-------------|
|
|
1206
|
+
| `id` | string | Yes | Exact folder id (`x-coredata://…/ICFolder/pN`), or the folder's Notes UUID or numeric key |
|
|
1207
|
+
| `expectedName` | string | Yes | Current folder name (not a path), matched case-sensitively |
|
|
1208
|
+
| `expectedAccountId` | string | Yes | Owning account id (`x-coredata://…/ICAccount/pN`) |
|
|
1209
|
+
| `expectedParentId` | string | One of these two | Current parent folder id (same forms as `id`) |
|
|
1210
|
+
| `expectedRoot` | `true` | One of these two | The folder sits at the account root |
|
|
1211
|
+
| `dryRun` | boolean | Yes | `true` plans; `false` applies |
|
|
1212
|
+
| `expectedRevision` | string | On apply | The `revision` from the dry run |
|
|
1213
|
+
|
|
1214
|
+
**Example (plan, then apply with the returned revision):**
|
|
1215
|
+
```json
|
|
1216
|
+
{
|
|
1217
|
+
"id": "x-coredata://ABC/ICFolder/p42",
|
|
1218
|
+
"expectedName": "Old Projects",
|
|
1219
|
+
"expectedAccountId": "x-coredata://ABC/ICAccount/p3",
|
|
1220
|
+
"expectedRoot": true,
|
|
1221
|
+
"dryRun": true
|
|
1222
|
+
}
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
**Returns:** `status: "planned"` with `wouldDelete`, `identifier`, `name`,
|
|
1226
|
+
`accountId`, `parentId`, `folderType: 0`, zero `childFolderCount` and
|
|
1227
|
+
`noteCount`, and `revision`; on apply, `status: "deleted"`, `committed: true`,
|
|
1228
|
+
`verified: true` (Notes.app no longer resolves the id), and `storeTombstoned`.
|
|
1229
|
+
|
|
1230
|
+
**Safety:** it always refuses Recently Deleted, smart folders, the account's
|
|
1231
|
+
default and other system folders, shared folders (or folders inside a shared
|
|
1232
|
+
folder), and any folder that still holds notes or subfolders. There is no
|
|
1233
|
+
override. It is **not atomic**: the guard is a pre-check followed by an
|
|
1234
|
+
AppleScript delete. The name, parent, account, sharing, and emptiness checks
|
|
1235
|
+
repeat inside the delete script, but the folder type and stable identifier come
|
|
1236
|
+
from the local Notes database just before it. It needs Full Disk Access and
|
|
1237
|
+
fails closed without it.
|
|
1238
|
+
|
|
1239
|
+
**Errors** carry the standard `code`: `revision_conflict` (a `Conflict:` message;
|
|
1240
|
+
read and plan again), `unsupported` (a `Refused:` message), `verification_failed`
|
|
1241
|
+
with `indeterminate: true` (read the folder before any retry), and
|
|
1242
|
+
`full_disk_access_missing`.
|
|
1243
|
+
|
|
1244
|
+
---
|
|
1245
|
+
|
|
1164
1246
|
#### `delete-folder`
|
|
1165
1247
|
|
|
1166
1248
|
Deletes a folder.
|