Unofficial Apple Music MCP v0.2.0
Fixed
- A fully-capable machine was told to go get a credential it did not need.
Adding a catalog track to a playlist, playing a catalog track you don't own,
adding by album, and adding by catalog ID all gated on "is a developer token
configured?" — while every step below those gates already had a credential-free
rail: the public iTunes endpoints for catalog reads, the signed MusicKit helper
for the library write, and Apple Events for the attach. A notarized bundle with
MusicKit authorized could do the work and was refused. Reported by a user who
hit it creating a playlist. - The advice those refusals gave could not be followed. They named
applemusic-mcp login --dev; the console script this package installs is
secure-applemusic-mcp, so pasting it gives "command not found". Several
offered a choice between two identical commands — the fossil of a web-login /
developer-login pair whose first half was removed. Error paths now point at
config(action='signin'), which shows the native Apple Music prompt, stores
nothing, and needs no developer account. No error path sends anyone to a shell
to authenticate. APPLEMUSIC_FORCE_TOKENLESS=1did not stop every write. It is documented
as disabling every API write, and status blames it by name so nobody
misdiagnoses it as missing auth. The MusicKit rails gated on "is the helper
binary on disk", which honoured neither that switch nor the user's Apple Music
consent. Found by security review of this change.- The test suite could mutate a real Apple Music account.
is_available()
reported whether the developer's checkout happened to contain a built, signed,
authorized helper, so on such a machine tests fell through to live, signed
calls. Apple returns HTTP 200 for a rating on a nonexistent id, so nothing
failed loudly. The helper now defaults to absent in tests.
Added
-
A public
lookuprail to match the existingsearchone.searchanswers
"what is called this?";lookupanswers "what IS this id?". Only the first was
wired up, so paths needing the second declared a developer token mandatory —
for catalog facts Apple serves to anyone. This covers album tracklists and
catalog-id resolution. Play-by-catalog-id previously full-text-searched for the
id's digits, which is a different question that occasionally answers the right
one. -
Four MusicKit helper verbs:
add-album(the helper hardcodedids[songs],
which is why album adds still needed a token),rate,playlist-add, and
isrc— the last being the one query no public Apple endpoint answers, since
the iTunes Search API has no ISRC filter. Every identifier is validated in
Python and again in Swift before it reaches a URL. -
Apple-Music-origin playlists can now be edited with no credential. This is
the one operation with no AppleScript equivalent at all — Music.app edits only
the playlists it owns — so_playlist_add's API mode (reached by passing an
explicitp.id) previously required a developer token outright. It now has a
MusicKit rail, including the duplicate check:_get_playlist_track_namesgrew
a second rail rather than letting the tokenless path skip the check, because
silently stacking copies of a track is a bug this codebase has already paid
for once. -
A library id was the last thing that genuinely needed a token.
i.ids
name rows in the user's own library, which no public endpoint can read — but
MusicKit reads them, so this was a missing verb, not a missing capability.
Passing a library id toplaylist(action='add')now works with no credential. -
The release gate had not run since
d4fc279. That commit removed the
amp-api rail, but leftscripts/check_live_env.pyimporting the deleted
module andscripts/preflight.shinvoking a deleted test file.make preflightdied with an ImportError at step 3 on every machine, tokens or
not — while RELEASING.md kept calling it mandatory. Both are rebuilt around
the MusicKit rail: the gate now passes if EITHER write rail works, and a
machine with only MusicKit is a valid release machine (it is the
configuration most users are on).
Added
unrate, so the gate can leave no residue. Without a way to remove a
rating, "exercise the rating path" and "leave the account as you found it"
were mutually exclusive.library-song(resolve ani.id) andcatalog-search(Apple's own
search, consulted only when the free public index comes up empty, so the
process launch is not paid on every query).
Changed
- The API-mode playlist add stopped doing unnecessary work. It POSTed to
/me/libraryand then polled/me/library/searchup to ten times to recover
a library id the playlist endpoint never needed — a write plus up to ten reads
per track, reporting "could not find it in library after adding" whenever
iCloud was slower than one second. A catalog song attaches directly as type
songs, which adds it to the library implicitly; that is what
_auto_search_and_add_to_playlisthas always done for these playlists.
Known gaps
- Ratings and album adds still fall back to the token rail when MusicKit refuses.
test_full_mutation_lifecycleneeds Music.app Automation permission for the
process running pytest, so the gate must be run from an unlocked console
session — as RELEASING.md already requires forpreflight-ui.