apple-notes-mcp 2.8.32 → 2.8.34

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.
Files changed (3) hide show
  1. package/README.md +66 -7
  2. package/build/index.js +1054 -166
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -171,7 +171,7 @@ On first use, macOS will ask for permission to automate Notes.app. Click "OK" to
171
171
  | **Checklist State** | Read checklist done/undone state directly from the Notes database (requires Full Disk Access) |
172
172
  | **Audio Transcripts** | Read the transcripts and summaries Notes stored for audio recordings (requires Full Disk Access) |
173
173
  | **Export** | Export all notes as JSON or get individual notes as Markdown |
174
- | **Attachments** | List attachments, save them to disk, or fetch their bytes as base64 |
174
+ | **Attachments** | List attachments with their on-disk asset and preview paths, find a note's lead image, save or batch-export them to disk, or fetch their bytes as base64 |
175
175
  | **Notes.app UI State** | Reveal a note in Notes.app or read the current Notes.app selection |
176
176
  | **Sync Awareness** | Detect iCloud sync in progress, warn about incomplete results |
177
177
  | **Collaboration** | Detect shared notes, warn before modifying |
@@ -332,13 +332,42 @@ title line, with no seed line.
332
332
  It also refuses Markdown that Notes would rewrite and the server could not
333
333
  verify: `_` emphasis (underscores inside a word, as in `snake_case`, and
334
334
  inside a link destination, as in `[docs](https://example.com/_next/static)`,
335
- are fine), backslash escapes, character references such as `&`, `---` or
336
- `===` lines, indented headings or list items, `1)` lists, closing `#`s, and
335
+ are fine), backslash escapes, character references such as `&`, `===` lines
336
+ and rule lines other than the `---` divider described below, indented headings or list items, `1)` lists, closing `#`s, and
337
337
  formatting inside link labels. Content that needs one of these literally, such
338
338
  as a `/_next` path or a literal `\*`, has no Markdown form here: use
339
339
  `format: "html"` for that note (or `append-native` with `format: "html"` on an
340
340
  existing one), which keeps the characters but not the Heading and Subheading
341
341
  styles. Markdown punctuation in `title` is escaped, so the title stays literal.
342
+ - Notes' importer also maps these block constructs to native styles. They are
343
+ gated separately, and `get-capabilities` reports them as
344
+ `create-note-markdown-blocks`. Each mapping below was live-verified on
345
+ macOS 27.2 by reading the created note's stored styles.
346
+
347
+ | Markdown | Native result |
348
+ |----------|---------------|
349
+ | `- [ ] item` / `- [x] item` | Checklist item, unchecked / checked |
350
+ | `> text` (consecutive lines form one quote) | Body paragraph with a block quote |
351
+ | A fence of bare ```` ``` ```` lines (no language) | Monospaced paragraphs; the code text is kept literally |
352
+ | `---` on its own line, after a blank line | Divider line |
353
+ | `` `inline code` `` | **Highlighted** text, not monospace |
354
+
355
+ Constructs Notes would not render faithfully, or that this server cannot yet
356
+ verify, are refused before anything is created: `~~~` fences, a language
357
+ after the opening fence, nested (`>>`) or indented quotes, lists or headings
358
+ inside a quote, a quote followed directly by text (Markdown would join that
359
+ text to the quote), `---` directly under text (Markdown would make that text
360
+ a heading), `***`/`___`/`----` rules, `[X]`, `* [ ]` or `+ [ ]` items, checklist
361
+ items directly next to ordinary list items, inline code padded with spaces or
362
+ inside a link label, tables, and `~~strikethrough~~`. The readback checks the
363
+ block-quote text, the Monospaced text, each checklist item's text and done
364
+ state, the divider count, and the highlighted text. These mappings apply to
365
+ the default Shortcut route only; see
366
+ [Markdown through HTML](#markdown-through-html) for `markdownRoute: "html"`.
367
+ - [`append-native`](#append-native)'s `format: "markdown"` refuses all of the
368
+ constructs above: its Shortcuts converter is a different one, which renders
369
+ a quote and a fenced block as plain body text, `- [ ]` as a bullet with
370
+ literal brackets, and inline code as plain text, and drops `---`.
342
371
  - The server finds the new note among the notes added to the default folder
343
372
  during the run by verifying each one's visible text, heading levels and links
344
373
  by exact-ID readback, and moves it only after exactly one verifies. On any
@@ -366,7 +395,9 @@ On this route, bullet task items (`- [ ] item`, `- [x] item`) become ordinary
366
395
  list rows that start with a visible `☐` or `☑` character, and the response
367
396
  reports how many as `taskItemsRendered`. They are text, not native checkable
368
397
  checklist items. Use this route as the glyph fallback when the Shortcut is not
369
- installed or the note is outside iCloud.
398
+ installed or the note is outside iCloud. Block quotes, fenced code and inline code, which
399
+ the Shortcut route maps natively, are refused on this route, and a `---` line
400
+ stays literal text rather than becoming a divider.
370
401
 
371
402
  ```json
372
403
  {
@@ -1404,10 +1435,22 @@ Lists attachments in a note.
1404
1435
  | `id` | string | No | Note ID (preferred) |
1405
1436
  | `title` | string | No | Note title |
1406
1437
  | `account` | string | No | Account containing the note |
1438
+ | `includePaths` | boolean | No | Also report where each attachment's files are on disk (needs `id` and Full Disk Access) |
1439
+ | `firstImage` | boolean | No | Return only the note's lead visual instead of the list (needs `id` and Full Disk Access) |
1407
1440
 
1408
1441
  **Returns:** List of attachments with IDs, names, content identifiers, URLs when available, created/modified dates, and shared state.
1409
1442
 
1410
- **⚠️ Safety:** A lookup failure is reported as an error, never as an empty list — so an empty result reliably means the note has no attachments and is safe to replace wholesale. Treat an error as "unknown", not "none".
1443
+ With `includePaths`, each attachment also carries `identifier`, `uti`, `kind` (`image`, `scan`, `drawing`, `pdf`, `audio`, `video`, `url`, `table`, `other`), `bodyIndex`, and three path fields read from NoteStore and the Notes data folder (read-only):
1444
+
1445
+ - `assetPaths`: the attachment's own files, best first (the media file, or Notes' fallback image or PDF rendering).
1446
+ - `previewPath`: Notes' largest rendered thumbnail, chosen by pixel area from the `Previews` entries named `<identifier>-<scale>-<W>x<H>-<appearance>`. It is always the image file, including when the entry is a directory holding `<n>_<uuid>/Preview.png`. `null` when there is none.
1447
+ - `paths`: `assetPaths` followed by `previewPath`.
1448
+
1449
+ Container attachments (a scan gallery) list their child rows under `children`. If the database cannot be read, the list is still returned with a `pathsError`.
1450
+
1451
+ With `firstImage`, the result is `{firstImage, orderSource}`. `firstImage` is the first image in the note's body order, even when its asset has not downloaded (`path: null`, possibly with a `previewPath`). A scan or drawing stands in only when the note has no image, and a gallery's pages are considered at the gallery's position (`parentIdentifier`, `galleryIndex`). `orderSource` is `body`, or `creation` when the body did not record attachment order. `firstImage` is `null` when the note has no visual.
1452
+
1453
+ **⚠️ Safety:** A lookup failure is reported as an error, never as an empty list — so an empty result reliably means the note has no attachments and is safe to replace wholesale. Treat an error as "unknown", not "none". Treat returned paths as local data: copy files out with [`export-attachments`](#export-attachments) instead of passing raw paths on.
1411
1454
 
1412
1455
  ---
1413
1456
 
@@ -1425,6 +1468,22 @@ Saves a note attachment to disk.
1425
1468
 
1426
1469
  ---
1427
1470
 
1471
+ #### `export-attachments`
1472
+
1473
+ Copies a note's attachment files into a directory without opening Notes.app.
1474
+
1475
+ | Parameter | Type | Required | Description |
1476
+ |-----------|------|----------|-------------|
1477
+ | `noteId` | string | Yes | Exact CoreData note ID |
1478
+ | `exportDir` | string | Yes | Absolute destination directory, created if missing. Same allowlist as `save-attachment` (home, temp, or `/Volumes`), and never inside the Notes data folder |
1479
+ | `firstImageOnly` | boolean | No | Export only the lead visual that `list-attachments` `firstImage` reports |
1480
+
1481
+ **Returns:** `exportDir`, counts (`exported`, `previews`, `skipped`, `failed`), and per attachment its `attachmentId`, `identifier`, `kind`, `exportedTo`, and `exportedKind`: `"asset"` for the real file, `"preview"` when the asset never downloaded and only Notes' thumbnail was on disk, or `null` when nothing was on disk. A preview is never chosen over an available asset, and it is named `<name>-preview.<ext>` so it is not mistaken for the original. A scan gallery with no file of its own exports its pages.
1482
+
1483
+ **⚠️ Safety:** Existing files are never replaced. A name that is taken gets `-2`, `-3`, and so on. Reads NoteStore and the Notes data folder read-only and needs Full Disk Access.
1484
+
1485
+ ---
1486
+
1428
1487
  #### `fetch-attachment`
1429
1488
 
1430
1489
  Returns a note attachment's bytes as base64, without writing to disk (the read counterpart to `save-attachment`).
@@ -1805,7 +1864,7 @@ MCP stores no secrets, but as a general rule keep only non-secret config here.
1805
1864
 
1806
1865
  ## Full Disk Access
1807
1866
 
1808
- Several tools read directly from the Apple Notes SQLite database, which lives in a macOS-protected directory. Those tools require **Full Disk Access** for the process running the MCP server: `get-checklist-state`, `get-note-metadata`, `get-note-blocks`, `get-audio-transcripts`, `get-note-link`, the checklist annotations in `get-note-markdown`, and the database half of `get-sync-status`.
1867
+ Several tools read directly from the Apple Notes SQLite database, which lives in a macOS-protected directory. Those tools require **Full Disk Access** for the process running the MCP server: `get-checklist-state`, `get-note-metadata`, `get-note-blocks`, `get-audio-transcripts`, `get-note-link`, the checklist annotations in `get-note-markdown`, `list-attachments` with `includePaths` or `firstImage`, `export-attachments`, and the database half of `get-sync-status`.
1809
1868
 
1810
1869
  > 📘 **For the full why-and-how walkthrough (which app to grant, verifying with `doctor`, graceful degradation), see the [Full Disk Access Setup Guide](https://github.com/sweetrb/apple-notes-mcp/blob/main/docs/FULL-DISK-ACCESS.md).** The summary below is the quick version.
1811
1870
 
@@ -1870,7 +1929,7 @@ Apple Notes stores checklists as a paragraph style (`style_type=103`) inside a g
1870
1929
  **Workarounds:**
1871
1930
 
1872
1931
  1. **Create the note with bulleted list items, then convert manually in Notes.app.** Select the items and press <kbd>⇧⌘L</kbd> (or **Format → Checklist**). This converts the list in place and the resulting checklist will be readable by `get-checklist-state` and annotated by `get-note-markdown`.
1873
- 2. **Use the Apple Shortcuts app** to script the checklist creation, since Shortcuts can manipulate Notes content at a higher level than AppleScript.
1932
+ 2. **Use the Apple Shortcuts app** to script the checklist creation, since Shortcuts can manipulate Notes content at a higher level than AppleScript. This server does that for you in two ways: [`create-checklist-item`](#create-checklist-item) appends one unchecked item to an existing note, and [`create-note`](#create-note) with `format: "markdown"` turns `- [ ]` / `- [x]` lines into checklist items with that done state through Notes' own Markdown importer, (see [Markdown notes](#markdown-notes)).
1874
1933
  3. **Read-only checklist support is fully implemented** — once a checklist exists (created manually or by another app), `get-checklist-state` and `get-note-markdown` will read its done/undone state correctly (with Full Disk Access).
1875
1934
 
1876
1935
  If you need to *track* todos programmatically and don't strictly need them rendered as Apple Notes checklist UI, plain markdown-style `- [ ] item` / `- [x] item` lines in a `plaintext` note are a reasonable alternative — they are searchable, human-readable, and can be parsed by downstream tooling.