apple-notes-reminders-mcp
apple-notes-reminders-mcp
一个 MCP(模型上下文协议)服务器,用于在 macOS 上向 MCP 兼容客户端(例如 Claude Desktop)开放 Apple Notes 和 Apple Reminders 功能。
功能
该服务器注册了一组工具,用于读写 Notes 和 Reminders。Notes 工具涵盖列出、搜索(包括图片附件中的识别文本)、读取、创建、更新、移动和删除笔记及文件夹,以及标签、置顶状态、图片附件和最近删除。Reminders 工具涵盖类似操作,还包括子任务、批量创建、完成、截止日期、标记、重复、位置/提前提醒、已保存筛选视图、模板和基于关键词的批量筛选。
Related MCP server: apple-reminders-mcp
架构
两个域通过不同的机制进行读写:
读取尽可能通过 SQLite 进行。笔记直接从磁盘上的 NoteStore 数据库中读取:
~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite数据库被复制到临时位置并以只读方式打开,因此不会触及或锁定在线存储。笔记正文以 gzip 压缩的 protobuf blob 存储在 ZICNOTEDATA.ZDATA 中;解码器将其解压并确定性地导航 protobuf 结构,以提取文本和格式化元数据。
写入通过 AppleScript (osascript) 进行。NoteStore 数据库归 Notes.app 所有,无法从外部安全写入,因此创建/更新/删除/移动操作通过 AppleScript 委托给 Notes.app。Reminders 子任务也使用 AppleScript,因为公共 EventKit API 不暴露它们。
笔记正文解码
正确读取笔记正文是该项目中较为精细的部分。正文不是纯文本——它是一个包含在 gzip blob 中的 protobuf 消息。解码器:
解压缩
ZDATA并确定性地导航到笔记文本消息(document → field 2 → field 3),然后读取文本字符串(field 2)。这取代了早期的一种启发式方法,该方法扫描“最干净”的字符串候选项,并在包含检查清单的笔记中返回损坏的二进制数据。遍历重复的按段落排列的元数据,以检测检查清单项及其完成/未完成状态,用
- [x]前缀标记已完成项,用- [ ]前缀标记未完成项。
有两个细节对于正确性很重要:
Varints 是通过乘法(
* 2 ** shift)而不是<<运算符累积的,因为 JavaScript 的按位移位会截断为 32 位并破坏大的偏移量。跨度长度以 UTF-16 代码单元测量,与 Apple 存储它们的方式匹配,因此即使文本包含多字节字符或表情符号,检查清单标记也能保持对齐。
如果 SQLite 解码因任何原因失败,notes_get 会退而通过 AppleScript 读取笔记正文,这返回干净的文本,但无法恢复复选框状态(Apple 的 AppleScript body 属性不编码它)。
附件
图片附件从 ZICCLOUDSYNCINGOBJECT 的 ICAttachment/ICMedia 行读取(通过 Z_PRIMARYKEY/Z_ENT 动态解析,不是硬编码的,因为数字实体 ID 和 ZACCOUNT*/ZPARENT 列名在 macOS 版本之间会变化)。实际文件位于磁盘上的:
~/Library/Group Containers/group.com.apple.notes/Accounts/{account}/Media/{media id}/{generation}/{filename}notes_get 返回每个附件的 ID、文件名、类型、解析后的文件路径以及任何识别的 OCR 文本;notes_get_attachment 将图片附件作为 MCP 图片内容块获取。notes_search 将 OCR 文本折叠到搜索语料库中,因此仅出现在屏幕截图中的文本也是可查找的。不支持添加附件——请参阅下面的“已知限制”。
Reminders 的 flagged 和其他 AppleScript 独占读取
EventKit 的公共 API 没有 flagged 属性,因此它完全通过 AppleScript 读取和写入,并通过 ID 合并到 EventKit 来源的 Reminder 对象中。整个库的标记扫描相对较慢(AppleScript 每个属性的 IPC 开销),因此 reminders_list/reminders_search 仅在限定到单个列表时才包含 flagged;当需要在所有列表中跨列表查询时,请使用带有显式 flagged 过滤器的 reminders_query_where/reminders_view。
缓存
notesStore.ts 缓存打开的 SQLite 连接、检测到的模式以及每个笔记的解码正文,所有这些都通过在每次调用时比较源文件(及其 -wal/-shm 附属文件)的修改时间来失效——对在线 NoteStore 的写入总是会破坏缓存,因此这纯粹是性能提升,没有过时风险。解码正文还额外以 (Z_PK, 修改日期) 作为键,因此编辑过的笔记会获得新的缓存条目,而不是过时的命中。
要求与权限
macOS(在 macOS 26 / Tahoe 上测试)
Node.js 18+(使用
better-sqlite3访问 SQLite)Notes.app 和 Reminders.app 已设置并登录到账户
自动化权限:主机应用程序(例如 Claude Desktop)必须被允许控制 Notes 和 Reminders——macOS 会在首次使用时提示,或者在系统设置 › 隐私与安全性 › 自动化中授予
完全磁盘访问权限:主机应用程序需要能够读取位于
~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite的 NoteStore 数据库——在系统设置 › 隐私与安全性 › 完全磁盘访问权限中授予
macOS 版本说明
ZICCLOUDSYNCINGOBJECT 内部的列名和数字实体 ID 会随 macOS/Notes.app 版本变化(例如,ZACCOUNT1 到 ZACCOUNT8 都曾在不同系统上被观察到作为实时文件夹→账户外键,而 ICAccount/ICAttachment/ICMedia 的 Z_ENT 值并不稳定)。notesStore.ts 的 detectSchema() 在每次缓存未命中时重新检测这些值,而不是硬编码任何一个——请参阅那里的注释,然后再硬编码新的列名。该项目针对 macOS 26 (Tahoe) 开发和测试;检测逻辑设计为兼容旧版本,但尚未验证。
安装
npm install
npm run build运行
npm start或者将 dist/index.js 注册为客户端配置中的 MCP 服务器命令。
项目布局
src/
index.ts MCP server + tool registrations
notes.ts Notes tool implementations (SQLite reads, AppleScript writes)
notesStore.ts NoteStore SQLite access + protobuf body decoder
reminders.ts Reminders tool implementations + local template/saved-view storage
applescript.ts Shared runAppleScript() helper (argv-only, never string-spliced)
markdown.ts Markdown -> Notes-compatible HTML converter
swift/
reminders-daemon.swift Persistent EventKit daemon (NDJSON over stdio)
scripts/
test-phase2.mjs Protobuf/checklist decoder tests (+ pinned full-pipeline fixtures)
test-markdown.mjs Markdown -> HTML converter tests
test-schema-detection.mjs Schema-detection sanity checks against the live DB
dist/ Compiled output (generated by `npm run build`)Reminder 模板和已保存的筛选视图(reminders_save_template、reminders_save_view)作为 JSON 存储在 ~/.apple-notes-reminders-mcp/ 下——服务器端没有用于这些的数据库,因为 EventKit 本身没有这样的概念。
关于权限和隐私的说明
所有读取操作都在本地针对本地 NoteStore 数据库的临时副本进行。服务器本身不会将任何内容发送出设备。服务器要求的访问权限与用户对自己 Notes 和 Reminders 已有的权限相同。
测试
npm run build && node scripts/test-phase2.mjs # protobuf/checklist decoder
npm run build && node scripts/test-markdown.mjs # markdown -> Notes-HTML converter
npm run build && node scripts/test-schema-detection.mjs # schema detection sanity (live DB)test-markdown.mjs 是完全确定性的。test-phase2.mjs 的单元测试部分(varint 安全性、检查清单边缘情况、置顶全管道夹具)是自包含的;其最后的“真实数据库笔记”部分以及整个 test-schema-detection.mjs 会读取真实的在线 Notes 数据库,并且只有在具有完全磁盘访问权限和实际笔记数据存在时才会通过——在其他机器上(除了原作者的那台)预期会出现失败/错误(test-phase2.mjs 的数据库部分特别引用了仅在那一个库中存在的笔记 ID)。
已知限制
文件夹重新父级化未实现。 已实机确认 Notes.app 的 AppleScript
move <folder> to <folder>不可靠——它间歇性地抛出错误(item N of every folder kan niet worden opgevraagd)或静默无操作,无论文件夹引用来自folder id、whose筛选器还是手动扫描。文件夹重命名和删除是可靠的并已实现;将某个文件夹重新父级化到另一个文件夹下则未实现,因为发布一个会不可预测地失败的工具比没有更糟糕。重命名/删除嵌套文件夹(通过 Notes.app 界面创建,而不是由本服务器创建)是支持的——传递其完整的"Parent/Child"路径。无法通过此服务器添加附件。 读取附件完全支持(见上文)。添加附件需要 Notes.app 界面——曾研究过基于 Shortcuts-CLI 的桥接(
shortcuts run <name> -i <path>),但发现作为零设置工具不可行:它只接受一个输入文件,无法同时传递目标笔记,并且shortcutsCLI 只能运行一个已存在的快捷指令,无法创建一个。请参阅notes.ts顶部的注释查看完整说明。音频转录不公开。 图片附件的 OCR 文本是公开的(
notes_get、notes_search)。数据库中也有一个类似于音频转录的列(ZTEMPORARYTRANSCRIPTDATA),但它是一个不透明的 blob,并且没有可用的音频附件来逆向工程其格式——留给将来有真实测试数据的贡献者处理。已删除的文件夹可能需要超过一分钟才能从
notes_list_folders中消失。 已实机确认:删除本身在 Notes.app 中是即时的(并且立即可见给 AppleScript),但 SQLite 行的软删除标志可能滞后 60 秒以上,似乎取决于 iCloud 同步往返——比通常在其他地方看到的重命名/创建的约 5 秒 SQLite 滞后长得多。这不是本服务器能缩短的;在notesStore.ts中已记录,供那些追查看似缓存错误的人参考。“智能文件夹” 作为 Reminders 所具有的通用 Notes.app 功能实际上并不存在——数据库中的
ZFOLDERTYPE=1仅区分内置的“最近删除”文件夹和普通文件夹。对此标志的只读支持存在(notes_list_folders上的isSmartFolder);基于标签的分组(notes_list_tags)对于 Notes 而言更接近“已保存的智能列表”。Reminders “列表分区”(一个较新的 Reminders.app 分组功能)不被读取——EventKit 不暴露它们,这样做意味着要逆向工程 Reminders 自己单独的磁盘存储,本轮未尝试。
工具
Notes
工具 | 用途 |
| 列出所有文件夹——ID、名称、嵌套路径、账户、智能文件夹标志、笔记数量 |
| 列出笔记,可选文件夹过滤,支持排序 + 分页(limit/offset) |
| 按名称或ID获取笔记,包含附件元数据 |
| 获取图片附件,作为MCP图像块 |
| 一次性读取文件夹中的所有笔记,解码正文,支持排序 + 分页 |
| 在所有文件夹中搜索标题/正文/OCR文本,支持排序 + 分页 |
| 创建笔记(markdown/html/文本正文) |
| 更新笔记(替换/追加/前置;附件安全防护) |
| 删除笔记 |
| 创建文件夹 |
| 重命名文件夹(顶级或嵌套,按路径) |
| 删除文件夹(其中的笔记移至“最近删除”) |
| 将笔记移动到其他文件夹 |
| 列出笔记中使用的 |
| 列出“最近删除”中的笔记 |
| 从“最近删除”中恢复笔记 |
| 按基于单词的过滤器(文件夹、搜索、标签)统计/列出笔记 |
| 批量删除匹配的笔记(需确认) |
| 批量移动匹配的笔记(需确认) |
提醒事项
工具 | 用途 |
| 列出所有提醒列表 |
| 列出提醒事项,可选列表过滤,支持排序 + 分页 |
| 按名称或ID获取提醒事项 |
| 按名称/备注/列表搜索提醒事项 |
| 提醒事项应用风格的智能列表:今天/已计划/逾期/紧急/已标记/已完成 |
| 创建提醒事项(自然语言截止日期、标记、重复、提前/位置提醒) |
| 在一次原生调用中创建多个提醒事项(单次数据库提交) |
| 更新提醒事项 |
| 标记为已完成/未完成 |
| 删除提醒事项 |
| 创建列表 |
| 重命名列表 |
| 删除列表及其提醒事项 |
| 添加子任务(AppleScript——EventKit 无公开子任务 API) |
| 完成/恢复子任务 |
| 批量删除已完成的提醒事项,可选限定范围到某个列表 |
| 按基于单词的过滤器统计/列出提醒事项 |
| 批量删除匹配的提醒事项(需确认) |
| 批量完成/恢复匹配的提醒事项(需确认) |
| 批量将匹配的提醒事项移动到其他列表(需确认) |
| 保存一个命名的提醒事项模板 |
| 列出已保存的模板 |
| 删除已保存的模板 |
| 从模板创建提醒事项,支持每次调用时覆盖参数 |
| 保存一个命名的基于单词的过滤器作为可复用视图 |
| 列出已保存的视图 |
| 删除已保存的视图 |
| 运行已保存的视图并返回匹配的提醒事项 |
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityCmaintenanceAn MCP server that enables AI assistants like Claude to access and manipulate Apple Notes on macOS, allowing for retrieving, creating, and managing notes through natural language interactions.82MIT
- AlicenseAqualityDmaintenanceAn MCP server that connects Claude Desktop to Apple Reminders on macOS via AppleScript.510MIT
- AlicenseAqualityBmaintenanceAn MCP server that enables LLM agents to list, read, create, update, delete, and search Apple Notes on macOS.611AGPL 3.0
- Flicense-qualityCmaintenanceAn MCP server that gives AI assistants access to your Apple Notes, Reminders, and Contacts — with optional BERT-powered semantic search.2
Related MCP Connectors
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
MCP connector for Apple Reminders — search, create, complete, and edit via your own Mac.
MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/martijnstegink/apple-notes-reminders-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server