Apple Mail MCP Server
Read, search, send and organise mail in the macOS Mail app from an MCP client
Local stdio server for reading, searching, editing, organising and exporting Apple Notes on a Mac
By Rob Sweet (individual) TypeScript Local · stdio Productivity
62 popularity score ★ 180 ↓ 3.0k/wk
Opens the app, which asks before it adds the server.
claude mcp add apple-notes -- npx -y apple-notes-mcp@2.15.1{
"mcpServers": {
"apple-notes": {
"command": "npx",
"args": [
"-y",
"apple-notes-mcp@2.15.1"
]
}
}
}{
"mcpServers": {
"apple-notes": {
"command": "npx",
"args": [
"-y",
"apple-notes-mcp@2.15.1"
]
}
}
}{
"servers": {
"apple-notes": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"apple-notes-mcp@2.15.1"
]
}
}
}[mcp_servers.apple-notes]
command = "npx"
args = ["-y", "apple-notes-mcp@2.15.1"]gemini mcp add --scope user apple-notes npx -- -y apple-notes-mcp@2.15.1Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
git clone --branch v2.15.1 https://github.com/sweetrb/apple-notes-mcp.gitclaude mcp add apple-notes -- node '<ABSOLUTE_PATH_TO_CLONE>/build/index.js'{
"mcpServers": {
"apple-notes": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
]
}
}
}{
"mcpServers": {
"apple-notes": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
]
}
}
}{
"servers": {
"apple-notes": {
"type": "stdio",
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
]
}
}
}[mcp_servers.apple-notes]
command = "node"
args = ["<ABSOLUTE_PATH_TO_CLONE>/build/index.js"]gemini mcp add --scope user apple-notes node -- '<ABSOLUTE_PATH_TO_CLONE>/build/index.js'APPLE_NOTES_MCP_TIMEOUT_MS |
Optional: Total time for a Notes call, retries included. A write's timeoutSeconds overrides it. |
|---|---|
APPLE_NOTES_MCP_MAX_RETRIES |
Optional: Retries for transient errors on read-only calls. Writes run once. |
APPLE_NOTES_MCP_MAX_BUFFER |
Optional: Most bytes kept from one AppleScript call (64 MB). |
APPLE_NOTES_MCP_MAX_ATTACHMENT_BYTES |
Optional: Largest attachment returned inline (25 MB). |
APPLE_NOTES_MCP_MAX_INLINE_IMAGE_BYTES |
Optional: Largest image kept inline per image. Bigger ones become placeholders. |
APPLE_NOTES_MCP_EXPORT_MAX_BYTES |
Optional: Size cap on exports (8 MB). Inline Markdown export gets half. |
APPLE_NOTES_MCP_BLOCKS_MAX_BYTES |
Optional: Page size cap for block, paragraph and link listings (4 MB). |
APPLE_NOTES_MCP_CONFIG_FILE |
Optional: JSON settings file. Only string values fill settings left unset. Brokered servers skip it. |
APPLE_NOTES_MCP_ENABLE_PRIVATE |
Optional: Set to 1 to turn on the private helper, which you build with setup --native-helper. Any other value leaves it off. Not passed to a brokered server. |
APPLE_NOTES_MCP_ALLOW_PRIVATE_CONTENT_PATHS |
Optional: Set to 1 to let file-reading tools open hidden folders and ~/Library outside iCloud Drive. Not passed to a brokered server. |
APPLE_NOTES_MCP_PUBLIC_HELPER_TIMEOUT_MS |
Optional: Time limit for one public helper call. |
APPLE_NOTES_MCP_PRIVATE_HELPER_TIMEOUT_MS |
Optional: Time limit for one private helper call. |
Apple Notes MCP runs on your Mac as a stdio server and gives an assistant read and write access to the Notes library there. Plain reads and edits go through AppleScript. A set of signed Shortcuts, which you import once, handles the things AppleScript cannot reach, such as native tags, checklists, tables and pinning. With Full Disk Access it also reads the Notes database directly, read-only, which is what powers the boolean query tool, link listing and checklist state.
The README documents 89 tools. Most of them write. Edits and deletes need the content hash from a recent read, so a note that changed since the assistant looked at it is left alone and reported as a conflict. Deleting a note moves it to Recently Deleted, and the server refuses to delete a note that is already there because that would be permanent.
Recent releases add an opt-in permission broker (`apple-notes-mcp setup --broker`). It is a small signed app with a LaunchAgent that holds the Full Disk Access and Automation grants, so replacing Node no longer means granting them again. The client side only relays bytes over a local Unix socket. In src/services/brokerProxy.ts the relay waits 5 seconds for the broker and then quietly runs the server in-process. Only ten numeric settings cross that socket: the TIMEOUT_MS, MAX_RETRIES, RETRY_DELAY_MS, MAX_BUFFER, MAX_ATTACHMENT_BYTES, MAX_INLINE_IMAGE_BYTES, EXPORT_MAX_BYTES and BLOCKS_MAX_BYTES limits plus the two helper timeouts, all with the APPLE_NOTES_MCP_ prefix. Anything else you set for a brokered session is dropped, and the brokered server ignores the JSON settings file too.
| Runtime | Node.js 20+ |
|---|---|
| Runs on | macOS |
| Apple Notes | Freeat least one Notes account set up on the Mac |
| Also |
|
Grant the launching app macOS Automation access to Notes. Full Disk Access goes to the responsible process: the Node binary under Claude Desktop, or Apple Notes MCP Broker.app when the broker is in use. For native tags, checklists, tables and pinning, run `npx -y apple-notes-mcp@2.15.1 setup`, import the Shortcuts and run each one once in Shortcuts.app. Drawing decoding and audio transcription need the helper built by `setup --public-helper`. `setup --broker` installs the broker as the LaunchAgent `apple-notes-mcp.broker` and needs a Node runtime linked only to system libraries. `--sign-identity` signs it with your own identity. Signed ad hoc, it needs fresh grants after a rebuild.
macOS only, and it must run on the Mac holding the library: it has no HTTP, SSE or OAuth endpoint, so cloud-only clients cannot use it. Without Full Disk Access the query, checklist-state, link, transcript and other database tools are unavailable, and an unavailable feature must not be read as an empty result. Password-protected notes cannot be read. A native Shortcut write can stall on an unanswered consent prompt; after a timeout the write may already have happened. `fetch-attachment` returns at most 25 MB inline by default (`APPLE_NOTES_MCP_MAX_ATTACHMENT_BYTES`). The private helper (`native-note-state`) relies on Apple's private API and is off unless `APPLE_NOTES_MCP_ENABLE_PRIVATE=1`.
Suits someone who keeps notes in Apple Notes and wants Claude Code, Claude Desktop, Codex or another local stdio client to search, file, edit and export them, tags and checklists included. Plan on some setup: macOS permissions, Shortcut imports and Full Disk Access for much of it. If Node changes under you often, the broker saves repeat grants, at the cost of letting any process running as your user use them. It is a community project with no tie to Apple. Look elsewhere if your assistant runs in the cloud or on another OS, or if you only want reads, since many tools write and you would have to rely on your client's tool approval.
38 only read, 19 change things, 3 can delete or overwrite. A ? marks an optional parameter.
create-note changestitle: stringcontent?: stringcontentPath?: stringformat?: enummarkdownRoute?: enumtags?: arrayfolder?: stringaccount?: stringtimeoutSeconds?: integersearch-notesquery: stringsearchContent?: booleanaccount?: stringfolder?: stringmodifiedSince?: stringlimit?: integerincludeWordCount?: booleanquery-notesquery: stringlimit?: integerscanLimit?: integerincludeDeleted?: booleanincludeWordCount?: booleanget-note-contentid?: stringtitle?: stringaccount?: stringtimeoutSeconds?: integerget-note-plaintextid?: stringtitle?: stringaccount?: stringget-note-detailsget-note-markdownid?: stringtitle?: stringaccount?: stringget-note-linkid?: stringtitle?: stringaccount?: stringget-native-objectsget-note-tablesid: stringoffset?: integerlimit?: integermaxBytes?: integerget-note-blocksid: stringoffset?: integerlimit?: integerget-note-structureid: stringincludeText?: booleanlist-note-paragraphslinkableOnly?: booleanoffset?: integerlimit?: integerrecordAnchors?: booleanget-paragraph-linkcontains?: stringmatch?: stringblockIndex?: integeroccurrence?: integerrecordAnchor?: booleancreate-paragraph-anchor changescontains?: stringmatch?: stringblockIndex?: integeroccurrence?: integerresolve-paragraph-anchoranchorId: stringminConfidence?: numberrefresh?: booleanlist-paragraph-anchorsnoteIdentifier: anyoffset?: integerlimit?: integerget-paragraph-anchorprune-paragraph-anchors deletesanchorIds?: arraynoteIdentifier: anystatuses: enumdryRun?: booleanlist-note-linksid?: anyaccount?: stringfolder?: stringincludeSubfolders?: booleanincludeInline?: booleankinds?: enumoffset?: integerlimit?: integerlist-native-tagsaccount?: stringfolder?: stringupdate-note deletesid: stringexpectedContentHash: stringallowLinkChanges?: booleannewTitle?: stringnewContent: stringformat?: enumtimeoutSeconds?: integerappend-to-note changesid: stringexpectedContentHash: stringcontent: stringscopeText?: stringposition?: enumseparator?: stringformat?: enumtimeoutSeconds?: integerinsert-link changesid: stringexpectedContentHash: stringurl: stringmode?: enumlabel?: stringlinked?: booleanposition?: enumblankLine?: booleanscopeText?: stringappend-native changesid: stringexpectedContentHash: stringscopeText: stringcontent: stringformat?: enumcreate-checklist-items changesid: stringexpectedContentHash: stringscopeText: stringitems: arraycreate-table changesid: stringexpectedContentHash: stringscopeText: stringrows?: arrayset-note-pinned changesid: stringexpectedContentHash: stringscopeText: stringexpectedPinned: booleanpinned: booleanremove-native-tags changesid: stringexpectedContentHash: stringscopeText: stringtags: arrayreplace-native-tag changesnotes: arrayoldTag: stringnewTag: stringinsert-note-link changesid: stringexpectedContentHash: stringscopeText: stringlinkedNoteId: stringlabel?: stringdelete-note changesid: stringexpectedContentHash: stringguardNoteId?: anyexpectedGuardContentHash?: anyrequireActiveNoteId?: anytimeoutSeconds?: integerbatch-delete-notes changesnotes: arraymove-note changesid: stringfolder: stringaccount?: stringtimeoutSeconds?: integerbatch-move-notes changesids: arrayfolder: stringaccount?: stringlist-notesaccount?: stringfolder?: stringmodifiedSince?: stringlimit?: integerincludeRecentlyDeleted?: booleanget-selected-noteslist-foldersaccount?: stringlist-smart-foldersincludeMatchingNotes?: booleanlimit?: integercreate-folder changesname: stringaccount?: stringdelete-folder deleteslist-accountsget-default-locationlist-shared-notesget-sync-statusdoctorget-capabilitiesget-notes-statsshow-noteid: stringseparately?: booleanshow-folderid: stringseparately?: booleanshow-accountid: stringseparately?: booleanlist-attachmentsid?: stringtitle?: stringaccount?: stringincludePaths?: booleanfirstImage?: booleansave-attachment changesnoteId: stringattachmentId: stringsavePath: stringexport-attachments changesnoteId: stringexportDir: stringfirstImageOnly?: booleanfetch-attachmentnoteId: stringattachmentId: stringshow-attachmentnoteId: stringattachmentId: stringseparately?: booleanlist-paper-attachmentsexport-paper-image changesnoteId: stringsavePath: stringattachmentId?: stringexport-notes-jsonoffset?: integerlimit?: integermodifiedSince?: stringexport-notes-markdownid?: anyfolder: anynotes://accountsnotes://foldersnotes://statsnotes://note/{id}find-noteweekly-reviewnew-meeting-note