Skip to content

Unofficial Apple Music MCP v0.2.0

Choose a tag to compare

@github-actions github-actions released this 28 Aug 00:21

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=1 did 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 lookup rail to match the existing search one. search answers
    "what is called this?"; lookup answers "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 hardcoded ids[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
    explicit p. id) previously required a developer token outright. It now has a
    MusicKit rail, including the duplicate check: _get_playlist_track_names grew
    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 to playlist(action='add') now works with no credential.

  • The release gate had not run since d4fc279. That commit removed the
    amp-api rail, but left scripts/check_live_env.py importing the deleted
    module and scripts/preflight.sh invoking a deleted test file. make preflight died 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 an i. id) and catalog-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/library and then polled /me/library/search up 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_playlist has always done for these playlists.

Known gaps

  • Ratings and album adds still fall back to the token rail when MusicKit refuses.
  • test_full_mutation_lifecycle needs 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 for preflight-ui.