Skip to main content
ClaudeWave
EN, English
mgcrea / MCP Servers · Official registry

cupertino

MCP servers for the Apple apps on your Mac — one Full Disk Access grant, held by a signed app instead of your editor

  • 5 stars
  • 0 forks
  • 2 open issues
  • Language: TypeScript
  • License: MIT
  • updated

Install

Claude Code CLI
git clone https://github.com/mgcrea/cupertino
  1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
  2. Replace any <placeholder> values with your API keys or paths.
  3. Restart Claude. The MCP server and its tools appear automatically.

Clone https://github.com/mgcrea/cupertino and follow its README for install instructions.

README

MCP Servers overview

Full README on GitHub

Cupertino

Put your agent to work in your everyday Apple apps.

MCP servers for the Apple apps already on your Mac, and the signed app that grants them their permissions once instead of once each — for any agent that speaks MCP, not for one host.

Unofficial. Not affiliated with Apple. These drive the apps that are already on your Mac.

In use

Look at how I write in my work inbox, then draft this reply in the same voice.

Pull together everything about the Atlas launch from my mail, my notes and my calendar. What do I still owe people?

Turn the action items from yesterday's client thread into reminders, due Friday.

Every one of those carries a constraint — an account, a date bound, a filter. That is the part the naive osascript path answers in 74 seconds or answers wrongly, and the reason a server earns its place: it holds what the model would otherwise re-derive every session. The measurements are in docs/verify.md; what the alternatives cost is in docs/alternatives.md.

The last one needs the write gate open on Reminders. Writes are off per surface until you turn them on, and the toggle decides whether the mutating tools are registered at all — an agent with writes off cannot see that they exist.

Surfaces

SurfacePackageStatus
Mailpackages/mailimplemented — 22 tools, search/read/attachments + gated writes
Notespackages/notesimplemented — 13 tools, search/read/attachments + gated writes
Reminderspackages/remindersimplemented — 11 tools, lists/search/dates + gated writes
Calendarpackages/calendarimplemented — 10 tools, ranges/search/free-time + gated writes
Contactspackages/contactsimplemented — 7 tools, resolves handles to names + gated writes
Messagespackages/messagesimplemented — 9 tools, chats/search/counts/decoded text + gated send and codes
Safaripackages/safariimplemented — 17 tools, history/tabs/reading list/page reads + gated writes, codes, network
Mapspackages/mapsimplemented — 13 tools, favourites/Guides/recents + gated writes
Screen—implemented — 3 tools, ScreenCaptureKit; served in-app, no npm package; off until switched on
Sound—implemented — 10 tools, volume/routing/speech + gated recording; in-app; off until switched on
Desktop—implemented — 24 tools, AXUIElement natively; in-app, no npm package; off until switched on
Simulator—implemented — 11 tools, an iOS Simulator's screen in iOS points; in-app; off until switched on
—packages/coreshared: the osascript boundary, TCC-aware errors, ro SQLite

Screen, Sound, Desktop and Simulator arrive switched off. Every other surface that brokers an Apple app is on when Cupertino is installed; those four are not, because Screen Recording, the microphone and Accessibility are per-process grants that reach past the surface being brokered. Desktop reaches furthest — Accessibility does not scope to a target at all, so the right to press a button in Maps is the right to press one in anything, and it additionally arrives with writes off, so it can only look until you say otherwise. Simulator holds the same grant and pins its own reach to Simulator.app, with no switch that widens it. Switch them on in the surface list if you want them.

Each surface is its own server, so a host loads only the tools it wants. Every surface that brokers an Apple app through its store or its scripting dictionary is also its own npm package; screen, sound, desktop and simulator are not, and could not be — the first three broker a framework rather than an app, simulator brokers an app through Accessibility, and in every case the grant lives in the app, so the app serves them in-process and a published package could do nothing. See docs/screen.md, docs/desktop.md and docs/simulator.md.

simulator is the lane for an app you are building. Simulator.app bridges the simulated device's accessibility tree into the Mac's, so an iOS app's own controls are readable and pressable here with no WebDriverAgent and no runner process — and the surface answers in iOS points, the space ios_simulator_tap and ios_simulator_screenshot use, with the window scale measured on every call rather than assumed. It reads, finds and presses; behind writes it taps, swipes, types and presses the device's buttons. Booting, installing, launching, screenshots and push need no grant and stay with @mgcrea/mcp-ios-simulator, which this complements rather than copies.

desktop is the one surface that drives an interface rather than reading a store, and it does it through AXUIElement natively rather than through osascript. That distinction is the whole surface: every Accessibility measurement this project took before 2026-09-05 went through System Events, one Apple Event per attribute, which is where "33.6 ms a round trip" and "~14 s for a place card" came from. Natively the same walks cost 1.24 ms a round trip and the same place card 0.177 s. The transport was the cost, not the API — see docs/desktop.md.

They share one bundle and one Full Disk Access grant, which is the whole reason they live together — see docs/distribution.md.

Quick start

Every server that brokers an Apple app is on npm and runs straight from npx — for Claude Code, a .mcp.json beside your project:

{
  "mcpServers": {
    "apple-mail": {
      "command": "npx",
      "args": ["-y", "@mgcrea/mcp-apple-mail"]
    },
    "apple-notes": {
      "command": "npx",
      "args": ["-y", "@mgcrea/mcp-apple-notes"]
    }
  }
}

The packages are MIT and need no licence key. What they do need is a permission, and on npm you grant it to whatever launches them — your editor, your terminal — which is the trade the signed Cupertino.app exists to avoid: one Full Disk Access grant held by a notarized binary, instead of one per host. See docs/licensing.md.

brew install --cask mgcrea/tap/cupertino

Or run them from source:

git clone https://github.com/mgcrea/cupertino.git
cd cupertino
pnpm install
pnpm build

then point your host at packages//dist/cli.js by absolute path.

Writes are off unless you ask for them — see Configuration.

Running through the menu bar app instead routes every server through the bridge, so Full Disk Access is granted to Cupertino rather than to whichever editor spawned the server:

make run      # build Cupertino.app, point it at packages/*/dist, launch it
make smoke    # handshake every server through the bridge

make surfaces writes a gitignored .mcp.json at the repo root, wired for that path — it is a developer's local working config rather than something to commit, because every entry is an absolute path into one Mac's bundle. make on its own lists every target.

Note the different server names. Wired by hand as above, a server is apple-mail and runs under whatever grant its host process has. Wired by Cupertino it is cupertino-mail, because that entry points at the app's bridge and runs under the app's grant. Two names for two deployments, and you can have both. The app only ever touches its own cupertino-* keys — an apple-mail entry belonging to some other server is left alone.

Cupertino is machine configuration, not a project dependency, so it belongs in a per-user config: one file each, and the equivalent of --scope user everywhere. Deliberately not --scope project, which writes an .mcp.json meant to be committed — that entry is an absolute path into a bundle on one Mac, backed by one person's Full Disk Access grant, and it would be useless to a teammate and unwise to offer them.

All seven are written by the app, and nothing has to be pasted into a terminal. Six keep strict JSON and are merged into as dictionaries — five under mcpServers, Visual Studio Code under servers in User/mcp.json, which is a different file from the JSONC settings.json it was confused with for two releases. The seventh, ~/.codex/config.toml, is TOML full of hand-written prose and structure, so it is never re-serialised: ClientWiringTOML replaces the lines that hold MCP servers and quotes every other byte verbatim. ChatGPT has no row of its own because it is not a separate client — the ChatGPT app, the Codex CLI and the Codex IDE extension all read that same file, which is the row called "ChatGPT & Codex".

Claude Code's ~/.claude.json is written directly, and it is the one config where that deserves a paragraph: it holds this machine's credentials beside ninety-odd project blocks, and Claude Code

Topics
ai-agentsappleapple-calendarapple-mailapple-notesapple-remindersapplescriptclaudeimessagejxamacosmcpmcp-servermodel-context-protocolsafari
Frequently asked

What people ask about cupertino

What is mgcrea/cupertino?

mgcrea/cupertino is mcp servers for the Claude AI ecosystem. MCP servers for the Apple apps on your Mac — one Full Disk Access grant, held by a signed app instead of your editor It has 5 GitHub stars and its last recorded update is dated 2026-10-22.

How do I install cupertino?

You can install cupertino by cloning the repository (https://github.com/mgcrea/cupertino) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is mgcrea/cupertino safe to use?

Our security agent has analyzed mgcrea/cupertino and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.

Who maintains mgcrea/cupertino?

mgcrea/cupertino is maintained by mgcrea. The last recorded GitHub activity is dated 2026-10-22, with 2 open issues.

Are there alternatives to cupertino?

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Alternatives