Skip to main content
Glama

applemusic-mcp

CI License: MIT

English | 简体中文

An MCP server that lets Claude (or any MCP client) control the Music app on macOS and analyze your library. Just talk to it:

"Play some Leehom Wang" "Make a playlist of the K-pop songs in my library" "What genres do I listen to most?" "Favorite every song in playlists 3, 2, 1, last track first, so Favorite Songs shows them in order"

Everything runs locally on your Mac through JavaScript for Automation (JXA). No Apple Developer account, no API keys, and nothing leaves your machine.

Features

Area

Tools

Playback

now_playing, playback (play / pause / toggle / next / previous / stop), set_player_options (volume, shuffle, repeat)

Search

search_library, search_and_play, play_track

Playlists

list_playlists, get_playlist_tracks, play_playlist, create_playlist, add_to_playlist, remove_from_playlist, compare_playlists

Favorites

set_favorite, favorite_playlist (in order, in batches, optional gap so "sort by Date Favorited" keeps your order)

Stats

listening_stats (overview, top tracks / artists / albums / genres, recently added / played), artist_stats

Limits: search covers your library, not the full Apple Music catalog. Play counts are the lifetime totals the Music app keeps on this Mac, so there's no per-week history. If you mostly listen on your phone, counts may be low.

Related MCP server: Sound

Requirements

  • macOS with the Music app (tested on a recent macOS, Apple Silicon)

  • Claude Desktop or another MCP client

  • uv. The installer sets it up for you.

Install

One-click

  1. Download or clone this repo, e.g. into ~/Documents/applemusic-mcp.

  2. Double-click install.command. If macOS blocks it, right-click > Open. It installs uv, runs a read-only self-test, and adds the server to Claude Desktop's config (it backs up the old config first).

  3. When macOS asks whether the app may control Music, click OK.

  4. Quit Claude Desktop with Cmd+Q, reopen it, and ask "What's playing?"

Manual

git clone https://github.com/bwu109-netizen/applemusic-mcp.git
cd applemusic-mcp
uv sync
uv run python scripts/smoke_test.py   # read-only check

Then add this to ~/Library/Application Support/Claude/claude_desktop_config.json, using your own paths (which uv):

{
  "mcpServers": {
    "apple-music": {
      "command": "/Users/you/.local/bin/uv",
      "args": ["run", "--directory", "/Users/you/applemusic-mcp", "python", "-m", "applemusic_mcp.server"],
      "env": { "PYTHONPATH": "/Users/you/applemusic-mcp/src" }
    }
  }
}

Troubleshooting

  • "Not authorized to send Apple events": open System Settings > Privacy & Security > Automation and turn on Music for Claude (or your terminal).

  • Server keeps disconnecting / No module named applemusic_mcp: if the project lives in an iCloud-synced folder like Documents, iCloud can break a .venv inside it. install.command keeps the venv in ~/.local/share/applemusic-mcp/venv instead. Re-run it.

  • Changes to the code don't show up: Claude Desktop starts the server once. Quit it with Cmd+Q and reopen.

How it works

Claude ──MCP (stdio)──▶ server.py ──osascript -l JavaScript──▶ Music.app
  • src/applemusic_mcp/jxa.py runs JXA via osascript. User input is passed as JSON in argv, never pasted into script source, so song titles with quotes can't break or inject code. Errors come back as readable MCP tool errors.

  • src/applemusic_mcp/server.py defines the tools. Library reads use bulk property fetches (one Apple Event per property, not per track), so even large libraries stay fast.

  • src/applemusic_mcp/stats.py is plain Python aggregation over a 5-minute library cache.

Development

uv sync
uv run pytest

The tests mock the Music app, so they run on Linux too (CI uses Ubuntu). They also run node --check on every generated JXA script to catch syntax errors before they reach a Mac.

PRs welcome. Ideas: Apple Music catalog search via MusicKit, AirPlay device selection, ratings, smart-playlist creation.

License

MIT

Available Tools

17 tools
add_to_playlistB

Add tracks (by id) to a playlist. Tracks already in the playlist are skipped.

Inputs: playlist (required), track_ids (required).

artist_statsC

Everything about one artist in the library: track count, total plays, albums, top songs.

Inputs: artist (required), limit.

compare_playlistsB

Tracks in playlist that are NOT in any of the against playlists (read-only).

Inputs: against (required), playlist (required), limit.

create_playlistB

Create a new empty playlist. Fails if one with that name already exists.

Inputs: name (required), description.

favorite_playlistA

Mark a playlist's tracks as Favorite one by one, in batches.

With reverse=true it walks from the LAST track toward the first. start is the position in that walking order; call again with the returned next_start until done=true. Tracks already favorited are skipped (keeps their earlier timestamp). gap_sec (default 0) optionally spaces out timestamps if the Music app's timestamps turn out to be too coarse to keep the order.

Inputs: playlist (required), count, start, gap_sec, +1 more.

get_playlist_tracksC

List tracks in a playlist (by exact name).

Inputs: playlist (required), limit.

listening_statsA

Analyze the library: play counts, favorite artists/albums/genres, recent activity.

Play counts are lifetime totals tracked by the Music app (no per-period history). Library data is cached for 5 minutes; pass refresh=true to re-read it.

Inputs: view, limit, refresh.

list_playlistsA

List the user's own playlists (regular and smart), with track counts.

Inputs: no named parameters. Returns: result

now_playingA

What's playing right now, plus player state, volume, shuffle and repeat.

Inputs: no named parameters.

playbackC

Control playback. Returns the player state afterwards.

Inputs: action (required).

play_playlistB

Start playing a playlist by name, optionally setting shuffle first.

Inputs: playlist (required), shuffle.

play_trackC

Play a specific track by its id (from search_library or get_playlist_tracks).

Inputs: track_id (required).

remove_from_playlistA

Remove tracks (by id) from a playlist. Does not delete them from the library.

Inputs: playlist (required), track_ids (required).

search_and_playB

Search the library and immediately play the best match. Also returns other candidates.

Inputs: query (required), kind.

search_libraryC

Search the user's Music library. Returns tracks with ids you can play or add to playlists.

Inputs: query (required), kind, limit.

set_favoriteA

Mark (or unmark) tracks as Favorite, one at a time in the given order.

gap_sec waits between tracks so each gets a distinct timestamp. Keep calls under ~40 tracks when using a gap so the call doesn't time out.

Inputs: track_ids (required), gap_sec, favorite.

set_player_optionsA

Set volume (0-100), shuffle on/off, and/or repeat mode. Omit what you don't want to change.

Inputs: repeat, volume, shuffle.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 17 tools

    Disambiguation4/5

    Most tools target distinct resources/actions (now_playing vs playback vs set_player_options; search_library vs search_and_play). Minor overlap exists between set_favorite and favorite_playlist (single vs batch) and between playback and set_player_options for player state, but descriptions clarify the boundaries well.

    Naming Consistency4/5

    Consistent snake_case throughout, but the convention mixes verb_noun (play_track, create_playlist, add_to_playlist) with noun-first/state names (now_playing, playback, listening_stats, artist_stats). Readable and predictable despite the minor stylistic split.

    Tool Count4/5

    17 tools is slightly above the ideal 3-15 sweet spot, but each covers a distinct facet of music playback, library search, playlists, favorites, and stats, so it earns its place rather than feeling padded.

    Completeness4/5

    Strong coverage of playback, search, playlist lifecycle (create/list/get/add/remove/play), favorites, and analytics. Minor gaps: no delete/rename playlist and no explicit queue management, but agents can work around these.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Apple Music playback control, library search, playlist management, and queue operations via MCP.
      2
      MIT
    • F
      license
      Not graded
      quality
      A
      maintenance
      Enables MCP clients like Claude, Cursor, Cline, and Windsurf to search and browse the Apple Music catalog and library, manage playlists and favorites, control playback, and drive the Up Next queue on macOS, Windows, and Linux. It works with just a Mac or an Apple Music subscription, automatically choosing among native Music.app, Safari, Chrome, and Apple Music API engines.
      -
    • F
      license
      Not graded
      quality
      A
      maintenance
      Enables MCP clients to search the catalog, manage playlists, folders, and library items, and control playback, ratings, and the Up Next queue across macOS, Windows, and Linux. It selects among native Music.app, Safari, Chrome, and web API engines so an assistant can drive Apple Music with or without a subscription.
      -