Cupertino
Cupertino
Заставьте вашего агента работать в ваших повседневных приложениях Apple.
MCP-серверы для приложений Apple, уже установленных на вашем Mac, и подписанное приложение, которое выдаёт им разрешения один раз вместо каждого по отдельности — для любого агента, говорящего на MCP, а не для одного хоста.
Неофициально. Не связано с Apple. Эти серверы управляют приложениями, которые уже есть на вашем Mac.
В работе
Посмотри, как я пишу в рабочем почтовом ящике, затем составь этот ответ в том же стиле.
Собери всё о запуске Atlas из моей почты, заметок и календаря. Что я ещё должен людям?
Преврати пункты действий из вчерашней переписки с клиентом в напоминания со сроком до пятницы.
Каждый из них несёт ограничение — учётная запись, привязка к дате, фильтр. Именно эту часть
наивный osascript выполняет за 74 секунды или выполняет неверно, и именно поэтому сервер
оправдывает своё существование: он хранит то, что модель в противном случае пересобирала бы в каждой сессии. Измерения — в
docs/verify.md; альтернативы описаны в
docs/alternatives.md.
Последний требует открытого шлюза записи в Reminders. Запись отключена для каждой поверхности, пока вы её не включите, и этот переключатель определяет, зарегистрированы ли изменяющие инструменты вообще — агент с отключённой записью не увидит, что они существуют.
Related MCP server: apple-mcp
Поверхности
Поверхность | Пакет | Статус |
реализовано — 18 инструментов, поиск/чтение/вложения + запись под переключателем | ||
Notes | реализовано — 12 инструментов, поиск/чтение/вложения + запись под переключателем | |
Reminders | реализовано — 11 инструментов, списки/поиск/даты + запись под переключателем | |
Calendar | реализовано — 9 инструментов, диапазоны/поиск/повторения + запись под переключателем | |
Contacts | реализовано — 7 инструментов, преобразует идентификаторы в имена + запись под переключателем | |
Messages | реализовано — 6 инструментов, чаты/поиск/декодированный текст + отправка под переключателем | |
Safari | реализовано — 6 инструментов, история/вкладки/список для чтения, только чтение | |
— | общее: граница osascript, ошибки с учётом TCC, SQLite только для чтения |
Каждая поверхность — это отдельный сервер и отдельный npm-пакет, поэтому хост загружает только те инструменты, которые нужны. Все они используют один бандл и один грант Full Disk Access — именно поэтому они живут вместе — см. docs/distribution.md.
Быстрый старт
Каждый сервер есть в npm и запускается прямо через npx — для Claude Code достаточно .mcp.json рядом с вашим
проектом:
{
"mcpServers": {
"apple-mail": {
"command": "npx",
"args": ["-y", "@mgcrea/mcp-apple-mail"]
},
"apple-notes": {
"command": "npx",
"args": ["-y", "@mgcrea/mcp-apple-notes"]
}
}
}Пакеты распространяются по лицензии MIT и не требуют ключа. Что им действительно нужно — это разрешение, и в npm вы
выдаёте его тому, кто их запускает — вашему редактору, вашему терминалу, — и именно этой сделки призвано избежать подписанное
Cupertino.app: один грант Full Disk Access, удерживаемый
нотариально заверенным бинарником, вместо одного на каждый хост. См. docs/licensing.md.
Или запускайте из исходников:
git clone https://github.com/mgcrea/mcp-cupertino.git
cd mcp-cupertino
pnpm install
pnpm buildзатем укажите хосту абсолютный путь к packages/<surface>/dist/cli.js.
Запись отключена, пока вы её не запросите — см. Configuration.
Запуск через приложение в строке меню вместо этого направляет каждый сервер через мост, поэтому Full Disk Access выдаётся Cupertino, а не тому редактору, который породил сервер:
make run # build Cupertino.app, point it at packages/*/dist, launch it
make smoke # handshake every server through the bridgeВ репозитории есть готовый .mcp.json, настроенный на этот путь. make сам по себе перечисляет
все цели.
Обратите внимание на разные имена серверов. При ручной настройке, как описано выше, сервер называется apple-mail и работает под
тем грантом, который есть у его процесса-хоста. При настройке через Cupertino он называется cupertino-mail, потому что эта запись
указывает на мост приложения и работает под грантом приложения. Два имени для двух способов развёртывания, и вы можете
использовать оба. Приложение никогда не трогает чужие ключи cupertino-* — запись apple-mail,
принадлежащая другому серверу, остаётся нетронутой.
Cupertino — это конфигурация машины, а не зависимость проекта, поэтому она живёт в пользовательской конфигурации:
по одному файлу для Claude Desktop, Cursor, LM Studio и Windsurf, а для CLI — --scope user, —
именно это используют готовые команды приложения. Сознательно не --scope project, который записывает
.mcp.json в репозиторий — эта запись содержит абсолютный путь к бандлу на одном Mac,
подкреплённый грантом Full Disk Access одного человека, и была бы бесполезна для коллеги и неразумна
для них.
Какие клиенты получают запись, а какие — команду, зависит не от популярности. Приложение вносит изменения в конфигурацию
только когда это строгий JSON с серверами в mcpServers; у Visual Studio Code это JSONC,
а у Codex — TOML, и повторная сериализация любого из них удалила бы комментарии в файле, который ведётся
вручную. ~/.claude.json у Claude Code — строгий JSON, но в нём хранятся учётные данные, и параллельные сессии
пишут в него одновременно, так что изменение из строки меню могло бы затереть чужую правку.
Эти три клиента получают строку для вставки. ChatGPT отсутствует полностью: он принимает только удалённые HTTP-подключения и
вообще не умеет запускать локальный stdio-сервер.
Собственный .mcp.json в этом репозитории — исключение, и он намеренно называет серверы
cupertino-*-dev: он указывает на apps/apple/.build, так что при разработке у вас есть
dev-сборка и установленная рядом. Claude Code сообщает об одном и том же имени в двух
областях как о конфликте, а не выбирает одну, поэтому суффикс — это то, что позволяет сосуществовать обоим.
Cupertino.app требует macOS 26 или новее — его иконка — это Icon Composer-бандл, который ничто
старее не отрендерит. Сами серверы — обычный Node и не имеют такого ограничения; оно касается только приложения
в строке меню.
Разрешения
Два отдельных гранта macOS, и они достаются тому процессу, который запустил сервер — вашему редактору, вашему терминалу или Cupertino — но никогда Mail, Notes или Reminders.
Грант | Для чего нужен |
Full Disk Access | индексный путь: поиск по Mail, байты вложений |
Automation (для каждого приложения, с запросом) | путь Apple Events: учётные записи, почтовые ящики, все записи |
Contacts (с запросом) | поверхность Contacts — её хранилище не закрыто Full Disk Access |
System Settings → Privacy & Security → Full Disk Access → добавьте запускающее приложение и перезапустите его. Выдача гранта Mail.app ничего не даёт; разрешение нужно читающему процессу, а не Mail.
Что работает без Full Disk Access:
Поверхность | Без гранта |
учётные записи, почтовые ящики и только запись — поиск откатывается к Apple Events за ~74 с | |
Notes | полностью работоспособно примерно до 5 тысяч заметок; только байты вложений требуют гранта |
Reminders | работоспособно, но целодневные даты и подзадачи требуют хранилища — контейнер невозможно даже перечислить без него |
Calendar | ничего. Единственная поверхность без достаточно быстрого пути чтения через Apple Events, чтобы служить запасным — один запрос диапазона в 90 дней стоит 3,4 с, — поэтому каждое чтение требует гранта. Запись при этом работает. |
Contacts | ничего — но ей и не нужен Full Disk Access. Её хранилище закрыто отдельным разрешением Contacts, которое macOS запрашивает само, а не заставляет вас искать нужную панель настроек. Запись дополнительно требует Automation. |
Messages | вообще ничего. Пути чтения через Apple Events не существует — Messages отвечает «Application isn't running», даже когда запущено, — поэтому нет ни второго пути, ни урезанного режима. Отправку можно попытаться выполнить, но без хранилища, из которого можно выбрать получателя или с которым можно свериться, она обычно не может быть адресована вовсе. |
Safari | живые вкладки, и только они. Единственная поверхность, где пути — не запасные друг для друга: Apple Events видит то, что открыто сейчас, файловый путь видит всё остальное. История, закладки и список для чтения — всё требует гранта. |
Инструменты, которым нужен индекс, не исчезают, когда его нет, — список инструментов — чистая функция
allowWrites и больше ничего, потому что MCP-клиенты его кэшируют. Они возвращают структурированный результат degraded,
называющий, чего не хватает. apple_mail_diagnostics / apple_notes_diagnostics сообщают, какой путь
активен и как выдать недостающее.
Инструменты
Инструменты чтения регистрируются всегда. Инструменты записи невидимы, пока запись не включена — не просто отклоняются.
Всегда доступны | Под переключателем записи |
|
|
|
|
|
|
Notes
Всегда доступны | Под переключателем записи |
|
|
|
Reminders
Всегда доступно | Только запись |
|
|
|
Календарь
Всегда доступно | Только запись |
|
|
|
list_events разворачивает повторяющиеся события, поэтому еженедельный стендап возвращается один раз в неделю. Каждый результат
несёт окно, для которого известно развёртывание, и устанавливает truncated, когда диапазон выходит за его пределы,
а не возвращает короткий список — короткий список событий неотличим от свободного дня.
Контакты
Всегда доступно | Только запись |
|
|
|
resolve_handles превращает номера телефонов и адреса электронной почты в имена, что и делает
поверхность Messages читаемой вообще. Читайте status в каждом результате, а не предполагайте, что имя
вернулось: unknown — это обычное дело, а не ошибка, а ambiguous означает, что два контакта используют один номер, поэтому
имя не возвращается, а не угадывается.
Инструмента удаления нет. В словаре сценариев контактов нет команды удаления какого-либо вида, и записи проходят через Apple Events на каждой поверхности здесь, потому что хранилище доступно только для чтения по политике. См. docs/contacts.md.
Сообщения
Всегда доступно | Только запись |
|
|
|
Один инструмент записи, потому что в словаре есть одна полезная команда. sdef перечисляет send, login и
logout; другие два вышли бы пользователя из iMessage на всех его устройствах. Нет
редактирования, удаления, отметки о прочтении или реакции, которые можно было бы выставить.
Это единственная поверхность, где Apple Events — это только канал записи и ничего больше — каждый
чтение через него не удаётся, поэтому при выключенном APPLE_MESSAGES_ALLOW_WRITES ни одно событие Apple не отправляется и ни одно
разрешение Automation не запрашивается.
send_message предпочитает chatRef из list_chats вместо сырого адреса, потому что Messages отказывается
перечислять участников для сценария: существующий разговор — единственная цель, которую можно
надёжно адресовать. Apple Events не возвращает идентификатор того, что было отправлено, поэтому результат
сверяется с chat.db — reconciliation: "matched" несёт реальную ссылку на сообщение, а
"pending" означает, что Messages принял отправку, но ещё не записал строку. Ожидание — это не
ошибка, и повторная попытка отправляет сообщение дважды.
Около 3% сообщений за всю историю хранят свой текст только в архивном блобе NSArchiver, который
SQL не может достичь — а Apple перестала записывать обычный столбец в начале 2026 года, так что для недавних
это ~100%. Этот сервер декодирует их; textSource в каждом результате говорит, какой канал ответил. См.
docs/messages.md.
Safari
Всегда доступно | Только запись |
| — нет |
|
Только для чтения, и столбец записи пуст намеренно. Открытие URL или добавление в список для чтения — это событие Apple Events, которое управляет реальным видимым браузером, и ни одна запись на этой поверхности не была проверена.
list_tabs — единственный инструмент во всём наборе, который работает без полного доступа к диску — ему нужен
разрешение Automation, и Safari должен быть запущен. Поле history вкладки, равное null, означает
не найдено в истории, а не «никогда не посещалось»: только около 55% открытых вкладок соответствуют строке истории,
потому что перенаправления, параметры сеанса и страницы, никогда не зафиксированные в истории, создают URL, который
просто отсутствует.
Инструмента do JavaScript нет. Этот глагол требует «Разрешить JavaScript из Apple Events», переключатель
в меню разработчика Safari, который не является разрешением TCC и чьё собственное состояние нельзя надёжно прочитать.
Включение его означало бы сообщать о здоровой поверхности, чья самая мощная возможность молча не работает.
См. docs/safari.md.
Все имена имеют префикс apple_mail_ / apple_notes_ / apple_reminders_ / apple_calendar_ /
apple_contacts_ / apple_messages_ / apple_safari_.
Конфигурация
Только переменные окружения — эти серверы не хранят собственных секретов, поэтому нет файла конфигурации. Префикс
APPLE_MAIL_, APPLE_NOTES_, APPLE_REMINDERS_, APPLE_CALENDAR_, APPLE_CONTACTS_,
APPLE_MESSAGES_ или APPLE_SAFARI_.
Переменная | По умолчанию | Что |
|
| регистрировать ли изменяющие инструменты вообще |
| все | список разрешённых учётных записей (имена или UUID) — контроль чтения |
|
| единственная директория, в которую могут записываться вложения |
|
| предел для любого списка |
|
|
|
|
| таймаут на каждый вызов Apple Events |
|
| подробное логирование в stderr |
allowWrites ограничивает изменение, но в Mail больший радиус поражения — это чтение всего архива —
именно для этого предназначен *_ACCOUNTS, и он применяется ровно в одном месте, чтобы ни один путь запроса не обходил его.
Mail также принимает *_ROOT, *_ENVELOPE_INDEX, *_DEGRADED_MAX_MESSAGES, *_BODY_MAX_BYTES,
*_BODY_SCAN_MAX, *_BODY_SCAN_BYTES и *_MAILBOX_CACHE_TTL_MS; см. packages/mail/src/config.ts.
Приложение
Строка меню — это вся поверхность Cupertino — нет значка в Dock и нет главного окна.
Раздел | Что он отвечает |
Полный доступ к диску | предоставлен или нет, с кнопкой, открывающей нужную панель настроек |
Одна панель на поверхность | статус Automation для каждого приложения, запрос согласия и переключатель записи |
Подключения | какой клиент общается с каким сервером прямо сейчас и сколько инструментов он вызвал |
MCP-клиенты | подключение в один клик для Claude Desktop, Cursor, LM Studio и Windsurf; копируемая команда для Claude Code, VS Code и Codex |
Активность… | открывает окно со списком всех вызовов инструментов в реальном времени |
Окно Активность записывает только имена инструментов — никогда аргументы, содержимое сообщений или результаты. Это ответ на вопрос «что ассистент только что сделал с моей почтой?» и причина, по которой серверы работают под приложением, которое вы видите, а не внутри редактора, который их запустил.
Запись отключена для каждой поверхности, пока вы её не включите, и переключатель решает, регистрируются ли изменяющие инструменты вообще — ассистент с выключенной записью не может видеть, что они существуют.
Почему одно приложение
Полный доступ к диску — это одно неделимое разрешение на весь диск. Предоставление его по каждой поверхности не даёт изоляции и стоит похода в Системные настройки каждый раз, поэтому каждая поверхность поставляется внутри одного подписанного, нотариально заверенного приложения под названием Cupertino. docs/distribution.md также объясняет, почему Mac App Store не может разместить ничего из этого, чтобы вопрос не поднимался снова.
Но разрешение — не единственное, что хранит приложение, и не единственная причина запускать серверы под ним, а не под редактором:
Разрешение ложится на Cupertino | не на редактор, который запустил сервер, и вместе с ним на каждое расширение и задачу, которые этот редактор выполняет |
Видимый аудит-след | окно Активность перечисляет каждый вызов инструмента в реальном времени; сервер внутри редактора не наблюдаем |
Запись отключена, по поверхности | и переключатель определяет, регистрируются ли изменяющие инструменты вообще |
| радиус поражения в Mail — это архив, а не изменения |
Результаты говорят, насколько им доверять |
|
Четыре поверхности, одно разрешение | что является фактической выгодой от неделимости выше |
docs/alternatives.md — это честная версия этого списка: что ещё читает Apple Mail для ассистента и где эти инструменты впереди.
Документация
как это распространяется, и почему не в App Store | |
какие поверхности и во что выходит каждая | |
что открыто, что продаётся, что покупает доверие | |
что ещё умеет читать Apple Mail, и где мы проигрываем | |
трек поиска по телу письма и почему выбран именно он | |
измерения Apple Notes, фаза 0 | |
измерения Apple Reminders, фаза 0 | |
Apple Messages: измерения, декодер, отправка | |
измерения Apple Calendar, фаза 0 | |
измерения Safari, фаза 0 | |
наблюдаемая схема | |
проверка Mail-сервера по реальному индексу |
В работе
pnpm build # every package
pnpm test # every package
pnpm typecheck
pnpm lint
pnpm formatМаркетинговый сайт — это отдельное рабочее пространство, и разворачивается вручную:
pnpm --filter @mgcrea/cupertino-website dev # astro dev
pnpm --filter @mgcrea/cupertino-website build # static buildОн собирается из дизайн-холста в .idea/design/, а количество инструментов берёт не из этого файла, а из packages/*/src/tools/ — см. apps/website.
Swift-половина — это xcodebuild, вызываемая в Makefile по имени, а не обёрнутая им:
make app # build Cupertino.app (Debug)
make run # build, point at packages/*/dist, launch
make smoke # handshake every server through the bridge
make stop # quit and remove the socketСкриншоты приложения создаются автоматически, а не снимаются вручную — в apps/apple/Screenshots/ лежат конфигурация и закоммиченные эталонные изображения, а сайт рендерит результат:
make screenshots # capture, gate against the goldens, compose both sets
make screenshots-check # gate only — fails if the UI drifted
make screenshots-update # accept the captures as the new goldens (review the diffs first)
make screenshots-selftest # prove the gate fails when it shouldЗапуск в момент каждого снимка перехватывает указатель и активное приложение, поэтому во время его работы не пользуйтесь компьютером. Он требует разрешения на запись экрана для терминала, и никогда — для самого Cupertino. make screenshots-doctor проверяет это и ещё две вещи, которые иначе молча сломаются: доступен ли шрифт подписей и подходит ли магазину размер результата.
На скриншотах — тестовые данные из apps/apple/Cupertino/DemoSeed.swift, а не из этого Mac: в режиме -ScreenshotMode приложение не запускает хост, наполняет свой журнал и сессии, а на вопросы о разрешениях и App Store отвечает из таблицы. Без этого изображения показали бы состояние TCC одного ноутбука и вывели его домашнюю директорию на маркетинговый сайт.
Зонды фазы 0 охватывают репозиторий и работают только на чтение. Им требуется разрешение той поверхности, которую они измеряют, а вывод в них — только количество, времена и DDL:
pnpm probe:mail # Envelope Index — needs Full Disk Access
pnpm probe:mail-body # which lane can search message bodies — needs Full Disk Access
pnpm probe:notes # Notes — the Apple Events half runs without it
pnpm probe:reminders # Reminders — the store path is a glob, so finding it is itself privileged
pnpm probe:messages # chat.db — no Apple Events read lane exists, so this one needs the grant
# --send-target=<handle> also checks the send lane's targeting, without sending
pnpm probe:calendar # settles whether Calendar has a file lane at all
pnpm probe:safari # History.db, and the Reading List hiding inside Bookmarks.plist
pnpm probe:contacts # the resolver Messages needs — its own TCC grant, not Full Disk AccessУ каждой исследуемой поверхности теперь есть пакет. Safari работает только на чтение — в ней не региструется ни одного изменяющего инструмента, и это зафиксированное решение, а не пробел: открытие URL или добавление в список чтения управляет настоящим видимым браузером и никогда не зондировалось. См. docs/safari.md. В Messages зарегистрирован ровно один пишущий инструмент — send_message; им полностью исчерпывается то, что умеет её scripting dictionary.
Каждый зонд деградирует, а не происходит — если приложение не запущено или разрешение не выдано, это фиксируется как наблюдение, — и ни один из них не запускает приложение, если не передать --launch. Общий механизм лежит в scripts/lib/probe-kit.mjs.
Релизы размечаются тегами по пакетам, поэтому тег называет, что он издаёт: mail-v1.1.0, reminders-v1.1.0, calendar-v1.1.0, core-v1.1.0. Приложение помечается тещ в app-v1.1.0 и выпускается по своему каналу — подписанный и нотаризованный Cupertino.zip, прикреплённый к GitHub-релизу, плюс его SHA-256. См. docs/distribution.md.
Репозиторий был назван
mcp-cupertino; npm-пакеты остаются@mgcrea/mcp-apple-*, потому что именно так их ищут в npm. Никакое из этих названий не значимо. По-настоящему важна строка bundle identifierio.mgcrea.cupertino— её изменение аннулирует всем пользователям доступ Full Disk Access.
Лицензия
Лицензия.
Две части — потому что это не одно и то же.
Часть | Лицензия |
| MIT — библиотеки, можно свободно внедрять |
| source-available — читать, проверять, компилировать; распространение бинарных, кроме того, разрешено |
подписанный, нотированый бинарный | продаётся, по EULA, входящей в комплект |
Cupertino запрашивает Full Disk Access, поэтому исходный код остаётся читаемым — это та цена, которую следует заплатить за подобный доступ, и именно чтение его есть смысл.
Запуск — отдельный вопрос: проверка лицензии живёт в исходниках, так что сборка требует ключ — ваш или наш. Продаётся нотаризованная сборка и поддержка за ней. Серверы — MIT — работают на своём, без какого-либо ключа. Причина подробно описана в docs/licensing.md.
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
- AlicenseNot gradedqualityCmaintenanceA local MCP server that provides a secure bridge for automating macOS applications like Notes, Calendar, and Mail through AppleScript. It uses template-based execution and policy-based allowlists to enable safe, structured interaction with system tools.MIT
- AlicenseBqualityDmaintenanceMCP server for macOS Apple apps. Enables read/write access to Notes, Reminders, Calendar, Contacts, and Safari using SQLite and JXA, all running locally.428122MIT
- AlicenseAqualityCmaintenanceMCP server for privacy-gated local Apple data access including Mail, Messages, Notes, Calendar, Contacts, Photos, Reminders, Voice Memos, and iCloud Drive.301MIT
- AlicenseNot gradedqualityAmaintenanceA collection of MCP servers for Apple macOS apps (Mail, Contacts, Notes, Memory, Messages, Calendar, Reminders) enabling AI assistants to read, search, create, and update data via JXA, SQLite, and EventKit.12MIT
Related MCP Connectors
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
MCP connector for iMessage & Contacts via a local Mac agent + Vercel relay
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/mgcrea/mcp-cupertino'
If you have feedback or need assistance with the MCP directory API, please join our Discord server