
Apple Music Playlist Curator
io.github.Z-Han-Z由 GitHub 账号 Z-Han-Z 发布v1.5.0更新于 Oct 24, 2026
Deep Apple Music curation: language-led selection, catalog grounding, and thoughtful listening flow.
概览
本地 MCP 服务器,让助手搜索 Apple Music 曲库、核实候选曲目、审查与排序歌单,并在用户账户中创建或修改歌单。
- 可以做什么
- 搜索 Apple Music 曲库并把候选曲目解析为确切录音,标记重复项和可疑的现场版或重制版,同时查询账户与登录状态。列出、查看、创建歌单,向歌单添加曲目,以及删除歌单。审查歌单元数据(长度、艺人集中度、流派、年代、重复项),并基于速度、调性、能量与情绪值分析曲目衔接。可在用户指定的叙事分段内可选地重新排序,并读取最近播放记录与播放次数。
- 适用场景
- 适合希望助手把自然语言需求变成有据可查的 Apple Music 歌单,或检查、审查和改进现有歌单与收听记录的场景。适合已订阅 Apple Music、并愿意完成一次 Apple ID 登录的用户。
- 运行要求
- 以 stdio 本地进程运行;需要 Python 3.10+,支持 Windows、macOS 和 Linux,可通过 uvx 或 pip 从 apple-music-playlists 包启动。需通过 am-playlist login 命令完成一次 Apple ID 登录,凭据保存在本地应用配置中。流程分析需要访问 Apple Music 及第三方音频特征服务的网络连接。
安装
在 SourceWeft 中
- 打开 控制台中的 Apple Music Playlist Curator,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
Apple Music MCP Curator
网易云(NCM)公开预览:简体中文使用说明。
[Apple Music MCP — natural-language playlists grounded in Apple Music]
[Tests] [Container] [Release] [PyPI] [MCP Registry] [Python 3.10+] [License: MIT] [Glama quality score]
English | 简体中文 | 繁體中文 | 日本語 | 한국어 | Español | Português do Brasil | Deutsch | Français
Deep playlist curation for Apple Music: describe a feeling, scene, era, listening purpose, or sound; your agent grounds the selection and shapes its flow into a satisfying listening experience. You define any narrative beats; without that request, no story arc is imposed.
See a 12-track curation demo: 22 grounded candidates become a deliberately requested three-act story—and show why a lower optimizer cost can make a playlist worse. It is one possible shape, not a default template.
Pure Python standard library — no pip install required to run, and no Apple Developer Program
membership needed. Requires Python 3.10+ and works on Windows / macOS / Linux.
The primary interface is the local am-mcp stdio server. The language model already running in
your MCP client interprets the brief and chooses candidates; this project searches the Apple Music
catalog, resolves exact tracks, and performs account operations. There is no bundled model, LLM
API key, artist list, or fixed theme. The CLI remains available for login, diagnostics, scripting,
audits, and advanced sequencing.
Why this project
- The brief stays semantic. The host LLM reasons directly about imagery, mood, lyrical angle, era, cultural context, contrast, and the role of each song. It is not reduced to a handful of user-supplied sliders or an opaque theme-fit number.
- Selection and sequencing stay separate. The model decides what belongs; measured BPM, key, energy, valence, and loudness can diagnose transitions or refine flow within beats you specify— otherwise, no global arc is imposed.
- Every candidate is grounded. Catalog resolution catches missing tracks, duplicates, wrong artists, and suspicious live/remastered versions before the dry run and final create step.
- Listening evidence remains evidence. Replay history, recent plays, dates, and play counts can inform curation without silently becoming an algorithmic definition of the user's taste.
- Local and private by design. The server runs on your machine; credentials stay in the local app config, and there is no bundled model, telemetry service, or extra LLM API key.
- Portable MCP stdio. Works with Codex, Claude, Cursor, VS Code/Copilot, Gemini CLI, Windsurf, Cordis/DSH, Harness, and other clients that can launch a local stdio server.
Quick start
Recommended — install the MCP stdio service:
Already use uv? Run the published package without a permanent install:
For an MCP client, the equivalent Registry-aligned configuration is:
Register am-mcp in the client. The common configuration shape is:
Then describe the result, not the implementation:
Create a 25-track late-night driving playlist: atmospheric alternative R&B and electronic, mostly from the last ten years, no live versions, with a calm landing.
Clients with MCP Prompt support can select create_playlist_from_description. In every other
client, send the same request in chat: the server instructions and typed tools expose the same
status → candidate pool → catalog grounding → direct comparison → dry-run → create workflow.
From a clone (nothing to install):
Installation also puts the CLI and MCP commands on your PATH:
For development, pip install -e . from a clone makes edits take effect without reinstalling.
See SETUP.en.md for the credential walkthrough (three ways to get the user token, including a zero-dependency one).
A real curation demo: A Machine Dreams It Is Human
This is deliberately harder than “make me a workout playlist.” The brief asks music to carry a plot, and some of its constraints cannot be expressed as tempo or mood sliders:
Build a 12-track, three-act story in which a machine wakes in a city, mistakes attention for intimacy, asks to be touched, becomes vulnerable, and sees dawn. Cross electronic music and art pop from the late 1970s to the present; use one track per artist, studio recordings only, and let the voices become progressively more human. The ending must feel quiet and earned, not merely low-energy.
The run below used the public US Apple Music catalog on 2026-09-23. It did not read or write a private library.
Each title below opens the exact US catalog recording returned by the resolver, so the sequence can be auditioned rather than taken on trust.
The interesting failure happened during ordering. With only the three acts locked, the numerical
optimizer cut the measured cost from 48.28 to 14.88 — but put Retrograde after the dawn and
made All Is Full of Love answer a request that had not happened yet. That is cheaper and worse.
The host model therefore added semantic beat boundaries (request → answer, return → dawn) and
let am_optimize_order make only local changes inside those boundaries. Selection and story stayed
linguistic; BPM, key, energy, and valence remained supporting evidence.
Final dry-run input
This is the normal MCP workflow: the host model interprets the brief and proposes more candidates
than it needs; am_resolve_candidates grounds them; the model chooses tracks and interprets narrative roles only when the brief calls for them;
am_optimize_order optionally checks local flow without crossing semantic boundaries; and
am_create_playlist(dry_run=true) verifies the exact final recordings before the write.
To compare that workflow with a one-shot baseline, use the six difficult multilingual briefs and blind-listening protocol in examples/. The suite provides auditable constraints, not predetermined “correct” songs.
What's in the box
Supporting modules:
All three analysis modules are importable as libraries:
MCP tools
The standard prompt create_playlist_from_description asks for a natural-language brief and
optional name, track count, and response language. Curation stays in the host model; the tools are
the grounded Apple Music execution layer:
am_status · am_search_songs · am_resolve_candidates · am_list_playlists · am_show_playlist ·
am_create_playlist · am_add_tracks · am_delete_playlist ·
am_audit_playlist · am_analyze_flow · am_optimize_order ·
am_recently_played · am_top_played
am_resolve_candidates grounds a generous LLM-proposed pool in real catalog metadata, flags
duplicates and suspicious versions, and deliberately does not score theme fit. The host model
compares candidates directly with the user's words and explains their playlist roles.
am_analyze_flow diagnoses transitions; am_optimize_order can optionally refine ordering inside
already chosen narrative blocks. It never decides which songs belong in the playlist.
Mount it in a Cordis agent preset with the template in preset/, or wire it into
any other MCP client with:
Complete tested examples for Codex, Claude, Cursor, VS Code/Copilot, Gemini CLI, Windsurf, Docker, Cordis/DSH, and Harness are in docs/client-setup.md.
Build the non-root local container with:
The client must run it attached with docker run --rm -i; mount only the app config directory and
a writable cache as shown in the client guide. Config stays writable so token refresh can persist.
Never bake Apple credentials into the image.
Tests
The suite is entirely offline — no network, no credentials. Two kinds:
- Behaviour: the pure math that decides what "sounds good" — Camelot mapping, BPM folding, arc classification, each adjacency penalty asserted in isolation, annealing determinism and the block-order constraint. All six narrative archetypes must classify as themselves.
- Structural regressions, each pinned to a bug that actually shipped: no hardcoded catalog
region, exactly one
catalog_meta, no non-None--storefrontdefault, cache outside the repo, every MCP tool wired to a handler, and the optimizer free of platform imports.
They earn their keep immediately — the suite caught a syntax error in a file written minutes earlier, before it was ever run.
The interesting part: audio features
Apple's catalog API exposes no audio features at all — no tempo, key, loudness, energy, or
valence. Spotify's audio-features endpoint was shut off for new apps on 2024-11-27, and
AcousticBrainz retired in 2022.
playlist_flow.py bridges the gap with a free, key-less chain built on ISRC, which Apple does
return:
Results are cached locally, so the network cost is paid once per playlist.
Coverage is reported, never silently dropped. Every consumer prints a funnel saying why each track could not be measured:
That distinction is the point. No ISRC means the chain cannot start at all — a different feature source will not help. Not in the source means the ISRC is fine and switching sources (or analysing the audio locally) would fix it. Collapsing both into "missing features" discards the only information that tells you what to do next.
It matters more than it looks: tempo / key / energy / valence are the only things the
adjacency rules and the arc can act on, so coverage is the ceiling on how good an ordering can
be. At 60% coverage, four positions in ten were never evaluated — while the cost number still
looks excellent. The optimizer therefore prints coverage above its cost lines, and warns below 90%.
Sequencing rules the optimizer enforces
Derived from the research collected in docs/ — including a PLOS ONE study in which
130 music professionals sequenced albums, and a randomized trial on mood-adaptive music ordering.
Hard adjacency rules
- No two slow tracks adjacent
- Avoid "only slightly slower" transitions (0–12% drop makes the slower track feel like it drags)
- Adjacent tracks must not be similar in both tempo and key
- No unjustified large BPM jumps (>40%); no jarring energy shifts under incompatible keys
These four have exactly one definition, in playlist_core.check_pair(), and both the audit and
the optimizer call it. They used to be implemented twice, and the copies disagreed: the audit
called a track "slow" below the tempo's 25th percentile while the optimizer used a fixed 100 BPM,
and the audit never checked the BPM-jump rule at all. That is a tool diagnosing against one
standard and repairing against another — so the count it reported could not be trusted.
Note on the "slow" threshold. It is absolute (100 BPM), not data-driven, deliberately: the optimizer evaluates the same sequence thousands of times while annealing, and a percentile threshold would drift as the permutation changes, so the cost would never settle. The cost is that a uniformly slow playlist flags every adjacent pair — that is real, not a sequencing failure, and the report says so.
Global narrative arc is optional. With no --arc, the optimizer only considers local
adjacency and does not impose an emotional or tempo trajectory. The host LLM should interpret a
free-form story from the brief and preserve its order through blocks; use a named preset only when
the user explicitly asks for that kind of curve.
Six optional shapes: rags-to-riches, tragedy, man-in-a-hole, icarus, cinderella,
oedipus. The target curve and the shape the audit classifies come from the same table in
playlist_core.ARCHETYPES. The audit may still report which preset a playlist resembles; that
diagnosis does not make the preset a recommendation or an ordering target.
When a preset is explicitly requested, valence / energy / loudness follow its emotional
trajectory and tempo uses a separate inverted-U target. With no --arc, neither global target is
applied.
An arc cost is a distance from an explicitly requested feature curve, not a measure of whether a playlist is good. Coverage limits what it describes, and a lower cost cannot override the brief or prove that one sequence sounds better.
The optimizer preserves your grouping (movements / eras / moods) and only reorders within groups, so thematic structure survives the loudness tuning. Drop the grouping and it reorders freely — measurably "smoother", at the cost of your narrative.
Example from a real run: cost 104.46 → 19.41 with grouping preserved, → 1.28 ungrouped.
Gotchas worth knowing before you debug
- Responses can be gzip-compressed even when you never sent
Accept-Encoding. Decoding the raw bytes as UTF-8 yields garbage that looks like an empty body. (This is fixed inam_playlist.py.) DELETEonly works onamp-api.music.apple.com. The documented hostapi.music.apple.comreturns 401 for playlist and library-song deletion.- Do not send
x-apple-client-versionto amp-api — it turns into a 500. - Creating a playlist also adds its tracks to the library. Deleting the playlist does not remove them.
- BPM estimates have octave ambiguity (90 vs 180 for the same track). Fold into
[70,160)before comparing, or "two slow tracks adjacent" over-reports by ~4×. - Never pass
"Title - Artist"straight into catalog search — you get live/remastered takes. Search on the space-separated form and score versions afterwards. - An artist missing from a storefront's search ≠ the song is unavailable there. Look it up by ISRC.
- Only the client that created a playlist can modify it — Apple-side restriction.
More in docs/apple-music-api-notes.md and
skill/reference.md.
Documentation
For the complete Simplified Chinese guide, see README_ZH_CN.md.
Community
- Contributing — development workflow, architecture boundaries, and review expectations
- Support — where to ask questions, report bugs, or propose features
- Code of Conduct — participation standards and private reporting route
- Security policy — supported versions and confidential vulnerability reporting
License
MIT — see LICENSE.
Unofficial community tooling. Not affiliated with or endorsed by Apple. Uses your own Apple Music account for personal use; follow Apple's terms of service.
来源:README.md,提交 12f82de
工具
0版本历史
2- v1.5.0最新Sep 28, 2026
- v1.4.0Sep 23, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分