# Applemusic Mcp

> MCP server for Apple Music - manage playlists, control playback, browse your library.

- **Type:** MCP server
- **Install:** `agentstack add mcp-epheterson-applemusic-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [epheterson](https://agentstack.voostack.com/s/epheterson)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [epheterson](https://github.com/epheterson)
- **Source:** https://github.com/epheterson/applemusic-mcp

## Install

```sh
agentstack add mcp-epheterson-applemusic-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# applemusic-mcp

[](https://github.com/epheterson/applemusic-mcp/releases)
[](https://www.python.org/downloads/)
[](https://pepy.tech/project/applemusic-mcp)
[](LICENSE)
[]()
[](https://modelcontextprotocol.io/)

[MCP](https://modelcontextprotocol.io/) server for Apple Music — lets your AI assistant (Claude, Cursor, Cline, Windsurf, or any [MCP client](https://modelcontextprotocol.io/clients)) manage playlists, add music, control playback, and browse your library.

**Works on macOS, Windows, and Linux.**

### Access

| Access | What it does | Platforms |
|---|---|---|
| **Developer token** — recommended | Full Apple Music API: library, playlists, catalog add, recommendations | macOS · Windows · Linux |
| Web token | Same | macOS · Windows · Linux |
| No token | Control the local Music app — play, browse, edit local playlists | macOS |

**Developer token** is included with Apple Developer membership (free for App Store developers), valid 6 months — [setup](#appendix-developer-token-setup). **Web token** is a free fallback captured by `applemusic-mcp signin`; it uses Apple's web-player API the same way open-source clients such as [Cider](https://github.com/ciderapp/Cider-2) and [Sidra](https://github.com/wimpysworld/sidra) do.

## Features

| Feature | macOS | Cross-platform |
|---------|:-----:|:--------------:|
| List playlists | ✓ | ✓ |
| Browse / search library | ✓ | ✓ |
| Create playlists | ✓ | ✓ |
| Love/dislike tracks | ✓ | ✓ |
| CSV/JSON export | ✓ | ✓ |
| Search catalog | ✓ | ✓ |
| **Add songs to library** | ✓ | ✓ |
| **Add tracks to playlists** | ✓ | ✓ |
| Recommendations, charts, radio | ✓ | ✓ |
| Play tracks | ✓ |   |
| Play by URL (album, playlist, song) | ✓ |   |
| Playback control (pause/skip/seek/volume) | ✓ |   |
| Star ratings (1-5) | ✓ |   |
| Remove tracks / delete playlists / folders | ✓ |   |
| Rename / move playlists & folders | ✓ |   |

**Catalog, library, and playlist features run over the Apple Music API** — same on every
platform (sign in once). **Playback** is macOS-only for now (native AppleScript control of
Music.app); cross-platform browser playback is in progress. Play-from-URL on macOS uses a
small AppleScript UI step and needs the screen unlocked + Accessibility permission.

---

## Quick Start (macOS)

**Requirements:** Python 3.10+, Apple Music app with subscription.

**No Apple Developer account needed.** On macOS, playback and local library features work instantly via AppleScript. To add catalog music to your library/playlists (any platform), sign in once — see [Enable catalog features](#enable-catalog-features-sign-in-once) below.

```bash
git clone https://github.com/epheterson/applemusic-mcp.git
cd applemusic-mcp
python3 -m venv venv && source venv/bin/activate
pip install -e .
```

Add to your MCP client config. **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`); **Cursor / Cline / Windsurf** use the same `mcpServers` shape — see your client's docs for the file location.

```json
{
  "mcpServers": {
    "Apple Music": {
      "command": "/full/path/to/applemusic-mcp/venv/bin/python",
      "args": ["-m", "applemusic_mcp"]
    }
  }
}
```

**That's it!** Restart your client and try: "List my Apple Music playlists" or "Play my favorites playlist"

> **Windows/Linux users:** AppleScript playback requires macOS, but catalog/library/playlist
> features work cross-platform — just [sign in](#enable-catalog-features-sign-in-once).

---

## Enable Catalog Features (sign in once)

Adding catalog music to your library and playlists runs over the Apple Music API. Sign in once:

```bash
applemusic-mcp signin     # opens Chrome to music.apple.com; sign in once
applemusic-mcp status     # verify
```

Captures your `media-user-token` from a local, signed-in Chrome profile (your password never
touches this tool); uses your installed Chrome when present. The sign-in persists.

Have an Apple Developer membership? A generated token (6-month, sanctioned) is preferred — see
[Appendix: Developer token setup](#appendix-developer-token-setup).

### Add to Your MCP Client (Windows/Linux)

Same `mcpServers` shape works across clients (Claude Desktop, Cursor, Cline, Windsurf, etc.) — only the config file path differs.

**Claude Desktop:**
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "Apple Music": {
      "command": "/full/path/to/applemusic-mcp/venv/bin/python",
      "args": ["-m", "applemusic_mcp"]
    }
  }
}
```

### Optional Preferences

Add to config.json:
```json
{
  "preferences": {
    "auto_search": true,
    "clean_only": false,
    "fetch_explicit": false,
    "reveal_on_library_miss": false
  }
}
```

- `auto_search`: Enables catalog search + library-add fallback for `playlist(action="add")` when a track isn't already in the user's library (default: false to avoid unintended library writes — set to true for "fill this playlist" workflows). On macOS works without an API token by falling back to Music.app UI automation (requires display + Accessibility permissions for the host process).
- `clean_only`: Filter explicit content, for `search_catalog`, `search_library`, `browse_library` (default: false)
- `fetch_explicit`: Fetch explicit status (cached), for `get_playlist_tracks`, `search_library`, `browse_library` (default: false)
- `reveal_on_library_miss`: Open catalog tracks in Music app, for `play` (default: false)

---

## Usage Examples

**Playlist management:**
- "List my Apple Music playlists"
- "Create a playlist called 'Road Trip' and add some upbeat songs"
- "Add Hey Jude by The Beatles to my Road Trip playlist"
- "Remove the last 3 tracks from my workout playlist"
- "Export my library to CSV"

**Folder organization (macOS):**
- "Create a folder called Genres and put subfolders for Rock, Jazz, and Electronic in it"
- "Move my Road Trip playlist into the Summer folder"
- "Show me my folder hierarchy"
- "Where is my workout playlist?"

**Discovery & playback (macOS):**
- "What have I been listening to recently?"
- "Play my workout playlist on shuffle"
- "Skip to the next track"
- "What's playing right now?"

**With API enabled:**
- "Search Apple Music for 90s alternative rock"
- "Find songs similar to Bohemian Rhapsody and add them to my library"
- "What are the top charts right now?"
- "Get me personalized recommendations"

---

## Tools

### `playlist(action=...)`
Playlist and folder operations - list, manage tracks, create, copy, remove (macOS), delete (macOS), rename (macOS), folder management (macOS)

| Action | Parameters | Description | Platform |
|--------|-----------|-------------|----------|
| `list` | `format`, `export`, `full` | List all playlists | All |
| `tracks` | `playlist`, `filter`, `limit`, `offset`, `format`, `export`, `full`, `fetch_explicit` | Get playlist tracks with filter/pagination | All (by-name: macOS) |
| `search` | `query`, `playlist` | Search tracks in playlist | All |
| `create` | `name`, `description`, `folder` | Create playlist and/or folder. `folder` supports slash paths (e.g. `Summer/Chill`). | All |
| `add` | `playlist`, `track`, `album`, `artist`, `allow_duplicates`, `verify`, `auto_search` | Smart add: auto-search catalog, UI fallback when no API token, skip duplicates | All (by-name: macOS) |
| `copy` | `source`, `new_name` | Copy playlist to editable version | All (by-name: macOS) |
| `move` | `playlist`, `folder` | Move playlist/folder into a folder path. `folder=""` moves to root (recreates playlist*). | macOS |
| `remove` | `playlist`, `track`, `artist` | Remove track(s) from playlist | macOS |
| `delete` | `playlist` or `folder` | Delete a playlist or folder (supports slash paths) | macOS |
| `rename` | `playlist` or `folder`, `new_name` | Rename a playlist or folder | macOS |
| `path` | `playlist` or `folder` | Get full path of a playlist/folder. No args = show full hierarchy. | macOS |

**Folder paths:** Use `/` for nesting: `create(folder="Music/Genres/Jazz")` creates all levels. Works with `move`, `delete`, and `create`.

**Note:** The Apple Music API only supports creating single-level folders. Nested paths, move, delete, rename, tree, and path operations require macOS (AppleScript). Snapshots on macOS capture full folder hierarchy.

*\*Move-to-root limitation: Music.app's AppleScript interface cannot move playlists out of folders. `folder=""` recreates the playlist at root with the same tracks — the playlist's persistent ID will change. Moving INTO folders preserves the ID.*

**Examples:**
```python
playlist(action="list")
playlist(action="create", name="Road Trip", description="Summer vibes")
playlist(action="create", folder="Summer/Chill")                           # nested folders
playlist(action="create", name="Road Trip", folder="Summer/Chill")         # playlist in nested folder
playlist(action="move", playlist="Road Trip", folder="Summer/Chill")       # into nested folder
playlist(action="move", playlist="Road Trip", folder="")                   # back to root
playlist(action="move", playlist="Chill", folder="Archive")                # folder into folder
playlist(action="path")                                                    # show full hierarchy
playlist(action="path", playlist="Road Trip")                              # "Summer/Chill/Road Trip"
playlist(action="path", folder="Chill")                                    # "Summer/Chill"
playlist(action="delete", folder="Summer/Chill")                           # delete nested folder
playlist(action="rename", folder="Summer", new_name="Summer 2026")
playlist(action="add", playlist="Road Trip", track="Hey Jude", artist="Beatles")
```

**Unified `track` parameter** auto-detects and batches: a single name/ID, a comma-separated CSV, a newline-separated list (one per line — safe for titles containing commas), or a JSON array (`["A","B"]` or `[{"name":"A","artist":"X"}]`). Add entire albums with `album` parameter.

### `library(action=...)`
Library management - search, add, browse, favorites (macOS), rate, recently played/added, remove (macOS), snapshot (macOS)

| Action | Parameters | Description | Platform |
|--------|-----------|-------------|----------|
| `search` | `query`, `types`, `limit`, `format`, `export`, `full`, `fetch_explicit`, `clean_only` | Search your library (fast local on macOS) | All |
| `add` | `track`, `album`, `artist` | Add tracks/albums from catalog | All |
| `browse` | `item_type`, `limit`, `offset`, `format`, `export`, `full`, `fetch_explicit`, `clean_only` | List songs/albums/artists/videos | All |
| `favorites` | `limit`, `offset`, `format`, `export`, `full`, `fetch_explicit`, `clean_only` | List songs marked Favorite (loved) | macOS |
| `recently_played` | `limit`, `format`, `export`, `full` | Recent listening history | All |
| `recently_added` | `limit`, `format`, `export`, `full` | Recently added content | All |
| `rate` | `rate_action`, `track`, `artist`, `stars` | Love/dislike/clear/get/set ratings | All (stars/clear: macOS) |
| `remove` | `track`, `artist` | Remove track(s) from library | macOS |
| `snapshot` | `query` | Library integrity checking — captures tracks, playlists, and folder hierarchy | macOS |

**Snapshot sub-commands** via `query`:

| Query | Description |
|-------|-------------|
| _(empty)_ | Diff current state from baseline, or take initial baseline |
| `new` | Reset baseline to current state |
| `history` | View recorded changes over time |
| `list` | List all saved snapshot/diff files |
| `delete FILENAME` | Delete a specific diff file |

**Examples:**
```python
library(action="search", query="Beatles", types="songs", limit=25)
library(action="add", album="Abbey Road", artist="Beatles")
library(action="recently_played", limit=30)
library(action="rate", rate_action="love", track="Hey Jude")
```

### `catalog(action=...)`
Catalog search and details - search, albums, songs, artists, genres, stations

`search` accepts fuzzy queries — typos, partial lyrics, vague descriptions ("whistling beatles song"). On macOS it falls back to Music.app's built-in UI search when no API token is available, so you can find a half-remembered song without credentials.

| Action | Parameters | Description | Platform |
|--------|-----------|-------------|----------|
| `search` | `query`, `types`, `limit`, `format`, `export`, `full`, `clean_only` | Search Apple Music catalog (fuzzy; UI fallback on macOS when no API token) | All |
| `album_tracks` | `album`, `artist`, `limit`, `offset`, `format`, `export`, `full` | Get album tracks (by name or ID) | All |
| `album_details` | `album`, `artist`, `format`, `export`, `full` | Full album metadata + track listing | All |
| `song_details` | `song_id` | Full song metadata | All |
| `artist_details` | `artist` | Artist info and discography | All |
| `song_station` | `song_id` | Get radio station for song | All |
| `genres` | - | List all available genres | All |

**Examples:**
```python
catalog(action="search", query="90s alternative", types="songs", limit=50)
catalog(action="album_tracks", album="Abbey Road", artist="Beatles")
catalog(action="album_details", album="GNX", artist="Kendrick Lamar")
catalog(action="artist_details", artist="The Beatles")
```

### `discover(action=...)`
Discovery and recommendations - personalized stations, charts, top songs, similar artists

| Action | Parameters | Description | Platform |
|--------|-----------|-------------|----------|
| `recommendations` | `format`, `export`, `full` | Personalized recommendations | All |
| `heavy_rotation` | `format`, `export`, `full` | Your frequently played | All |
| `charts` | `chart_type`, `format`, `export`, `full` | Apple Music charts | All |
| `top_songs` | `artist` | Artist's popular songs | All |
| `similar_artists` | `artist` | Find similar artists | All |
| `search_suggestions` | `term` | Autocomplete suggestions | All |
| `personal_station` | - | Your personal radio station | All |

**Optional:** All catalog-based discover actions (`charts`, `top_songs`, `similar_artists`, `song_station`) accept an optional `storefront` parameter to query other regions without changing your default storefront.

**Examples:**
```python
discover(action="recommendations")
discover(action="charts", chart_type="songs", storefront="it")  # Italy charts
discover(action="top_songs", artist="The Beatles")
```

### Playback (macOS only)
| Action | Description | Method |
|--------|-------------|--------|
| `playback(action="play", ...)` | Play track, playlist, album, or URL | API + AS |
| `playback(action="control", ...)` | Play, pause, stop, next, previous, seek | AppleScript |
| `playback(action="now_playing")` | Current track info and player state | AppleScript |
| `playback(action="settings", ...)` | Get/set volume, shuffle, repeat | AppleScript |
| `playback(action="airplay", ...)` | List or switch AirPlay devices | AppleScript |

`play` accepts ONE of: `track`, `playlist`, `album`, or `url`. Use `shuffle=True` for shuffled playback. Response shows source: `[Library]`, `[Catalog]`, `[Catalog→Library]`, `[UI Catalog]` (UI played a track API resolved), or `[UI Search]` (UI played a track only the UI search found). Catalog items can be added first (`add_to_library=True`) or opened in Music (`reveal=True`).

**URL playback** — albums, playlists (including personal `pl.u-`), and songs via `?i=`:
```
playback(action="play", url="https://music.apple.com/us/album/ok-computer/1097861387")
playback(action="play", url="https://music.apple.com/us/album/cowboy-carter/1738363766?i=1738363961")
playback(action="play", url="https://music.apple.com/us/playlist/todays-hits/pl.f4d106fed2bd41149aaacabb233eb5eb")
```
Uses UI scripting (requires display + Accessibility permissions). The mouse cursor may briefly move for `?i=` track selection.

### Utilities

| Tool | Description | Platform |
|------|-------------|----------|
| `config(action=...)` | Preferences, storefronts, cache, audit log | All |
| `check_auth_status()` |

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [epheterson](https://github.com/epheterson)
- **Source:** [epheterson/applemusic-mcp](https://github.com/epheterson/applemusic-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-epheterson-applemusic-mcp
- Seller: https://agentstack.voostack.com/s/epheterson
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
