apple-notes-mcp

mcp
Security Audit
Fail
Health Pass
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 14 GitHub stars
Code Fail
  • execSync — Synchronous shell command execution in scripts/jxa-comparison.ts
  • rm -rf — Recursive force deletion command in src/services/appleNotesManager.test.ts
Permissions Pass
  • Permissions — No dangerous permissions requested
Purpose
This MCP server bridges AI assistants like Claude with the native macOS Apple Notes app. It enables users to create, read, search, and manage their local notes using natural language commands.

Security Assessment
The overall risk is rated as Medium. Because this tool is designed to interact directly with personal notes, it inherently accesses potentially sensitive user data, though all processing stays local on the machine. The automated scan flagged two notable code findings: synchronous shell command execution and a recursive force deletion command (`rm -rf`). However, these instances appear within a test file and a script comparison file rather than the core application code. The server relies on AppleScript to control the Notes app, which will correctly trigger macOS's native permission prompts. No dangerous permissions are requested, and no hardcoded secrets or suspicious network requests were found.

Quality Assessment
The project appears to be healthy and actively maintained, with repository pushes happening as recently as today. It uses the permissive MIT license and includes CI pipelines for automated testing. While the community is still small at 14 GitHub stars, the documentation is thorough, providing clear installation instructions and outlining exactly what the tool requires to function.

Verdict
Use with caution: the tool is actively maintained and respects local data boundaries, but users should be aware it requires granting operating system-level access to their personal notes.
SUMMARY

MCP server for Apple Notes - create, search, update, and manage notes via Claude and other AI assistants

README.md

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.

npm version
CI
License: MIT

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.

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
Batch Operations Delete or move multiple notes at once
Checklist State Read checklist done/undone state directly from the Notes database
Export Export all notes as JSON or get individual notes as Markdown
Attachments List attachments in notes
Sync Awareness Detect iCloud sync in progress, warn about incomplete results
Collaboration Detect shared notes, warn before modifying
Diagnostics Health check, sync status, and statistics tools

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 <h1> — 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 <h1>. In plaintext mode, newlines become <br>, tabs become <br>, 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": "<h2>Summary</h2><p>All tasks <b>on track</b>.</p><ul><li>Feature A: complete</li><li>Feature B: in progress</li></ul>",
  "format": "html"
}

Note: The title is automatically prepended as <h1> in both plaintext and HTML formats. Do not include a <h1> 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.


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.


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": "<p>New findings with <b>bold</b> emphasis.</p><pre><code>console.log('hello');</code></pre>",
  "format": "html"
}

Returns: Confirmation message, or error if note not found.


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.


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 of the note to move (use id instead when available)
folder string Yes Destination folder name or nested path (e.g., "Work/Clients")
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",
  "folder": "Archive"
}

Example - Using title:

{
  "title": "Completed Task",
  "folder": "Archive"
}

Returns: Confirmation message, or error if note or folder not found.

Note: This operation copies the note to the new folder then deletes the original. If the delete fails, the note will exist in both locations.


list-notes

Lists all notes, optionally filtered by folder, date, and limit.

Parameter Type Required Description
account string No Account to list notes from (defaults to iCloud)
folder string No Filter to notes in this folder only (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 notes to return

Example - All notes:

{}

Example - Notes in a folder:

{
  "folder": "Work"
}

Example - Recent notes with limit:

{
  "modifiedSince": "2025-06-01",
  "limit": 20
}

Returns: List of note titles.


Folder Operations

list-folders

Lists all folders in an account with full hierarchical paths.

Parameter Type Required Description
account string No Account to list folders from (defaults to iCloud)

Example:

{}

Returns: List of folder paths. Nested folders are shown as full paths (e.g., Work/Clients/Omnia). Duplicate folder names are disambiguated by their full path. Literal slashes in folder names are escaped as \/ (e.g., Spain\/Portugal 2023).


create-folder

Creates a new folder.

Parameter Type Required Description
name string Yes Name for the new folder
account string No Account to create folder in (defaults to iCloud)

Example:

{
  "name": "Work Projects"
}

Returns: Confirmation message, or error if folder already exists.


delete-folder

Deletes a folder.

Parameter Type Required Description
name string Yes Name or path of the folder to delete (supports nested paths like "Work/Old")
account string No Account containing the folder (defaults to iCloud)

Example:

{
  "name": "Old Projects"
}

Returns: Confirmation message, or error if folder not found or not empty.


Account Operations

list-accounts

Lists all configured Notes accounts.

Parameters: None

Example:

{}

Returns: List of account names (e.g., "iCloud", "Gmail", "Exchange").


Batch Operations

batch-delete-notes

Deletes multiple notes at once by ID.

Parameter Type Required Description
ids string[] Yes Array of note IDs to delete

Returns: Summary of successes and failures.


batch-move-notes

Moves multiple notes to a folder.

Parameter Type Required Description
ids string[] Yes Array of note IDs to move
folder string Yes Destination folder name or nested path (e.g., "Work/Clients")
account string No Account containing the folder

Returns: Summary of successes and failures.


Export Operations

export-notes-json

Exports all notes as a JSON structure.

Parameters: None

Returns: Complete JSON export with all accounts, folders, and notes including metadata.


get-note-markdown

Gets a note's content as Markdown instead of HTML. If the note contains checklists and Full Disk Access is granted, checklist items are automatically annotated with [x] (done) or [ ] (undone).

Parameter Type Required Description
id string No Note ID (preferred)
title string No Note title
account string No Account containing the note

Returns: Note content converted to Markdown format. Checklist items include [x]/[ ] prefixes when database access is available.


get-checklist-state

Reads checklist done/undone state for a note. This bypasses the AppleScript limitation where body of note strips checklist state, by reading directly from the NoteStore SQLite database.

Requires: Full Disk Access for the MCP host process (see Full Disk Access Setup).

Parameter Type Required Description
id string Yes Note ID (use search-notes to find it first)

Example:

{
  "id": "x-coredata://ABC123/ICNote/p456"
}

Returns: Checklist items with done/undone state and progress count:

Checklist for "Shopping List" (2/4 done):
[x] Buy milk
[x] Get bread
[ ] Pick up laundry
[ ] Call dentist

list-attachments

Lists attachments in a note.

Parameter Type Required Description
id string No Note ID (preferred)
title string No Note title
account string No Account containing the note

Returns: List of attachments with names and content types.


Diagnostics

health-check

Verifies Notes.app connectivity and permissions.

Parameters: None

Returns: Status of all health checks (app installed, permissions, account access).


get-notes-stats

Gets comprehensive statistics about your notes.

Parameters: None

Returns: Total counts, per-account breakdown, folder statistics, and recently modified counts.


get-sync-status

Checks iCloud sync status.

Parameters: None

Returns: Whether sync is active, pending uploads, and last activity time.


list-shared-notes

Lists all notes shared with collaborators.

Parameters: None

Returns: List of shared notes with warnings about collaboration.


Usage Patterns

Basic Workflow

User: "Create a note called 'Todo' with my tasks for today"
AI: [calls create-note with title="Todo", content="Tasks for today..."]
    "I've created a note called 'Todo' with your tasks."

User: "What notes do I have?"
AI: [calls list-notes]
    "You have 15 notes: Todo, Shopping List, Meeting Notes..."

User: "Show me the Shopping List"
AI: [calls get-note-content with title="Shopping List"]
    "Here's your shopping list: - Milk - Eggs - Bread..."

Working with Accounts

By default, all operations use iCloud. To work with other accounts:

User: "What accounts do I have?"
AI: [calls list-accounts]
    "You have 3 accounts: iCloud, Gmail, Exchange"

User: "List notes in my Gmail account"
AI: [calls list-notes with account="Gmail"]
    "Your Gmail account has 5 notes..."

Organizing with Folders

User: "Create a folder called 'Archive'"
AI: [calls create-folder with name="Archive"]
    "Created folder 'Archive'"

User: "Move my old meeting notes to Archive"
AI: [calls move-note with title="Old Meeting Notes", folder="Archive"]
    "Moved 'Old Meeting Notes' to 'Archive'"

User: "What folders do I have?"
AI: [calls list-folders]
    "You have 5 folders: Work, Work/Clients, Work/Clients/Omnia, Archive, Recipes"

User: "Create a note in Work/Clients about Acme Corp"
AI: [calls create-note with title="Acme Corp", content="...", folder="Work/Clients"]
    "Created 'Acme Corp' in Work/Clients"

Installation Options

npm (Recommended)

npm install -g github:sweetrb/apple-notes-mcp

From Source

git clone https://github.com/sweetrb/apple-notes-mcp.git
cd apple-notes-mcp
npm install
npm run build

If installed from source, use this configuration:

{
  "mcpServers": {
    "apple-notes": {
      "command": "node",
      "args": ["/path/to/apple-notes-mcp/build/index.js"]
    }
  }
}

Full Disk Access for Checklist Features

The get-checklist-state tool and checklist annotations in get-note-markdown read directly from the Apple Notes SQLite database. This requires Full Disk Access for the process running the MCP server.

How to Grant Full Disk Access

  1. Open System Settings (or System Preferences on older macOS)
  2. Go to Privacy & Security > Full Disk Access
  3. Click the + button
  4. Add the application that hosts the MCP server:
    • Claude Desktop: Add /Applications/Claude.app
    • Terminal: Add /Applications/Utilities/Terminal.app
    • VS Code: Add /Applications/Visual Studio Code.app
    • iTerm: Add /Applications/iTerm.app
  5. Restart the application after granting access

Without Full Disk Access

All other tools work normally without Full Disk Access. Only checklist state features are affected:

  • get-checklist-state will return an error explaining that database access is needed
  • get-note-markdown will return plain list items without [x]/[ ] annotations (graceful fallback)

Security and Privacy

  • Local only - All operations happen locally via AppleScript. No data is sent to external servers.
  • Permission required - macOS will prompt for automation permission on first use.
  • Password-protected notes - Notes with passwords cannot be read or modified via this server.
  • No credential storage - The server doesn't store any passwords or authentication tokens.

Known Limitations

Limitation Reason
macOS only Apple Notes and AppleScript are macOS-specific
No attachment content Attachments can be listed but not downloaded via AppleScript
No pinned notes Pin status is not exposed via AppleScript
Limited rich formatting Use format: "html" on create/update for headings, lists, bold, code blocks; some complex formatting may not render
Title matching Most operations require exact title matches
Checklist state Requires Full Disk Access to read done/undone state from the database

Backslash Escaping (Important for AI Agents)

When sending content containing backslashes (\) to this MCP server, you must escape them as \\ in the JSON parameters.

Why: The MCP protocol uses JSON for parameter passing. In JSON, a single backslash is an escape character. To include a literal backslash in content, it must be escaped as \\.

Example - Shell command with escaped path:

{
  "title": "Install Script",
  "content": "cp ~/Library/Mobile\\\\ Documents/file.txt ~/.config/"
}

The \\\\ in JSON becomes \\ in the actual string, which represents a single \ in the note.

Common patterns requiring escaping:

  • Shell escaped spaces: Mobile\ DocumentsMobile\\\\ Documents in JSON
  • Windows paths: C:\Users\C:\\\\Users\\\\ in JSON
  • Regex patterns: \d+\\\\d+ in JSON

If you see errors when creating/updating notes with backslashes, double-check that backslashes are properly escaped in the JSON payload.


Troubleshooting

"Notes.app not responding"

  • Ensure Notes.app is not frozen
  • Try opening Notes.app manually
  • Restart the MCP server

"Permission denied"

  • macOS needs automation permission
  • Go to System Preferences > Privacy & Security > Automation
  • Ensure your terminal/Claude has permission to control Notes

"Note not found"

  • Note titles must match exactly (case-sensitive)
  • Check if the note is in a different account
  • Use list-notes to see available notes

Note creation/update fails silently with backslashes

  • Content containing \ characters requires JSON escaping
  • Use \\ to represent each literal backslash
  • See "Backslash Escaping" section under Known Limitations

Development

npm install      # Install dependencies
npm run build    # Compile TypeScript
npm test         # Run test suite (310 tests)
npm run lint     # Check code style
npm run format   # Format code

Author

Rob Sweet - President, Superior Technologies Research

A software consulting, contracting, and development company.

License

MIT License - see LICENSE for details.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Related Projects

Reviews (0)

No results found