Install
$ agentstack add mcp-sweetrb-apple-notes-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Apple Notes MCP Server
A Model Context Protocol (MCP) server that enables AI assistants like Claude to read, create, search, and manage notes in Apple Notes on macOS.
[](https://www.npmjs.com/package/apple-notes-mcp) [](https://www.npmjs.com/package/apple-notes-mcp) [](https://www.npmjs.com/package/apple-notes-mcp) [](https://github.com/sweetrb/apple-notes-mcp/actions/workflows/ci.yml) [](https://scorecard.dev/viewer/?uri=github.com/sweetrb/apple-notes-mcp) [](https://www.apple.com/macos/) [](https://opensource.org/licenses/MIT) [](https://modelcontextprotocol.io)
What is This?
This server acts as a bridge between AI assistants and Apple Notes. Once configured, you can ask Claude (or any MCP-compatible AI) to:
- "Save this conversation as a note called 'Meeting Summary'"
- "Find all my notes about the project deadline"
- "Read my shopping list note"
- "Move my draft notes to the Archive folder"
- "What notes do I have in my Work folder?"
The AI assistant communicates with this server, which then uses AppleScript to interact with the Notes app on your Mac. All data stays local on your machine.
Quick Start
Using Claude Code (Easiest)
If you're using Claude Code (in Terminal or VS Code), just ask Claude to install it:
Install the sweetrb/apple-notes-mcp MCP server so you can help me manage my Apple Notes
Claude will handle the installation and configuration automatically.
Using the Plugin Marketplace
Install as a Claude Code plugin for automatic configuration and enhanced AI behavior:
/plugin marketplace add sweetrb/apple-notes-mcp
/plugin install apple-notes
This method also installs a skill that teaches Claude when and how to use Apple Notes effectively.
Using the Codex Marketplace
The same plugin is available for Codex. Add the marketplace and install the plugin:
codex plugin marketplace add sweetrb/apple-notes-mcp
codex plugin add apple-notes@apple-notes-mcp
The Codex plugin runs the published apple-notes-mcp server through npx and ships the same Apple Notes skill, so behavior matches the Claude Code plugin.
Other Hosts (Hermes, Antigravity)
Configuration for two more hosts is included — each registers the same apple-notes MCP server (npx -y apple-notes-mcp):
- Hermes Agent (NousResearch) — Hermes has no plugin/marketplace drop-in. Add the server with
hermes mcp add apple-notes --command npx --args -y apple-notes-mcp, or merge [.hermes-plugin/config.yaml](.hermes-plugin/config.yaml) into~/.hermes/config.yaml. Details: [.hermes-plugin/README.md](.hermes-plugin/README.md). - Antigravity (Google) — add the server entry from [
.antigravity-plugin/mcp_config.json](.antigravity-plugin/mcpconfig.json) to~/.gemini/config/mcp_config.json(or via Antigravity's MCP settings).
Manual Installation
1. Install the server:
npm install -g github:sweetrb/apple-notes-mcp
2. Add to Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"apple-notes": {
"command": "npx",
"args": ["apple-notes-mcp"]
}
}
}
3. Restart Claude Desktop and start using natural language:
"Create a note called 'Ideas' with my brainstorming thoughts"
On first use, macOS will ask for permission to automate Notes.app. Click "OK" to allow.
Requirements
- macOS - Apple Notes and AppleScript are macOS-only
- Node.js 20+ - Required for the MCP server
- Apple Notes - Must have at least one account configured (iCloud, Gmail, etc.)
Features
| Feature | Description | |---------|-------------| | Create Notes | Create notes with titles, content, and optional folder/account targeting | | Search Notes | Find notes by title or search within note content | | Read Notes | Retrieve note content and metadata | | Update Notes | Modify existing notes (title and/or content) | | Delete Notes | Remove notes (moves to Recently Deleted) | | Move Notes | Organize notes into folders (supports nested paths) | | Folder Management | Create, list, and delete folders with full hierarchical path support | | Multi-Account | Work with iCloud, Gmail, Exchange, or any configured account, including account IDs and default folders | | Batch Operations | Delete or move multiple notes at once | | Checklist State | Read checklist done/undone state directly from the Notes database (requires Full Disk Access) | | Export | Export all notes as JSON or get individual notes as Markdown | | Attachments | List attachments, save them to disk, or fetch their bytes as base64 | | Notes.app UI State | Reveal a note in Notes.app or read the current Notes.app selection | | Sync Awareness | Detect iCloud sync in progress, warn about incomplete results | | Collaboration | Detect shared notes, warn before modifying | | Diagnostics | health-check plus a richer doctor (reachability, automation permission, accounts, Full Disk Access), sync status, and statistics |
Read/list/get tools also return structured JSON (structuredContent) alongside the text, so agents can consume results without parsing prose.
MCP resources & prompts
Resources expose read-only context the client can attach without a tool call: notes://accounts, notes://folders, notes://stats, and the notes://note/{id} template (returns the note as Markdown). Prompts package common workflows: find-note, weekly-review, new-meeting-note.
Known limitations
A few Notes UI features are not exposed to AppleScript and therefore cannot be supported. See [docs/APPLESCRIPT-LIMITATIONS.md](docs/APPLESCRIPT-LIMITATIONS.md) for the investigation and verification behind each:
- Pinned notes — Notes has no scriptable
pinnedproperty via AppleScript. Pin state can now be read with the BETAget-note-metadatatool (from the NoteStore database), but it still cannot be set programmatically. - Note-to-note links — there is no
applenotes://deep link or link property; the only stable handle is thex-coredata://note id.
Tool Reference
This section documents all available tools. AI agents should use these tool names and parameters exactly as specified.
Note Operations
create-note
Creates a new note in Apple Notes.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | title | string | Yes | The title of the note. Automatically prepended as ` — do NOT include the title in content | | content | string | Yes | The body content of the note (do not repeat the title here) | | tags | string[] | No | Tags for organization (stored in metadata) | | folder | string | No | Folder to create the note in. Supports nested paths like "Work/Clients". Defaults to account root | | account | string | No | Account name (defaults to iCloud) | | format | string | No | Content format: "plaintext" (default) or "html". In both formats, the title is automatically prepended as . In plaintext mode, newlines become , tabs become `, and backslashes are preserved as HTML entities |
Example:
{
"title": "Meeting Notes",
"content": "Discussed Q4 roadmap and budget allocation",
"tags": ["work", "meetings"]
}
Example - Create in a specific folder:
{
"title": "Client Meeting",
"content": "Discussed project timeline",
"folder": "Work/Clients"
}
Example - HTML formatting:
{
"title": "Status Report",
"content": "SummaryAll tasks on track.Feature A: completeFeature B: in progress",
"format": "html"
}
> Note: The title is automatically prepended as ` in both plaintext and HTML formats. Do not include a title tag in the content` parameter, or the title will appear twice.
Returns: Confirmation message with note title and ID. Save the ID for subsequent operations like update-note, delete-note, etc.
search-notes
Searches for notes by title or content.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | query | string | Yes | Text to search for | | searchContent | boolean | No | If true, searches note body; if false (default), searches titles only | | account | string | No | Account to search in (defaults to iCloud) | | folder | string | No | Limit search to a specific folder (supports nested paths like "Work/Clients") | | modifiedSince | string | No | ISO 8601 date string to filter notes modified on or after this date (e.g., "2025-01-01") | | limit | number | No | Maximum number of results to return |
Example - Search titles:
{
"query": "meeting"
}
Example - Search content:
{
"query": "budget allocation",
"searchContent": true
}
Example - Search recent notes with limit:
{
"query": "todo",
"searchContent": true,
"modifiedSince": "2025-01-01",
"limit": 10
}
Returns: List of matching notes with titles, folder names, and IDs. Use the returned ID for subsequent operations like get-note-content, update-note, etc.
get-note-content
Retrieves the full content of a specific note.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | No | Note ID (preferred - more reliable than title) | | title | string | No | Note title (use id instead when available) | | account | string | No | Account containing the note (defaults to iCloud, ignored if id is provided) |
Note: Either id or title must be provided. Using id is recommended as it's unique and avoids issues with duplicate titles.
Example - Using ID (recommended):
{
"id": "x-coredata://ABC123/ICNote/p456"
}
Example - Using title:
{
"title": "Shopping List"
}
Returns: The HTML content of the note, or error if not found. The structuredContent also includes hashtags — any inline #hashtag tags parsed from the body. Apple Notes tags are inline hashtags, not a scriptable property; see [docs/APPLESCRIPT-LIMITATIONS.md](../docs/APPLESCRIPT-LIMITATIONS.md#tags--hashtags-29). Smart Folders are not scriptable.
get-note-plaintext
Retrieves a note's body as plain text, with no HTML markup.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | No | Note ID (preferred - more reliable than title) | | title | string | No | Note title (use id instead when available) | | account | string | No | Account containing the note (defaults to iCloud, ignored if id is provided) |
Note: Either id or title must be provided. This reads the note's native plaintext property, so it skips the HTML-to-text conversion that get-note-content plus a Markdown pass would do. Use get-note-content when you need the HTML, or get-note-markdown when you want Markdown with checklist state.
Returns: The plain-text content of the note in structuredContent.plaintext, or error if not found.
get-note-details
Retrieves metadata about a note (without full content).
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | title | string | Yes | Exact title of the note | | account | string | No | Account containing the note (defaults to iCloud) |
Example:
{
"title": "Project Plan"
}
Returns: JSON with note metadata:
{
"id": "x-coredata://...",
"title": "Project Plan",
"created": "2025-01-15T10:30:00.000Z",
"modified": "2025-01-20T14:22:00.000Z",
"shared": false,
"passwordProtected": false,
"account": "iCloud"
}
get-note-by-id
Retrieves a note using its unique CoreData identifier.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | Yes | The CoreData URL identifier (e.g., x-coredata://...) |
Returns: JSON with note metadata, or error if not found.
show-note
Reveals a note in Notes.app using its unique CoreData identifier.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | Yes | The CoreData URL identifier (e.g., x-coredata://...) | | separately | boolean | No | Open in a separate note window when supported by Notes.app |
Returns: Confirmation that Notes.app accepted the show command.
update-note
Updates an existing note's content and/or title.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | No | Note ID (preferred - more reliable than title) | | title | string | No | Current title of the note to update (use id instead when available) | | newTitle | string | No | New title (if changing the title; ignored when format is "html") | | newContent | string | Yes | New content for the note body | | account | string | No | Account containing the note (defaults to iCloud, ignored if id is provided) | | 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) |
Note: Either id or title must be provided. Using id is recommended.
Example - Using ID (recommended):
{
"id": "x-coredata://ABC123/ICNote/p456",
"newContent": "Updated content here"
}
Example - Update content only:
{
"title": "Shopping List",
"newContent": "- Milk\n- Eggs\n- Bread\n- Butter"
}
Example - Update title and content:
{
"title": "Draft",
"newTitle": "Final Version",
"newContent": "This is the completed document."
}
Example - Update with HTML formatting:
{
"id": "x-coredata://ABC123/ICNote/p456",
"newContent": "New findings with bold emphasis.console.log('hello');",
"format": "html"
}
Returns: Confirmation message, or error if note not found.
Note: newContent replaces the entire note body — it is not appended. To preserve existing content, read it first (e.g. with get-note-content) and include it in newContent.
Attachments: A full-body replace can drop embedded files, images, scans, PDFs, or audio. When a note may hold attachments, run [list-attachments](#list-attachments) first, and either save them with save-attachment or build a new note rather than overwriting. See the skill's [Attachment-Safe Updates](skills/apple-notes/SKILL.md#attachment-safe-updates) guidance.
delete-note
Deletes a note (moves to Recently Deleted in Notes.app).
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | No | Note ID (preferred - more reliable than title) | | title | string | No | Exact title of the note to delete (use id instead when available) | | account | string | No | Account containing the note (defaults to iCloud, ignored if id is provided) |
Note: Either id or title must be provided. Using id is recommended.
Example - Using ID (recommended):
{
"id": "x-coredata://ABC123/ICNote/p456"
}
Example - Using title:
{
"title": "Old Draft"
}
Returns: Confirmation message, or error if note not found.
⚠️ Safety: Irreversible from the agent's side — requires explicit user confirmation before calling. Prefer search-notes / list-notes first to confirm the exact id(s) being deleted.
move-note
Moves a note to a different folder.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | No | Note ID (preferred - more reliable than title) | | title | string | No | Title
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sweetrb
- Source: sweetrb/apple-notes-mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.