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 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