Skip to main content
Glama
Zheng-Kun
by Zheng-Kun
README.md
# Apple Music MCP

[中文文档](README.zh-CN.md)

A safe, structured Model Context Protocol server for the local Apple Music app on macOS.
It lets an MCP client inspect a library, analyze and manage playlists, control playback,
edit supported metadata, and keep a local audit trail. It does not call the online Apple
Music catalog API and never exposes a network transport.

## Highlights

- Structured JSON results with stable Music `persistent ID` values
- Opaque pagination for large libraries and playlists
- Deterministic duplicate, statistics, favorite, recent, stale, and play-count analysis
- Playlist and folder management, metadata updates, downloads, local imports, and exports
- Playback, volume, shuffle, repeat, EQ, and AirPlay control
- Mandatory preview/apply workflow for Music library writes
- Single-use, 10-minute approval tokens and optimistic concurrency checks
- Managed trash, persistent SQLite audit history, and best-effort undo
- No shell interpolation: Python passes bounded base64 JSON to one packaged JXA bridge

## Requirements

- macOS 13 or newer with the Music app
- Python 3.11 through 3.13
- An MCP client that supports stdio servers
- [`uv`](https://docs.astral.sh/uv/) for the recommended installation

Install `uv` with Homebrew if necessary:

```bash
brew install uv
```

## Install and run

From a source checkout:

```bash
uv sync
uv run apple-music-mcp
```

After the package is published, it can be launched without a checkout:

```bash
uvx apple-music-mcp
```

The server communicates only over stdio. It does not bind a TCP port.

### Codex configuration

For a local checkout, add this to `~/.codex/config.toml`, replacing the path if needed:

```toml
[mcp_servers.apple_music]
command = "/Users/kz/Documents/Codex/2026-08-03/mcp-applemusic-py-https-github-com/work/apple-music-mcp/.venv/bin/apple-music-mcp"
```

For a published package:

```toml
[mcp_servers.apple_music]
command = "/opt/homebrew/bin/uvx"
args = ["apple-music-mcp"]
```

### Claude Desktop configuration

```json
{
  "mcpServers": {
    "apple_music": {
      "command": "/opt/homebrew/bin/uvx",
      "args": ["apple-music-mcp"]
    }
  }
}
```

On first use, macOS may ask whether the MCP client may control Music. Allow it in
**System Settings > Privacy & Security > Automation**. The permission belongs to the host
application that launched the MCP server, not to the Python package by itself.

## Tools

### Library and playlists

| Tool | Purpose |
| --- | --- |
| `music_health` | Check macOS, Music, JXA, and writable playlist support |
| `music_get_player_state` | Read current playback and track state |
| `music_get_library_summary` | Read library and playlist counts |
| `music_list_playlists` | Page through playlists, kinds, parents, and capabilities |
| `music_get_playlist` | Resolve one playlist by persistent ID |
| `music_list_playlist_tracks` | Page through ordered playlist membership |
| `music_search_tracks` | Search, filter, sort, and page through local tracks |
| `music_get_tracks` | Resolve an ordered batch of persistent track IDs |
| `music_analyze_library` | Run deterministic library or playlist analysis |

### Playback

| Tool | Purpose |
| --- | --- |
| `music_list_playback_targets` | List AirPlay outputs and EQ presets |
| `music_control_playback` | Play, pause, stop, seek, and navigate tracks |
| `music_set_playback_options` | Set volume, mute, shuffle, repeat, EQ, and outputs |

### Safe changes

| Tool | Purpose |
| --- | --- |
| `music_plan_changes` | Validate changes and return a preview plus approval token |
| `music_get_change_plan` | Read plan state without secret hashes |
| `music_cancel_change_plan` | Cancel a pending plan |
| `music_apply_changes` | Apply an explicitly approved, still-current plan |
| `music_list_changes` | Page through redacted persistent audit history |
| `music_plan_undo` | Preview the reversible part of a previous change |

The server also exposes the `organize_library`, `clean_playlist`, and `build_playlist`
prompts, plus `music://capabilities` and `music://safety` resources.

## Safe write workflow

All Music library writes use two calls. Planning reads the target state, validates object
types and paths, and returns a short-lived token:

```json
{
  "operations": [
    {
      "type": "playlist.create",
      "name": "Focused Work",
      "description": "Built from the local library",
      "track_ids": ["A1B2C3D4", "E5F6A7B8"]
    }
  ]
}
```

The client must show the preview to the user and receive explicit approval before passing
the returned `plan_id` and `approval_token` to `music_apply_changes`. Apply re-reads every
target and rejects the operation with `STALE_PLAN` if Music changed in the meantime.

Supported operation types:

- `playlist.create`, `playlist.update`, `playlist.add_tracks`, `playlist.remove_tracks`
- `playlist.rebuild`, `playlist.archive`, `playlist.restore`, `playlist.purge`
- `folder.create`, `track.update`, `track.download`, `file.import`, `playlist.export`

Ordinary user playlists and folders are writable. Library, Smart, Genius, subscription,
and special playlists are read-only. Rebuilding an existing playlist creates a replacement
with the requested order and archives the original, so the playlist persistent ID changes.

Archive moves an item into a server-managed `MCP Trash` folder. Permanent purge is accepted
only for an item already inside that folder and requires the second confirmation phrase from
the plan. The server never deletes a song from the Music library or its source file.

## Metadata policy

`track.update` accepts common tags, sort tags, rating and favorite state, playback preferences,
and classical work/movement fields. It rejects identifiers, file locations, artwork, account
information, play/skip history, dates, and Music read-only fields. Large or incorrectly typed
values are rejected during planning. Lyrics are omitted from default track results and returned
only when `lyrics` is explicitly requested in `fields`.

Imports require existing absolute regular-file paths. Exports require an absolute path with an
existing writable parent and refuse to overwrite by default. Import undo removes membership
from the target playlist but deliberately leaves the imported library item in place.

## Audit and privacy

Plan and change state is stored at:

```text
~/Library/Application Support/apple-music-mcp/state.sqlite3
```

The directory and database are owner-only (`0700` and `0600`). History is pruned to 30 days
and the latest 500 changes. Tool logs go to stderr and do not log full track lists, lyrics, or
file contents. Stored before-values may include metadata needed for undo, so protect the macOS
account and remove the database when history is no longer needed.

Undo is best effort. Membership can be restored, but Music may append restored tracks in a
different order. Purge, downloads, and exports cannot be undone. Import undo does not remove
the library item.

## Error codes

Expected failures are returned in the normal structured result with `ok: false` and a stable
error code. Common codes include:

- `AUTOMATION_PERMISSION_DENIED`
- `UNSUPPORTED_PLATFORM`
- `NOT_FOUND`
- `READ_ONLY_PLAYLIST`
- `VALIDATION_ERROR`
- `PLAN_EXPIRED`, `PLAN_NOT_PENDING`, `INVALID_APPROVAL_TOKEN`
- `STALE_PLAN`
- `IRREVERSIBLE_CONFIRMATION_REQUIRED`, `PURGE_REQUIRES_TRASH`
- `MUSIC_TIMEOUT`, `MUSIC_ERROR`, `APPLY_FAILED`

## Development

```bash
uv sync
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run pyright
uv build
```

Read-only integration tests are marked `integration`. Isolated write tests are marked
`integration_write`; they create uniquely named objects, retain their exact persistent IDs,
and clean up only those objects. Neither group runs unless explicitly selected.

## Limitations

- Local Music only; no Apple Music catalog search or MusicKit authentication
- No HTTP/SSE server mode
- No library-song deletion, transcoding, artwork writes, or Music window automation
- Music does not expose safe in-place track reordering; rebuilding changes playlist identity
- AirPlay and subscription behavior depends on current Music and account availability

## License

MIT

TDQS

A3.7/5.0

Scored across 18 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: plan lifecycle, library browsing, playback control, and health checks. The plan-related tools are differentiated by their role (create, read, cancel, apply, list, undo), and there is no ambiguity between similar names.

Naming Consistency5/5

All tools follow a consistent snake_case verb_noun pattern prefixed with music_ (e.g., get_playlist, list_playlists, control_playback). The only slight deviation is music_health, but it's a conventional health-check noun and does not disrupt the overall pattern.

Tool Count4/5

18 tools is slightly above the typical 3–15 range, but the count is justified by the domain's breadth (library, playback, change planning, and system health). Each tool serves a distinct function, and there is no redundancy or bloat.

Completeness5/5

The tool set covers the full lifecycle: library retrieval and search, playlist management, playback control and options, change planning with approval and undo, and audit history. No critical operations are missing for a comprehensive Apple Music server.

Maintenance

ActivitySlowing
ResponsivenessNo issues