apple-notes-mcp 2.15.0 → 2.15.2

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.
@@ -1,95 +1,69 @@
1
- # Full Disk Access
2
-
3
- Apple Notes MCP works almost entirely without any special disk permission. The
4
- tools that need **Full Disk Access (FDA)** for the process responsible for the MCP
5
- server are the ones that read Notes' own SQLite store. Examples include:
6
-
7
- - **`get-checklist-state`** — reads a note's checklist done/undone state.
8
- - **Checklist annotations in `get-note-markdown`** — the `[x]` / `[ ]` prefixes on
9
- checklist items.
10
- - **`get-note-metadata` (BETA)** — pinned state, checklist flags, trash/recovery
11
- state, snippets, password hint. These columns exist nowhere else, so this tool
12
- needs FDA unconditionally.
13
- - **`get-note-link`** — its primary path reads the note's `ZIDENTIFIER` from the
14
- database. On macOS 12–15 it can fall back to the AppleScript `note link`
15
- property; that property is absent from the Notes SDEF on macOS 26+, so there
16
- FDA is the only route.
17
- - **`get-sync-status`** — degrades rather than fails: without database access it
18
- cannot see pending uploads or recent write activity.
19
-
20
- The AppleScript tools (creating, reading, searching, updating, moving, and
21
- deleting notes, for example) work **without** Full Disk Access. See the
22
- [full tool list](../README.md#full-disk-access) for all database-backed features.
23
-
24
- ## Why it's needed
25
-
26
- Apple Notes stores checklist items as a paragraph style inside a gzipped protobuf
27
- blob in its SQLite store, `NoteStore.sqlite`. AppleScript's `body of note`
28
- interface strips that state — it can't tell you whether a checklist item is
29
- checked. The same store also holds the pinned/trash/snippet columns behind
30
- `get-note-metadata` and the `ZIDENTIFIER` value behind `get-note-link`. To
31
- recover any of them, the MCP reads the SQLite store directly.
32
-
33
- That database lives in a macOS-protected directory:
1
+ # Full Disk Access and related permissions
34
2
 
3
+ Apple Notes MCP uses separate macOS permissions for different operations. Connecting an MCP client does not grant them. This guide covers the released 2.15.1 server; use diagnostics from the client that actually runs it.
4
+
5
+ | Requirement | Enables |
6
+ | --- | --- |
7
+ | Automation → Notes | AppleScript operations that read or change notes, folders, and accounts |
8
+ | Full Disk Access (FDA) | Reading the protected Notes database and media, including structured content, native-object verification, and some mutation guards |
9
+ | Installed Shortcuts and their first-run consent | Native tag, checklist, table, pin, and rich append operations; optional Markdown note creation |
10
+ | Public native helper | Classic PencilKit drawing decode and on-device audio transcription |
11
+ | Speech Recognition, where required by the macOS transcription route | On-device transcription; distinct from FDA and Notes Automation |
12
+
13
+ The server reads `~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite` with read-only database access. Writes use the supported AppleScript or Shortcut routes. FDA does not unlock password-protected notes or enable unsupported native edits.
14
+
15
+ ## Which features need Full Disk Access?
16
+
17
+ These groups use protected Notes data:
18
+
19
+ | Feature group | Tools and conditions |
20
+ | --- | --- |
21
+ | Search and library metadata | `query-notes`, `list-recent-notes`, `list-special-notes`, `list-folder-tree`, `get-note-metadata`, native tag inventory, Smart Folder rules, and database details in `get-sync-status` |
22
+ | Structured note contents | `get-note-blocks`, `get-note-structure`, `get-native-objects`, `get-note-tables`, `get-checklist-state`, `list-note-paragraphs`, `get-paragraph-link`, `list-note-links`, and stored audio transcripts |
23
+ | Portable exports | `export-notes-markdown`, `export-notes-html`, and attachment/media exports that read the Notes store |
24
+ | Attachments and drawings | `list-attachments` with `includePaths` or `firstImage`, `export-attachments`, `list-paper-attachments`, `export-paper-image`, `get-note-drawings`, and `transcribe-note-audio` |
25
+ | Guarded operations and identifiers | `delete-folder-by-id`; database-backed copy/active-note deletion guards; UUID or numeric note/folder selectors; native preservation/readback and Smart Folder destination detection |
26
+ | Optional private helper | `native-note-state`; the helper is read-only and requires its separate opt-in and build |
27
+
28
+ `get-note-link` needs FDA on macOS 26 and later. On macOS 12–15 it can fall back to Notes' AppleScript link property. `get-note-markdown` can still return Markdown without FDA, but native checklist done/undone annotations are unavailable.
29
+
30
+ Basic AppleScript paths can work without FDA after Automation is granted. That does not mean every use of a tool is available: its options, note contents, identifier form, and verification requirements can select a database-backed path. Guarded whole-body updates are unavailable when the server cannot read the metadata needed to establish that replacement is safe. Adding text to a note with native objects can route `append-to-note` through native append; deleting with a verified-copy guard also needs a database read. Keep exact IDs, fresh content hashes, and the tool's other preconditions. Do not bypass a refusal by rewriting the note through another route.
31
+
32
+ See the [tool reference](../README.md#tool-reference) for each operation's requirements and limitations.
33
+
34
+ ## Check before changing permissions
35
+
36
+ Use `get-capabilities` inside your MCP client first. It reports feature requirements, missing components, and unverified checks without opening Notes.app or running a Shortcut. It leaves Notes Automation unverified because testing that permission requires an Apple event.
37
+
38
+ For a non-prompting command-line permission report:
39
+
40
+ ```bash
41
+ npx -y apple-notes-mcp@2.15.1 setup --permissions --once --json --check
35
42
  ```
36
- ~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite
43
+
44
+ Use the package version and launch context that match your client. A check run in Terminal reports Terminal's process context; it does not certify a server launched by Claude Desktop or another desktop client.
45
+
46
+ Inspect each result, not only the exit code. `ready: true` can coexist with deliberately unprobed Automation and unavailable optional components. A missing public helper makes Speech status unknown. A Shortcut listed as installed may still be waiting for first-run consent.
47
+
48
+ The MCP `doctor` tool checks Notes reachability, Automation, accounts, FDA, runtime signing, and optional features. Unlike `get-capabilities`, it contacts Notes and can cause the first Automation prompt. Run it in the actual client when you are at the Mac and ready to answer that prompt. The optional feature matrix does not by itself determine `healthy`.
49
+
50
+ ## Grant access to the correct process
51
+
52
+ 1. Find the responsible process from diagnostics in the actual MCP client. For a **brokered session**, grant FDA to **Apple Notes MCP Broker.app**; `doctor` identifies whether the session uses the broker. For **Claude Desktop without the broker**, the server's **Node binary** needs FDA; the grant on Claude.app alone does not cover it. A terminal-launched server ordinarily uses the terminal app's permission; a server launched by VS Code uses that context. For other clients, confirm the reported process instead of assuming the app name is enough.
53
+ 2. Open **System Settings → Privacy & Security → Full Disk Access**.
54
+ 3. Click **+** and add the diagnosed app or Node executable. Press **⌘⇧G** in the file picker to enter an absolute path; **⌘⇧.** shows hidden files.
55
+ 4. Enable its toggle, then fully quit and relaunch the host application so it starts fresh processes.
56
+ 5. Re-run diagnostics inside that client. If FDA remains unavailable, verify the executable path and that the client was fully restarted before trying further changes.
57
+
58
+ A client sandbox can separately prevent the server from launching or connecting to the broker's Unix socket. Privacy grants do not expand that sandbox; check the client's launch and socket-access diagnostics separately.
59
+
60
+ FDA and Automation are independent. To check Automation from a terminal on the Mac, when you are ready for the first-use prompt:
61
+
62
+ ```bash
63
+ npx -y apple-notes-mcp@2.15.1 setup --permissions --once --probe-automation
37
64
  ```
38
65
 
39
- Reading anything under `~/Library/Group Containers/` requires **Full Disk
40
- Access** for the process that runs the server — without it, macOS denies the read. (The MCP only
41
- ever **reads** this database; it never writes to it.)
42
-
43
- ## How to grant Full Disk Access
44
-
45
- 1. Open **System Settings** (or **System Preferences** on older macOS).
46
- 2. Go to **Privacy & Security → Full Disk Access**.
47
- 3. Click the **+** button (you may need to unlock with Touch ID / your password
48
- first) and add the right entry for how you run the server:
49
- - **Permission broker** → `~/Applications/Apple Notes MCP Broker.app`, if you
50
- opted in with `apple-notes-mcp setup --broker`. Read the
51
- [trust trade-off below](#optional-permission-broker) before enabling it.
52
- - **Claude Desktop without the broker** → the **Node binary** that runs the server, e.g.
53
- `/usr/local/bin/node` or `~/.nvm/versions/node/v24.11.1/bin/node`. The
54
- `doctor` tool prints the exact path. In the file picker, press **⌘⇧G** and
55
- paste it (use **⌘⇧.** to show hidden folders such as `~/.nvm`). Adding
56
- `/Applications/Claude.app` as well does no harm, but on its own it is not
57
- enough (see below).
58
- - **Claude Code or another client in a terminal** → the terminal app:
59
- `/Applications/Utilities/Terminal.app` or `/Applications/iTerm.app`
60
- - **VS Code** → `/Applications/Visual Studio Code.app`
61
- 4. Make sure the toggle next to the entry is **on**.
62
- 5. **Fully quit and reopen the host app.** macOS only applies the new permission
63
- to processes started *after* the change. A reload or restart-server is not
64
- enough; quit the host application itself (⌘Q) and relaunch it. If `doctor`
65
- still reports Full Disk Access as not granted after that, restart the Mac.
66
-
67
- > **Why Claude Desktop needs the Node binary without the broker.** macOS checks Full Disk
68
- > Access against the *responsible process*, the app it holds accountable for a
69
- > request. A terminal passes that role on to everything it launches, so a grant
70
- > on Terminal or iTerm covers the server. Claude Desktop does not: it starts each
71
- > MCP server through a helper that *disclaims* responsibility, which makes the
72
- > `node` process its own responsible process. macOS then looks for a grant on the
73
- > Node binary's path and ignores the one on Claude.app
74
- > ([#220](https://github.com/sweetrb/apple-notes-mcp/issues/220)).
75
- >
76
- > The grant is tied to that exact path. With a version manager (nvm, fnm, Volta,
77
- > asdf, mise) the path changes with every Node version, so switching versions
78
- > drops the grant, and `npx` runs whichever `node` is first on the `PATH` Claude
79
- > Desktop sees. Pointing the config at one fixed Node binary keeps the grant
80
- > stable:
81
- >
82
- > ```json
83
- > "apple-notes": {
84
- > "command": "/Users/you/.nvm/versions/node/v24.11.1/bin/node",
85
- > "args": ["/path/to/global/node_modules/apple-notes-mcp/build/index.js"]
86
- > }
87
- > ```
88
- >
89
- > A Developer-ID-signed Node at a stable path avoids the identity changes of
90
- > ad-hoc rebuilds. Permission continuity still depends on its designated code
91
- > requirement and macOS permission state. See
92
- > [Node runtime and TCC permissions](NODE-RUNTIME-AND-TCC-PERMISSIONS.md).
66
+ This sends one read-only Apple event. Accept the macOS prompt to allow the launching process to control Notes. `--check` and SSH sessions suppress this probe even when `--probe-automation` is present. `--open` can open the relevant System Settings panes; it does not change a permission.
93
67
 
94
68
  ## Optional permission broker
95
69
 
@@ -134,32 +108,36 @@ same-user processes from using it. To remove that access, run
134
108
  also revoke the broker's Full Disk Access and Notes Automation grants in System
135
109
  Settings.
136
110
 
137
- ## Verifying it worked
138
-
139
- Run the **`doctor`** tool. It reports a dedicated **Full Disk Access** check as
140
- `ok` / `warn` / `fail` with the reason, so you can confirm the grant took effect
141
- without guessing. Its `broker` field identifies whether the session uses the
142
- broker or has fallen back to an in-process server with its own permissions.
143
- You can also just call `get-checklist-state` on a note that has
144
- a checklist — if it returns items with `[x]`/`[ ]` state, FDA is working.
145
-
146
- ## Without Full Disk Access
147
-
148
- The server degrades gracefully — nothing crashes:
149
-
150
- - `get-checklist-state` returns a clear error explaining that database access is
151
- needed (and points here).
152
- - `get-note-metadata` returns the same kind of error — it has no non-database
153
- path, so it cannot answer at all without FDA.
154
- - `get-note-link` returns an error on macOS 26+. On macOS 12–15 it still works,
155
- via the AppleScript `note link` fallback.
156
- - `get-note-markdown` still returns the note as Markdown, but checklist items
157
- appear as plain list items without the `[x]`/`[ ]` annotations.
158
- - `get-sync-status` still answers, but with no database visibility it reports no
159
- pending uploads and no active sync — treat that as "unknown", not "idle".
160
- - **AppleScript-only tools work normally.** See the
161
- [full tool list](../README.md#full-disk-access) for other database-backed tools
162
- that require FDA.
163
-
164
- See also: [Known Limitations](../README.md#known-limitations) and
165
- [Creating Checklists](../README.md#creating-checklists) in the README.
111
+ ## Complete the optional native setup
112
+
113
+ For native operations, install the packaged workflows:
114
+
115
+ ```bash
116
+ npx -y apple-notes-mcp@2.15.1 setup
117
+ npx -y apple-notes-mcp@2.15.1 setup --check
118
+ ```
119
+
120
+ Confirm **Add Shortcut** for each imported workflow. After installation or upgrade, run **Apple Notes MCP - Native Tags** and **Apple Notes MCP - Background Operations v5** once in the foreground in Shortcuts.app and choose **Always Allow** when asked. The optional **Create Markdown Note** bridge requires macOS 26+ and the documented input for its foreground run. Follow the [Shortcut setup instructions](../shortcuts/README.md).
121
+
122
+ Installation checks cannot read Shortcut consent state. An unanswered prompt can stall background native writes while the bridge still reports installed. If a write times out or its outcome is uncertain, read the exact note before retrying; the change may already have landed.
123
+
124
+ External public and private native helpers are unavailable in brokered sessions. Set `APPLE_NOTES_MCP_BROKER=off` for this client and restart it before using tools that require them.
125
+
126
+ For drawing decode or transcription, build the public helper locally with a current Swift toolchain and macOS SDK that expose the macOS 26 `SpeechAnalyzer` and `SpeechTranscriber` APIs. Having Command Line Tools installed does not alone prove that their SDK can build the helper; older SDK builds are unverified.
127
+
128
+ ```bash
129
+ npx -y apple-notes-mcp@2.15.1 setup --public-helper
130
+ npx -y apple-notes-mcp@2.15.1 setup --public-helper --check
131
+ ```
132
+
133
+ The helper never requests Speech Recognition permission in the background. On older macOS, the recognition route requires an existing grant to the launching app; on macOS 26+, the server handles SpeechAnalyzer separately. A missing language model returns `asset_unavailable`; downloading it requires the explicit `downloadAssets` option. See [on-device transcription](../README.md#transcribe-note-audio) for the current route and permission contract.
134
+
135
+ ## When a feature is unavailable
136
+
137
+ - Without FDA, database-only tools return an access error. For simple searches, `search-notes` has an AppleScript fallback; this does not replace `query-notes`' structured query support.
138
+ - Without database visibility, `get-sync-status` cannot establish pending uploads or active sync. Treat absent/zero database information as unknown, not proof that syncing is complete.
139
+ - Smart Folder detection and native-object guards depend on their documented read paths. Do not infer safe destination or preservation behavior from an incomplete diagnostic.
140
+ - If `doctor` reports FDA missing, use the per-feature requirements above. Optional feature availability does not determine `doctor.healthy`, and its summary does not enumerate every database-backed guard.
141
+ - If prompts recur after Node updates, check the exact executable path and signature. A version-manager path change or replacement of an ad-hoc-signed binary can invalidate its grants. A stable path and a Developer-ID-signed Node runtime reduce this problem; see [Node runtime and TCC permissions](NODE-RUNTIME-AND-TCC-PERMISSIONS.md).
142
+
143
+ Broker installation remains optional. Use its [setup and migration instructions](../README.md#permission-broker-opt-in) when you choose it, and rerun setup after a package or runtime change. A broker fallback uses the in-process server's own permissions; inspect `doctor.broker` before choosing which process to grant.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-notes-mcp",
3
- "version": "2.15.0",
3
+ "version": "2.15.2",
4
4
  "description": "MCP server for Apple Notes - read, search, create, edit, organize, and export notes on macOS via Claude and other AI assistants",
5
5
  "type": "module",
6
6
  "main": "build/index.js",