applenotes-mcp
An MCP server for Apple Notes that creates, reads, edits, and searches notes with proper formatting (headings, lists, tables, checklists) and file attachments.
README
applenotes-mcp
An MCP server for Apple Notes that writes properly formatted notes with support for headings, bulleted and numbered lists, tables, ticked checklists, and file attachments (images, PDFs).
Why this exists
Other Apple Notes MCP servers drive Notes using AppleScript, and this results in
a number of significant limitations. Writing a note through AppleScript requires
handing HTML to Notes' importer which ignores the styling and bakes
explicit inline font sizes onto everything it produces.
Headings are bold spans rather than real headings, font sizes are wrong, and tables,
checklists, and attachments cannot be created. Better HTML does not help: for example
an explicit 13px is rewritten to 11px by the importer.
This MCP uses Shortcuts.app instead as the method of writing. Its built-in Make Rich Text from Markdown action produces a properly attributed string, and Notes' Append to Note App Intent ingests that natively, avoiding the HTML importer. Notes written this way contain proper formatting.
Using Shortcuts also lets us write the things that AppleScript does not (checklists, attachments, tables...)
Requirements
Developed and tested on macOS 26.5. The minimum version is not known because it depends on which Notes App Intents are present (in particular Set Checklist Items Checked, which Apple doesn't even list in the Shortcuts action library...).
You also need Python 3.13+ and uv.
Permissions
Two macOS permissions must be granted to whichever application runs the server - which is generally your terminal or the Claude Desktop app (i.e. not to Python or to Notes.app).
- Full Disk Access (System Settings → Privacy & Security → Full Disk Access). Reading
is done straight from Notes' own store at
~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite, which is protected. Without it the server still runs but degraded.read_notefalls back to AppleScript HTML, andedit_notewill refuse to edit. - Automation → Notes (System Settings → Privacy & Security → Automation). Prompted for
on the first
osascriptcall.
Setup
uv sync
Register with Claude Code:
claude mcp add applenotes -- uv run --directory /path/to/applenotes_mcp applenotes-mcp
On first use the server generates and signs the bridge shortcut and asks you to import it. This is a one-time confirmation that Shortcuts cannot be automated around: open the file it names and click Add Shortcut, then retry. The same happens if you later update the server and the installed shortcut falls behind — delete the old one and import the new.
Tools
| Tool | Purpose |
|---|---|
create_note(title, markdown, folder?) |
Create a formatted note, attachments and all. Returns its ID. |
read_note(note_id) |
Read a note back as markdown. |
edit_note(note_id, markdown, title?) |
Replace a note's body. Destructive — see below. |
search_notes(query) |
Find notes by title. Returns id<TAB>title<TAB>folder<TAB>modified<TAB>snippet. |
search_note_text(query) |
Full-text search over title and body. Same rows as search_notes. |
list_folders() |
The folders a note can be filed into, as full paths. |
list_folder(folder) |
Browse one folder: its notes (newest first) and immediate subfolders. |
create_folder(path) |
Create a folder, making any missing parents. create_note still refuses unknown folders. |
The tools are annotated (readOnlyHint, destructiveHint) and the server contains instructions to explain the tools to your model.
Limitations
Editing is destructive. Due to a variety of Apple-based limitations, editing involves reading the source note, creating an edited copy, and deleting the original. This means that:
- the note gets a new internal ID and a new creation date
- this messes up Shared Notes
If the note's structure cannot be properly read from NoteStore then the edit is
refused rather than run from the degraded HTML. Still, every edit writes a JSON
backup to ~/.local/share/applenotes-mcp/backups/ first, and
the original also lands in Notes' Recently Deleted for 30 days so if anything goes wrong
then you can just fish it out of the bin.
Heading depth is flattened below level 3. Apple's markdown converter maps # to Notes'
Title style and ## to its Heading style, both of which round trip intact. ### maps
to Heading as well — Notes has a Subheading style (style_type 2) but the converter
never emits it so ### Foo reads back as ## Foo.
Links gain a trailing slash. Notes.app normalises a bare-host URL, so
https://example.com comes back as https://example.com/.
Any highlighted text will revert back to normal text. It is possible to read the highlighting out of the note store, but there is no way through either Shortcuts or HTML to write a highlight.
Attachments show as "PDF Document" (or "Image", etc.), not a title. Notes shows the tile
title from an attachment's ZTITLE field, which it only populates when you add a file through
its own UI. Nothing in the automation surface can set it: the Add File to Note intent leaves
it empty (its name parameter sets only the media filename, which Notes does not display),
there is no rename intent, the attachment entity's name is not writable, and AppleScript cannot
even see intent-created attachments. Attachment display size, by contrast, is settable — so
label attachments by the surrounding note text.
Tests
uv sync
uv run pytest
This will test all the normal code logic, renderers, AppleScript use etc. The test
suite also includes tests/fixtures/*.zdata which are real note protobufs that Notes.app
itself wrote, paired with the AppleScript HTML and the expected markdown.
These can be regenerated with uv run python tests/capture_fixtures.py, which
writes .actual files that you then promote to .expected by hand if everything looks correct.
The suite also includes a set of live round trips which test the entire flow. These create
and delete real notes, so they are off by default. Everything happens in a dedicated
MCP Live Tests folder, which must exist and be empty before the tests start.
APPLENOTES_MCP_LIVE=1 uv run pytest -m live
Both live and APPLENOTES_MCP_LIVE must be set and both are checked before testing starts.
Licence
MIT — see LICENSE.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。