Skip to main content
Glama

Apple MCP Server

Tools Actions Resources Tests Platform TypeScript MCP License

An MCP server that exposes macOS system controls and Apple apps as structured tools for Claude. Built with TypeScript and the official @modelcontextprotocol/sdk.

31 tools, 303 actions, 4 resources. Each Apple app is a single MCP tool with an action parameter.

Requirements

  • macOS (tested on macOS 15 with Apple Silicon)

  • Node.js 18+

  • Claude CLI or any MCP-compatible client

  • Some features require "Allow JavaScript from Apple Events" in Safari > Develop

Related MCP server: applescript-mcp

Setup

git clone https://github.com/lacausecrypto/apple-mcp-server.git
cd apple-mcp-server
npm install
npm run build

Register in your MCP config (~/.claude/.mcp.json or project .mcp.json):

{
  "mcpServers": {
    "apple": {
      "command": "node",
      "args": ["/absolute/path/to/apple-mcp-server/dist/index.js"]
    }
  }
}

How it works

Claude calls apple_music with {action: "now_playing"}
  → index.ts checks permissions (OPEN → proceed)
  → dispatches to domains/music.ts handler
  → handler calls runAppleScript() in executor.ts
  → AppleScript written to temp file, executed via osascript
  → result returned to Claude: "Bohemian Rhapsody — Queen (3:21/5min)"

Permission System

Actions are classified into three levels. Conservative by default — destructive actions require explicit confirmation.

OPEN (default)

Read-only and safe actions execute immediately. No confirmation needed.

Claude: apple_volume.get → "Volume: 56%"
Claude: apple_music.now_playing → "Bohemian Rhapsody — Queen"
Claude: apple_sysinfo.battery → "95%; charging"

PROTECTED (27 actions)

Destructive or irreversible actions return a preview and require confirm: true to execute.

Claude: apple_finder.empty_trash
→ "⚠️ apple_finder.empty_trash requires confirmation.
   Reason: Permanently deletes all items in Trash
   To proceed, call again with confirm: true."

Claude: apple_finder.empty_trash with confirm: true
→ "Trash emptied"

Protected actions include: file delete/move/rename, send email/iMessage, post/like/reply on Twitter, delete contacts/notes/reminders/events, force quit apps, system sleep.

BLOCKED (3 actions)

Never executed. Returns an error with instructions to unblock.

Claude: apple_system.shutdown
→ "🚫 apple_system.shutdown is blocked.
   Blocked by default (dangerous system action)."

Blocked by default: shutdown, restart, logout.

Configuration

Override defaults via ~/.config/apple-mcp/permissions.json:

{
  "blocked": ["empty_trash"],
  "unprotected": ["like", "send"],
  "unblocked": ["restart"],
  "protected": ["play", "pause"]
}

Key

Effect

blocked

Add actions to BLOCKED (on top of defaults)

unprotected

Move from PROTECTED → OPEN (skip confirmation)

unblocked

Move from BLOCKED → PROTECTED (allow with confirmation)

protected

Move from OPEN → PROTECTED (add confirmation)

Actions can be specified as "actionName" (global) or "apple_tool.actionName" (specific).

Rate Limiting

Prevents spam and abuse. Two independent sliding-window counters:

  • Global: max 30 tool calls per minute (all actions)

  • Protected: max 5 confirmed destructive actions per minute

When exceeded, the call is rejected with a wait time. Configurable:

{ "rate_limit": { "global_per_min": 60, "protected_per_min": 10 } }

Dry-Run Mode

Preview every action without executing. Useful for testing what Claude would do:

{ "dry_run": true }
Claude: apple_finder.delete(path: "~/old.pdf", confirm: true)
→ "[DRY RUN] Would execute apple_finder.delete (confirmed) — no action taken."

All actions return previews. Nothing is executed. The audit log records dry_run events.

Audit Log

Every tool call is logged as a structured JSON line in ~/.local/occ/rag/apple-mcp-audit.jsonl:

{"ts":"2026-03-31T18:36:49Z","tool":"apple_volume","action":"get","permission":"open","confirmed":false,"dry_run":false,"result":"ok","duration_ms":104,"output":"Volume: 56%"}
{"ts":"2026-03-31T18:36:52Z","tool":"apple_finder","action":"empty_trash","permission":"protected","confirmed":false,"dry_run":false,"result":"protected_no_confirm","duration_ms":0}

Queryable with jq:

# All blocked calls
cat apple-mcp-audit.jsonl | jq 'select(.result=="blocked")'

# Calls per tool
cat apple-mcp-audit.jsonl | jq -s 'group_by(.tool) | map({tool: .[0].tool, count: length})'

# Average duration per tool
cat apple-mcp-audit.jsonl | jq -s 'group_by(.tool) | map({tool: .[0].tool, avg_ms: (map(.duration_ms) | add / length)})'

Tools

Tool

#

Actions

Protected/Blocked

apple_volume

7

get set up down mute unmute info

—

apple_brightness

2

up down

—

apple_clipboard

3

get set clear

—

apple_apps

7

open quit is_running list_running hide activate force_quit

force_quit

apple_sysinfo

19

battery disk uptime ip macos_version cpu memory top_processes hostname resolution summary bluetooth_devices audio_devices printers displays usb_devices network_interfaces serial_number model

—

apple_music

26

play pause stop next prev restart now_playing shuffle_on shuffle_off repeat_off repeat_one repeat_all play_playlist list_playlists set_volume love dislike search play_song queue_next add_to_playlist create_playlist get_lyrics radio remove_from_playlist delete_playlist

delete_playlist remove_from_playlist

apple_spotify

17

play pause next prev now_playing set_volume shuffle playpause play_playlist list_playlists like repeat_off repeat_on search play_track current_album current_artist

—

apple_safari

17

open_url current_url current_title list_tabs close_tab new_tab reload page_text reading_list js_execute back forward bookmarks history_recent private_window close_window tab_count

—

apple_chrome

14

open_url current_url current_title list_tabs close_tab reload js_execute back forward new_window new_incognito close_window tab_count new_tab

—

apple_mail

10

unread_count check unread_list read_body search draft mailboxes send mark_all_read move_to_trash

send mark_all_read move_to_trash

apple_calendar

8

list today tomorrow create_event week date_events delete_event modify_event

delete_event modify_event

apple_reminders

10

list_lists list add complete set_due set_priority add_note overdue create_list delete

delete

apple_notes

9

list create read search folders move append count delete

delete

apple_finder

20

open_folder reveal desktop_files trash_count create_folder file_info copy get_selection tags set_tag list_folder disk_info empty_trash delete move rename eject_disk eject_all set_wallpaper create_alias

empty_trash delete move rename eject_disk eject_all set_wallpaper

apple_windows

14

frontmost_app minimize minimize_all maximize left_half right_half fullscreen close hide_app hide_others center resize list_windows switch_to

—

apple_system

30

sleep_display lock dark_mode dnd_on dnd_off caffeinate decaffeinate wifi_status wifi_on wifi_off wifi_network bluetooth_on bluetooth_off run_shortcut list_shortcuts open_prefs display_settings sound_settings network_settings airdrop screen_saver login_items time_machine audio_output audio_input sleep eject_all_disks shutdown restart logout

sleep eject_all_disks · Blocked: shutdown restart logout

apple_screenshot

5

full clipboard timed area window

—

apple_notification

1

send

—

apple_keyboard

8

type_text press_key copy paste undo redo save select_all

—

apple_tts

3

say list_voices stop

—

apple_twitter

11

draft save list_drafts feed notifications dm_check post post_draft reply like retweet

post post_draft reply like retweet

apple_facetime

2

call audio

—

apple_maps

2

open directions

—

apple_contacts

9

search get list create groups group_members delete update_phone update_email

delete update_phone update_email

apple_photos

10

albums recent search favorites album_contents export count create_album add_to_album import

—

apple_messages

5

recent unread conversation search send

send

apple_podcasts

7

now_playing play pause next shows episodes search

—

apple_books

5

library reading_now collections search open

—

apple_iwork

11

pages_create pages_open pages_export_pdf numbers_create numbers_open numbers_export_pdf keynote_create keynote_open keynote_export_pdf keynote_start_slideshow keynote_stop_slideshow

—

apple_preview

4

open list_open close close_all

—

apple_textedit

7

create open get_text set_text save close list_open

—

Security

What this provides

Permission system — Three-level access control (OPEN/PROTECTED/BLOCKED) enforced before execution. Protected actions require confirm: true. Configurable via JSON file.

Rate limiting — Sliding-window counters: 30 calls/min global, 5 protected/min. Prevents abuse loops.

Dry-run mode — All actions return previews without executing. Safe testing of what Claude would do.

Structured audit log — Every call logged as JSON line (tool, action, permission, result, duration). Queryable with jq.

Input validation — Not sandboxing. The server validates inputs before passing them to AppleScript or shell:

Function

What it does

safePath()

Allowlist: only permits paths under ~/, /tmp, /Volumes/nvme, /Applications. Everything else rejected.

safeAS()

Escapes \ and " for AppleScript string interpolation. Prevents script injection inside quoted strings.

safeSQL()

Escapes quotes, strips ;, --, /* */, UNION, DDL keywords, hex literals. Used for iMessage sqlite3 queries.

safeAppName()

Strips shell metacharacters from app names.

Concurrency — withLock() serializes Safari and Chrome tab operations to prevent race conditions.

Execution safety — AppleScript runs via temp .scpt files (not -e flag). Shell commands use execFile with array arguments (no shell interpolation).

Auto-launch — Apps that aren't running are launched automatically on -600 error and retried once.

Logging — All tool calls, permission checks, and errors logged to ~/.local/occ/rag/apple-mcp.log.

What this does NOT provide

  • No sandboxing. The Node process runs with your full user privileges. It can do anything you can do.

  • No network isolation. The server communicates via stdio (local only), but the actions it executes (email, tweets, etc.) reach the internet.

  • No encryption. Log files and the permission config are plain text.

  • No authentication on the MCP transport. Any process that can connect to stdio can call tools.

  • safePath is an allowlist, not a jail. It prevents operations on system paths, but ~/ is allowed — which includes ~/Library, ~/.ssh, etc.

This is suitable for personal use on your own Mac. It is not designed for multi-user environments or adversarial contexts.

Resources

URI

Description

apple://now-playing

Current track from Apple Music or Spotify

apple://system-info

Battery, disk, uptime, CPU load, RAM

apple://open-tabs/safari

All open Safari tabs

apple://open-tabs/chrome

All open Chrome tabs

Adding a new domain

  1. Create src/domains/myapp.ts (see existing domains for pattern)

  2. Import and register in src/registry.ts

  3. If destructive, add to DEFAULT_PROTECTED in src/permissions.ts

  4. npm run build && npm test

Testing

npm run build
npm test    # 135 tests (executor + registry + permissions)

Known limitations

  • Books and Podcasts have limited AppleScript support. Some actions return generic errors.

  • Spotify doesn't expose playlists or "like" via AppleScript. Uses URL schemes as fallback.

  • Safari JS execution requires "Allow JavaScript from Apple Events" in Safari > Develop.

  • Twitter/X actions depend on the current DOM structure, which may change.

  • safePath allows all of ~/ — including sensitive directories like ~/.ssh and ~/Library.

Logging

~/.local/occ/rag/apple-mcp.log

Project structure

src/
  index.ts          Server entry, permission enforcement, tool dispatch
  permissions.ts    Three-level permission system with config file
  types.ts          Interfaces: ExecResult, DomainModule, DomainAction, ResourceDef
  executor.ts       Execution layer: AppleScript, shell, caching, locking, safety
  registry.ts       Domain registry and JSON Schema builder
  domains/          31 domain files (one per Apple app/category)
  resources/        4 MCP resource providers
tests/
  executor.test.js  Safety function tests
  registry.test.js  Domain registration tests
  permissions.test.js  Permission system tests

License

MIT

Available Tools

31 tools
apple_appsB

Manage macOS applications. Actions: open, quit, force_quit, is_running, list_running, hide, activate.

Inputs: action (required), name, confirm.

apple_booksB

Control Apple Books. Actions: library, reading_now, collections, search, open. Note: Books has limited AppleScript support — some actions may return partial results.

Inputs: action (required), query, confirm.

apple_brightnessC

Control macOS display brightness. Actions: up, down.

Inputs: action (required), confirm.

apple_calendarC

Control Apple Calendar. Actions: list, today, tomorrow, create_event, delete_event, week, date_events, modify_event.

Inputs: action (required), date, hour, title, +3 more.

apple_chromeB

Control Google Chrome browser. Actions: open_url, current_url, current_title, list_tabs, close_tab, reload, js_execute, back, forward, new_window, new_incognito, close_window, tab_count, new_tab.

Inputs: action (required), url, code, confirm.

apple_clipboardA

Read and write the macOS clipboard. Actions: get, set, clear.

Inputs: action (required), text, confirm.

apple_contactsD

Control Apple Contacts. Actions: search, get, list, create, groups, group_members, delete, update_phone, update_email.

Inputs: action (required), name, email, phone, +4 more.

apple_facetimeB

Make FaceTime calls. Actions: call (video), audio.

Inputs: action (required), confirm, contact.

apple_finderC

Manage Finder: files, folders, trash, wallpaper, disks, tags. Actions: open_folder, reveal, desktop_files, empty_trash, trash_count, eject_disk, eject_all, set_wallpaper, create_folder, file_info, rename, move, copy, delete, create_alias, get_selection, tags, set_tag, list_folder, disk_info.

Inputs: action (required), tag, name, path, +4 more.

apple_iworkB

Control Pages, Numbers, and Keynote. Actions: pages_create, pages_open, pages_export_pdf, numbers_create, numbers_open, numbers_export_pdf, keynote_create, keynote_open, keynote_export_pdf, keynote_start_slideshow, keynote_stop_slideshow.

Inputs: action (required), path, confirm.

apple_keyboardC

Simulate keyboard input. Actions: type_text, press_key, copy, paste, undo, redo, save, select_all.

Inputs: action (required), text, combo, confirm.

apple_mailC

Control Apple Mail. Actions: unread_count, check, unread_list, send, mark_all_read, read_body, search, draft, mailboxes, move_to_trash.

Inputs: action (required), to, body, query, +3 more.

apple_mapsB

Open Apple Maps with a search query or directions. Actions: open, directions.

Inputs: action (required), to, from, query, +1 more.

apple_messagesC

Control Apple Messages / iMessage. Actions: recent, send, unread, conversation, search.

Inputs: action (required), to, text, limit, +3 more.

apple_musicC

Control Apple Music. Actions: play, pause, stop, next, prev, restart, now_playing, shuffle_on, shuffle_off, repeat_off, repeat_one, repeat_all, play_playlist, list_playlists, set_volume, love, dislike, search, play_song, queue_next, add_to_playlist, remove_from_playlist, create_playlist, delete_playlist, get_lyrics, radio.

Inputs: action (required), name, level, query, +3 more.

apple_notesC

Control Apple Notes. Actions: list, create, read, search, delete, folders, move, append, count.

Inputs: action (required), body, text, query, +3 more.

apple_notificationB

Send macOS notifications. Actions: send.

Inputs: action (required), sound, title, confirm, +1 more.

apple_photosB

Control Apple Photos. Actions: albums, recent, search, favorites, album_contents, export, count, create_album, add_to_album, import.

Inputs: action (required), name, path, album, +3 more.

apple_podcastsB

Control Apple Podcasts. Actions: now_playing, play, pause, next, shows, episodes, search.

Inputs: action (required), name, query, confirm.

apple_previewA

Control Preview app. Actions: open, list_open, close, close_all. Note: Preview has limited AppleScript support.

Inputs: action (required), path, confirm.

apple_remindersC

Control Apple Reminders. Actions: list_lists, list, add, complete, delete, set_due, set_priority, add_note, overdue, create_list.

Inputs: action (required), name, text, confirm, +4 more.

apple_safariC

Control Safari browser. Actions: open_url, current_url, current_title, list_tabs, close_tab, new_tab, reload, page_text, reading_list, js_execute, back, forward, bookmarks, history_recent, private_window, close_window, tab_count.

Inputs: action (required), url, code, confirm.

apple_screenshotA

Take screenshots on macOS. Actions: full, clipboard, timed, area, window.

Inputs: action (required), path, confirm, seconds.

apple_spotifyB

Control Spotify. Actions: play, pause, next, prev, now_playing, set_volume, shuffle, playpause, play_playlist, list_playlists, like, repeat_off, repeat_on, search, play_track, current_album, current_artist.

Inputs: action (required), uri, name, level, +2 more.

apple_sysinfoA

Read macOS system information. Actions: battery, disk, uptime, ip, macos_version, cpu, memory, top_processes, hostname, resolution, summary, bluetooth_devices, audio_devices, printers, displays, usb_devices, network_interfaces, serial_number, model.

Inputs: action (required), confirm.

apple_systemC

System controls: sleep, restart, shutdown, lock, dark mode, DND, caffeinate, wifi, bluetooth, shortcuts, prefs, audio, screen saver, AirDrop, login items, Time Machine, audio devices. Actions: sleep, sleep_display, restart, shutdown, logout, lock, dark_mode, dnd_on, dnd_off, caffeinate, decaffeinate, wifi_status, wifi_on, wifi_off, wifi_network, bluetooth_on, bluetooth_off, run_shortcut, list_shortcuts, open_prefs, display_settings, sound_settings, network_settings, airdrop, screen_saver, login_items, eject_all_disks, time_machine, audio_output, audio_input.

Inputs: action (required), name, pane, confirm, +1 more.

apple_texteditC

Control TextEdit. Actions: create, open, get_text, set_text, save, close, list_open.

Inputs: action (required), path, text, confirm.

apple_ttsC

Text-to-speech on macOS. Actions: say, list_voices, stop.

Inputs: action (required), rate, text, voice, +1 more.

apple_twitterC

Control X/Twitter via Safari. Actions: post, draft, save, list_drafts, post_draft, reply, like, retweet, feed, notifications, dm_check.

Inputs: action (required), num, text, confirm, +2 more.

apple_volumeB

Control macOS system volume. Actions: get, set, up, down, mute, unmute, info.

Inputs: action (required), level, confirm.

apple_windowsB

Manage macOS windows: move, resize, minimize, fullscreen. Actions: frontmost_app, minimize, minimize_all, maximize, left_half, right_half, fullscreen, close, hide_app, hide_others, center, resize, list_windows, switch_to.

Inputs: action (required), name, width, height, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3/5.0

    Scored across 31 tools

    Disambiguation5/5

    Each tool targets a distinct macOS domain or application (e.g., brightness, Music, Safari, Calendar). Despite some surface-level overlap (e.g., apple_music vs apple_spotify, apple_safari vs apple_chrome), the tool names and action lists clearly separate their purposes, leaving no real ambiguity.

    Naming Consistency5/5

    All tool names follow the exact pattern 'apple_<domain>', using lowercase snake_case throughout (e.g., apple_brightness, apple_sysinfo, apple_textedit). This is perfectly consistent and predictable, making it easy for an agent to infer the tool for a given task.

    Tool Count2/5

    With 31 tools, this server exceeds the 25+ threshold considered 'too many' in the calibration. Even though each tool represents a distinct feature area, the sheer number creates a heavy surface that may overwhelm agents and complicate selection.

    Completeness4/5

    The tool set covers a wide range of macOS apps and system functions, including core apps (Mail, Calendar, Notes, Messages), media (Music, Spotify, Podcasts), browsers (Safari, Chrome), and system controls. Minor gaps exist (e.g., no Apple TV, no HomeKit, some apps have limited actions), but these are not critical for common tasks.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables high-speed native macOS automation for Claude by interacting directly with the Accessibility API, AppleScript, and UI trees instead of using screenshots. It allows users to read app states, click elements, and type text semantically across any macOS application.
      12 npm
      12
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables Claude to automate macOS applications, manage files, control music, send messages, and more through AppleScript.
      29 npm
      1
      GPL 3.0
    • A
      license
      B
      quality
      C
      maintenance
      Enables Claude to interact with Apple apps on macOS including Mail, Calendar, Contacts, Reminders, Notes, and iCloud Drive for personal productivity tasks like triaging email, managing calendar, and cross-app context.
      76
      9
      MIT