apple-notes-reminders-mcp
apple-notes-reminders-mcp
Сервер MCP (Model Context Protocol), который предоставляет доступ к Apple Notes и Apple Reminders для MCP-совместимых клиентов (например, Claude Desktop) на macOS.
Что он делает
Сервер регистрирует набор инструментов для чтения и записи заметок и напоминаний. Инструменты для заметок охватывают создание списков, поиск (включая распознанный текст внутри вложенных изображений), чтение, создание, обновление, перемещение и удаление заметок и папок, а также теги, закрепленный статус, вложенные изображения и недавно удаленные. Инструменты для напоминаний охватывают аналогичные операции, а также подзадачи, пакетное создание, завершение, сроки выполнения, флаги, повторение, оповещения по местоположению/заранее, сохраненные представления фильтров, шаблоны и массовые фильтры на основе слов.
Related MCP server: apple-reminders-mcp
Архитектура
Две области читаются и записываются через разные механизмы:
Чтение осуществляется через SQLite, где это возможно. Заметки читаются напрямую из базы данных NoteStore на диске:
~/Library/Group Containers/group.com.apple.notes/NoteStore.sqliteБаза данных копируется во временное место и открывается только для чтения, поэтому живое хранилище никогда не затрагивается и не блокируется. Тела заметок хранятся в виде сжатого gzip protobuf-блобa в ZICNOTEDATA.ZDATA; декодер распаковывает его и детерминированно навигирует по структуре protobuf для извлечения текста и метаданных форматирования.
Запись осуществляется через AppleScript (osascript). База данных NoteStore принадлежит Notes.app и не может быть безопасно записана извне, поэтому операции создания/обновления/удаления/перемещения делегируются Notes.app через AppleScript. Подзадачи напоминаний также используют AppleScript, поскольку публичный API EventKit не предоставляет к ним доступа.
Декодирование тела заметки
Правильное чтение тела заметки — тонкая часть этого проекта. Тело — не обычный текст; это protobuf-сообщение внутри сжатого gzip блоба. Декодер:
Распаковывает
ZDATAи детерминированно навигирует к сообщению текста заметки (document → field 2 → field 3), затем читает строку текста (field 2). Это заменило более раннюю эвристику, которая сканировала «самый чистый» кандидат строки и возвращала поврежденный двоичный код для заметок, содержащих контрольные списки.Проходит по повторяющимся метаданным абзацев для каждого диапазона, чтобы обнаружить элементы контрольного списка и их состояние выполнено/не выполнено, добавляя префикс
- [x]для отмеченных элементов и- [ ]для неотмеченных.
Две детали важны для корректности:
Varints накапливаются с умножением (
* 2 ** shift), а не оператором<<, потому что побитовый сдвиг JavaScript усекается до 32 бит и повреждает большие смещения.Длины диапазонов измеряются в кодовых единицах UTF-16, что соответствует тому, как Apple их хранит, поэтому маркеры контрольных списков остаются выровненными, даже если текст содержит многобайтовые символы или эмодзи.
Если декодирование SQLite по какой-либо причине не удается, notes_get возвращается к чтению тела заметки через AppleScript, который возвращает чистый текст, но не может восстановить состояние флажков (свойство body AppleScript от Apple не кодирует его).
Вложения
Вложенные изображения читаются из строк ICAttachment/ICMedia таблицы ZICCLOUDSYNCINGOBJECT (разрешаются динамически через Z_PRIMARYKEY/Z_ENT, а не жестко закодированы, поскольку числовые идентификаторы сущностей и имена столбцов ZACCOUNT*/ZPARENT меняются в разных версиях macOS). Фактический файл находится на диске по адресу:
~/Library/Group Containers/group.com.apple.notes/Accounts/{account}/Media/{media id}/{generation}/{filename}notes_get возвращает идентификатор, имя файла, тип, разрешенный путь к файлу и любой распознанный OCR-текст каждого вложения; notes_get_attachment извлекает вложение изображения как блок содержимого изображения MCP. notes_search включает OCR-текст в корпус поиска, поэтому текст, который появляется только внутри скриншота, можно найти. Добавление вложения не поддерживается — см. «Известные ограничения» ниже.
Свойство flagged напоминаний и другие чтения только через AppleScript
Публичный API EventKit не имеет свойства flagged, поэтому оно полностью читается и записывается через AppleScript и объединяется в объекты Reminder, полученные из EventKit, по идентификатору. Полноценное сканирование флагов всей библиотеки относительно медленное (накладные расходы IPC AppleScript на каждое свойство), поэтому reminders_list/reminders_search включают flagged только при ограничении одним списком; используйте reminders_query_where/reminders_view с явным фильтром flagged, когда это нужно для всех списков.
Кэширование
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 запросит его при первом использовании, или предоставьте его в Системных настройках › Конфиденциальность и безопасность › Автоматизация
Полный доступ к диску: требуется для хост-приложения, чтобы читать базу данных NoteStore по адресу
~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite— предоставьте его в Системных настройках › Конфиденциальность и безопасность › Полный доступ к диску
Примечания к версиям macOS
Имена столбцов и числовые идентификаторы сущностей внутри ZICCLOUDSYNCINGOBJECT меняются в разных версиях macOS/Notes.app (например, ZACCOUNT1–ZACCOUNT8 все наблюдались как активный внешний ключ папка→учетная запись в разных системах, а значения Z_ENT для ICAccount/ICAttachment/ICMedia нестабильны). detectSchema() в notesStore.ts повторно обнаруживает их при каждом промахе кэша, а не жестко кодирует — см. комментарии там, прежде чем жестко кодировать новое имя столбца. Разработано и протестировано на 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`)Шаблоны напоминаний и сохраненные представления фильтров (reminders_save_template, reminders_save_view) хранятся в виде JSON в ~/.apple-notes-reminders-mcp/ — для них нет серверной базы данных, поскольку EventKit не имеет такой концепции.
Примечания о разрешениях и конфиденциальности
Все чтения выполняются локально с временной копии локальной базы данных NoteStore. Сам сервер ничего не отправляет с устройства. Сервер требует тот же доступ, который пользователь уже имеет к своим собственным заметкам и напоминаниям.
Тестирование
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, граничные случаи контрольных списков, фикстуры полного конвейера закрепленных) являются самодостаточными; его последний раздел «Real DB notes» и весь test-schema-detection.mjs читают реальную, живую базу данных Notes и пройдут только при наличии полного доступа к диску и реальных данных заметок — ожидайте сбоев/ошибок там на машине, отличной от машины оригинального автора (раздел БД test-phase2.mjs конкретно ссылается на идентификаторы заметок, которые существуют только в этой одной библиотеке).
Известные ограничения
Перемещение папки в другую папку не реализовано. Подтверждено вживую, что AppleScript
move <folder> to <folder>в Notes.app ненадежен — он периодически выдает ошибку (item N of every folder kan niet worden opgevraagd) или молча ничего не делает, независимо от того, получена ли ссылка на папку черезfolder id, фильтрwhoseили ручное сканирование. Переименование и удаление папки надежны и реализованы; перемещение одной папки под другую не реализовано, поскольку выпуск инструмента, который работает непредсказуемо, хуже, чем его отсутствие. Переименование/удаление вложенной папки (созданной через интерфейс Notes.app, а не этим сервером) поддерживается — передайте ее полный путь"Родитель/Дочерняя".Невозможно добавить вложение через этот сервер. Чтение вложений полностью поддерживается (см. выше). Добавление требует интерфейса Notes.app — был исследован мост на основе Shortcuts-CLI (
shortcuts run <name> -i <path>), но он оказался непригодным в качестве инструмента с нулевой настройкой: он принимает ровно один входной файл без возможности также передать целевую заметку, а CLIshortcutsможет запустить только уже существующий ярлык, а не создать новый. См. комментарий в началеnotes.tsдля полного описания.Транскрипции аудио не отображаются. OCR-текст из вложенных изображений отображается (
notes_get,notes_search). В БД также есть столбец, похожий на аудиотранскрипцию (ZTEMPORARYTRANSCRIPTDATA), но это непрозрачный блоб, и для обратного проектирования его формата не было доступных аудиовложений — оставлено для будущего участника, у которого есть реальные фикстурные данные.Удаленная папка может исчезать из
notes_list_foldersболее минуты. Подтверждено вживую: само удаление мгновенно в Notes.app (и мгновенно видно в AppleScript), но флаг мягкого удаления строки SQLite может задерживаться на 60+ секунд, по-видимому, в ожидании кругового пути синхронизации iCloud — намного дольше, чем типичная задержка SQLite в ~5 секунд, наблюдаемая для переименований/созданий в других местах. Этот сервер не может это сократить; задокументировано вnotesStore.tsдля тех, кто ищет то, что выглядит как ошибка кэширования.«Умные папки» (оригинальная формулировка PLAN) на самом деле не существуют как общая функция Notes.app так, как они есть в Reminders —
ZFOLDERTYPE=1в БД отличает только встроенную папку «Недавно удаленные» от обычных. Поддержка только для чтения этого флага существует (isSmartFolderвnotes_list_folders); группировка по тегам (notes_list_tags) является более близким аналогом «сохраненного умного списка» для Notes.«Разделы списков» напоминаний (новая функция группировки Reminders.app) не читаются — EventKit их не предоставляет, и для этого потребовалось бы обратное проектирование отдельного хранилища на диске Reminders, что не было предпринято в этом проходе.
Инструменты
Заметки
Инструмент | Назначение |
| Список всех папок — id, имя, вложенный путь, учётная запись, флаг умной папки, количество заметок |
| Список заметок, опциональный фильтр по папке, с сортировкой и постраничным выводом (limit/offset) |
| Получить заметку по имени или id, включая метаданные вложений |
| Загрузить вложение-изображение как блок изображения MCP |
| Получить все заметки в папке с декодированным содержимым за один запрос, с сортировкой и постраничным выводом |
| Поиск по заголовку/тексту/OCR-тексту во всех папках, с сортировкой и постраничным выводом |
| Создать заметку (тело в формате markdown/html/text) |
| Обновить заметку (заменить/добавить в конец/в начало; защита от удаления вложений) |
| Удалить заметку |
| Создать папку |
| Переименовать папку (верхнего уровня или вложенную, по пути) |
| Удалить папку (её заметки перемещаются в «Недавно удалённые») |
| Переместить заметку в другую папку |
| Список |
| Список заметок в «Недавно удалённых» |
| Восстановить заметку из «Недавно удалённых» |
| Подсчёт/список заметок, соответствующих текстовому фильтру (папка, поиск, тег) |
| Массовое удаление соответствующих заметок (с подтверждением) |
| Массовое перемещение соответствующих заметок (с подтверждением) |
Напоминания
Инструмент | Назначение |
| Список всех списков напоминаний |
| Список напоминаний, опциональный фильтр по списку, с сортировкой и постраничным выводом |
| Получить напоминание по имени или id |
| Поиск напоминаний по имени/заметкам/списку |
| Умные списки в стиле Reminders.app: сегодня/запланировано/просрочено/срочно/с флагом/выполнено |
| Создать напоминание (дата на естественном языке, флаг, повторение, ранние/гео-уведомления) |
| Создать много напоминаний за один нативный вызов (одна фиксация в БД) |
| Обновить напоминание |
| Отметить как выполненное/невыполненное |
| Удалить напоминание |
| Создать список |
| Переименовать список |
| Удалить список и его напоминания |
| Добавить подзадачу (AppleScript — у EventKit нет публичного API для подзадач) |
| Завершить/восстановить подзадачу |
| Массовое удаление выполненных напоминаний, опционально в рамках списка |
| Подсчёт/список напоминаний, соответствующих текстовому фильтру |
| Массовое удаление соответствующих напоминаний (с подтверждением) |
| Массовое выполнение/отмена выполнения соответствующих напоминаний (с подтверждением) |
| Массовое перемещение соответствующих напоминаний в другой список (с подтверждением) |
| Сохранить именованный шаблон напоминания |
| Список сохранённых шаблонов |
| Удалить сохранённый шаблон |
| Создать напоминание из шаблона с возможностью переопределения параметров при вызове |
| Сохранить именованный текстовый фильтр как повторно используемое представление |
| Список сохранённых представлений |
| Удалить сохранённое представление |
| Запустить сохранённое представление и вернуть соответствующие напоминания |
This server cannot be deployed
Maintenance
Related MCP Connectors
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
Google Keep-style notes app with an MCP server for AI agents to read/write notes.
An MCP server that used to create notes
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn 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.59 npmMIT
- AlicenseAqualityBmaintenanceAn MCP server that enables LLM agents to list, read, create, update, delete, and search Apple Notes on macOS.620 npmAGPL 3.0
- FlicenseNot gradedqualityCmaintenanceAn MCP server that gives AI assistants access to your Apple Notes, Reminders, and Contacts — with optional BERT-powered semantic search.1-