关于 Apple Music Playlist Curator
Apple Music 播放列表策划 MCP 服务,将自然语言描述转为经过目录核验和编排的曲目列表,面向使用 MCP 客户端的听众。由客户端中的 LLM 负责理解语义,服务负责搜索、匹配和账户操作。
主要功能
- 01按描述搜索 Apple Music 曲目
- 02核验曲目版本与重复项
- 03分析播放列表元数据和音频特征
- 04按指定叙事边界调整曲序
- 05查看最近播放与播放次数
- 06创建、编辑和删除播放列表
适用场景
- 01按氛围或场景策划播放列表
- 02确认候选曲目对应准确录音
- 03检查曲目衔接并调整顺序
- 04依据播放记录辅助选曲
MCP 相关
通过本地 stdio MCP 服务向客户端提供 Apple Music 搜索、曲目核验、播放列表管理和分析工具。客户端中的 LLM 负责理解策划要求并选择曲目。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
14收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
Apple Music MCP 策展工具
网易云(NCM)公开预览:简体中文使用说明。

English | 简体中文 | 繁體中文 | 日本語 | 한국어 | Español | Português do Brasil | Deutsch | Français
为 Apple Music 深度策划歌单:描述一种感觉、场景、年代、聆听目的或声音;你的 Agent 会基于这些信息筛选曲目,并安排播放顺序,打造令人满意的聆听体验。你可以指定任意叙事节拍;如果没有提出此类要求,就不会强加故事弧线。
观看 12 首曲目的策展演示:22 首经过核实的候选曲目,组成一个按明确要求打造的三幕故事,并展示了为什么较低的优化器成本可能让歌单变得更糟。这只是其中一种可能形式,并非默认模板。
纯 Python 标准库——运行无需 pip install,也无需加入 Apple Developer Program。需要 Python 3.10+,支持 Windows / macOS / Linux。
主要接口是本地 am-mcp stdio 服务。MCP 客户端中已运行的语言模型会解读需求并选择候选曲目;本项目负责搜索 Apple Music 曲库、匹配确切曲目并执行账户操作。项目不包含随附模型、LLM API 密钥、艺人列表或固定主题。CLI 仍可用于登录、诊断、脚本编写、审计和高级排序。
understand → curate → ground → sequence with intent → dry-run → create
为什么选择这个项目
- 简述始终聚焦语义。 宿主大模型会直接推理意象、情绪、歌词角度、时代、文化背景、对比,以及每首歌曲的作用。它不会被简化为少数几个由用户提供的滑块,也不会被浓缩成不透明的主题匹配分数。
- 选曲与排序各自独立。 模型决定哪些歌曲适合入选;测得的 BPM、调性、能量、效价和响度可以用于诊断过渡,或在你指定的节拍范围内优化流畅度——否则不会强加全局曲线。
- 每个候选都有依据。 在试运行和最终创建之前,目录解析会检查曲目缺失、重复、艺人错误,以及可疑的现场版/重制版。
- 聆听记录仅作为参考。 重播历史、近期播放记录、日期和播放次数可以为策划提供参考,但不会悄然变成算法对用户品味的定义。
- 从设计上保护本地隐私。 服务在你的设备上运行;凭据保存在本地应用配置中,不捆绑模型、遥测服务,也不需要额外的大模型 API 密钥。
- 可移植的 MCP stdio。 适用于 Codex、Claude、Cursor、VS Code/Copilot、Gemini CLI、Windsurf、Cordis/DSH、Harness,以及其他能够启动本地 stdio 服务的客户端。
快速开始
推荐 — 安装 MCP stdio 服务:
pip install apple-music-playlists
am-playlist status
am-playlist login # one-time Apple ID sign-in
已经在使用 uv?无需永久安装即可运行已发布的软件包:
uvx --from apple-music-playlists am-playlist status
uvx --from apple-music-playlists am-playlist login
uvx --from apple-music-playlists am-mcp
对于 MCP 客户端,符合 Registry 规范的等效配置如下:
{ "mcpServers": { "applemusic": { "command": "uvx",
"args": ["--from", "apple-music-playlists", "am-mcp"],
"env": { "PYTHONIOENCODING": "utf-8" } } } }
在客户端中注册 am-mcp。常见的配置形式如下:
{ "mcpServers": { "applemusic": { "command": "am-mcp",
"env": { "PYTHONIOENCODING": "utf-8" } } } }
接下来描述你想要的结果,而不是实现方式:
创建一个适合深夜驾车的 25 首歌曲播放列表:氛围感强的另类 R&B 和电子乐,主要选自过去十年,不要现场版,结尾要平和。
支持 MCP Prompt 的客户端可以选择 create_playlist_from_description。其他客户端则可以在聊天中发送相同的请求:服务说明和类型化工具会提供相同的工作流:状态 → 候选曲目池 → 目录核验 → 直接比较 → 试运行 → 创建。
从克隆版本开始(无需安装):
git clone https://github.com/Z-Han-Z/apple-music-playlists.git
cd apple-music-playlists
python am_playlist.py status # auto-fetches the developer token
python am_playlist.py login # one-time Apple ID sign-in (~6 months validity)
python am_mcp_server.py # register this absolute script path in the MCP client
安装后,CLI 和 MCP 命令也会添加到你的 PATH 中:
am-playlist status # the CLI
am-playlist login # one-time Apple ID sign-in
am-mcp # the MCP stdio server
开发时,从克隆版本运行 pip install -e .,即可让修改立即生效,无需重新安装。
凭据设置指南(三种获取用户令牌的方法,包括一种零依赖方法)请参见 SETUP.en.md。
一个真实的策展示例:一台机器梦见自己是人类
这比“给我做一份健身歌单”难得多。需求要求音乐承载剧情,而其中一些约束无法用节奏或情绪滑块来表达:
创作一个由 12 首曲目组成、分为三幕的故事:一台机器在城市中醒来,把关注误认为亲密,提出触碰请求,变得脆弱,并看见黎明。横跨 20 世纪 70 年代末至今的电子音乐和艺术流行乐;每位艺术家只选一首曲目,且仅使用录音室录音;让人声逐渐变得更像人类。结尾必须安静而令人信服,而不只是能量低。
以下运行使用了 2026-09-23 的美国 Apple Music 公共目录。它没有读取或写入私人音乐库。
22 LLM-proposed candidates
└─ 22 catalog matches returned exact title, artist, album, date, ISRC, and version metadata
├─ rejected: “Open Eye Signal (Mixed)” — resolved to a 2025 DJ Mix, not the studio cut
├─ rejected: “Deeper Understanding (2018 Remaster)” — not the requested original recording
└─ 12 final selections
Final create dry-run: 12/12 matched; no write performed
Audio-feature coverage: 12/12 usable (100%)
Flow cost, narrative locks: 44.14 → 41.14
下面每个曲目标题都会打开解析器返回的美国目录中的确切录音,因此可以试听这个顺序,而不是只能盲目信任。
| 幕 | 有依据的顺序 | 这个顺序的作用 |
|---|---|---|
| I — 启动 | The Robots — Kraftwerk Technopolis — Yellow Magic Orchestra Kid A — Radiohead | 先是一个身体,然后是一座城市,接着是一个不稳定的第一人称声音。 |
| II — 欲望 | Oblivion — Grimes Digital Witness — St. Vincent Is It Cold In The Water? — SOPHIE Touch — Daft Punk & Paul Williams All Is Full of Love — Björk | 公共关注逐渐变成身体风险、蜕变、触碰请求,最终得到回应。 |
| III — 重返 | Cellophane — FKA twigs Retrograde — James Blake Long Road Home — Oneohtrix Point Never An Ending (Ascent) — Brian Eno | 合成外壳失效;退避变成归来,故事最终落在黎明。 |
有意思的失败发生在排序阶段。仅锁定三幕时,数值优化器将测得的成本从 48.28 降到了 14.88,却把 Retrograde 放在黎明之后,还让 All Is Full of Love 回应一个尚未发生的请求。成本更低,效果却更差。因此,宿主模型添加了语义节拍边界(request → answer、return → dawn),并让 am_optimize_order 只在这些边界内进行局部调整。曲目选择和故事仍由语言判断;BPM、调性、能量和效价只是辅助证据。
最终试运行输入
[
"The Robots - Kraftwerk",
"Technopolis - Yellow Magic Orchestra",
"Kid A - Radiohead",
"Oblivion - Grimes",
"Digital Witness - St. Vincent",
"Is It Cold In The Water? - SOPHIE",
"Touch - Daft Punk",
"All Is Full of Love - Björk",
"Cellophane - FKA twigs",
"Retrograde - James Blake",
"Long Road Home - Oneohtrix Point Never",
"An Ending (Ascent) - Brian Eno"
]
这是常规的 MCP 工作流:宿主模型解读需求,并提出多于所需数量的候选项;am_resolve_candidates 为候选项提供依据;只有在需求需要时,模型才选择曲目并解读其叙事角色;am_optimize_order 可选择检查局部流畅度,但不会跨越语义边界;am_create_playlist(dry_run=true) 则会在写入前核验最终录音。
若要将此工作流与一次性基线进行比较,请使用 examples/ 中六份难度较高的多语言需求和盲听流程。该套件提供可审计的约束,而非预先指定的“正确”歌曲。
包含内容
| 文件 | 用途 |
|---|---|
am_playlist.py | 核心功能:令牌管理、目录搜索、创建 / 编辑 / 删除播放列表、曲目解析 |
am_mcp_server.py | 主要的 MCP stdio 服务:一个描述转播放列表提示词,以及 14 个工具 |
playlist_audit.py | 元数据审计:长度、艺人集中度、流派、年代、时长、重复项、间奏曲 |
playlist_flow.py | 音频特征审计:BPM / 调性 / 响度 / 能量 / 效价、相邻曲目检查、弧线形状 |
playlist_optimize.py | 根据测量规则进行模拟退火曲目排序 |
listening_stats.py | 聆听历史:最近播放,以及每首曲目 / 专辑 / 艺人的播放次数(Apple Music Replay 后端) |
profile_library.py | 描述性样本画像:测量 BPM / 能量 / 效价分布和相对于样本的象限;它不定义用户的品味 |
am_library.py | 你的资料库:分页导出你拥有的所有由目录提供支持的歌曲,并补充 ISRC / 年份 / 流派 |
build_pool.py | 聆听证据池:将最近播放与多个 Replay 年份的数据合并,保留日期和播放次数供大模型解读 |
支持模块:
| 文件 | 用途 |
|---|---|
playlist_core.py | 平台无关的核心功能:Camelot、BPM 折叠、四条相邻规则、六种叙事形状。不导入本项目中的任何内容,也不导入任何第三方内容 |
am_paths.py | 平台无关的路径和版本 — 配置与缓存的存放位置 |
am_meta.py | 唯一的 catalog_meta 实现(批量目录查询) |
所有三个分析模块都可作为库导入:
import playlist_flow, playlist_audit, playlist_optimize
print(playlist_flow.flow_report("My Playlist")) # -> str
print(playlist_audit.audit_report("My Playlist")) # -> str
ids, report = playlist_optimize.optimize("stack.json") # -> (list[str], str)
MCP 工具
标准提示词 create_playlist_from_description 会请求一段自然语言简介,以及可选的名称、曲目数量和回复语言。策展工作由宿主模型完成;这些工具是基于事实的 Apple Music 执行层:
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 会根据真实目录元数据核实大模型提出的候选曲目池,标记重复项和可疑版本,并且有意不对主题契合度评分。宿主模型会直接将候选曲目与用户的描述进行比较,并说明它们在播放列表中的作用。
am_analyze_flow 会诊断曲目间的衔接;am_optimize_order 可以选择性地优化已选叙事区块内的排序。它绝不会决定哪些歌曲应加入播放列表。
使用 preset/ 中的模板将其挂载到 Cordis Agent 预设中,或通过以下方式将其接入任何其他 MCP 客户端:
{ "mcpServers": { "applemusic": {
"command": "python", "args": ["/abs/path/am_mcp_server.py"] } } }
Codex、Claude、Cursor、VS Code/Copilot、Gemini CLI、Windsurf、Docker、Cordis/DSH 和 Harness 的完整测试示例见 docs/client-setup.md。
使用以下命令构建非 root 本地容器:
docker build -t apple-music-playlists:1.5.0 .
客户端必须使用 docker run --rm -i 以附加模式运行容器;只挂载应用配置目录和可写缓存,如客户端指南所示。配置目录必须保持可写,以便持久保存令牌刷新结果。切勿将 Apple 凭据打包进镜像。
测试
python -m unittest discover -s tests -v
整套测试完全离线——无需网络,也无需凭据。分为两类:
- 行为测试:决定什么才「听起来不错」的纯数学逻辑——Camelot 映射、BPM 折算、弧线分类、分别断言每项邻接惩罚、退火确定性,以及分块顺序约束。六种叙事原型都必须被分类为自身。
- 结构回归测试,每项都对应一个实际发布过的 bug:没有硬编码目录区域、恰好一个
catalog_meta、--storefront没有非None默认值、缓存位于仓库之外、每个 MCP 工具都连接到处理器,以及优化器不导入平台模块。
这些测试很快就证明了自己的价值——它们在几分钟前才写好的文件尚未运行之前,就发现了其中的语法错误。
有意思的部分:音频特征
Apple 的目录 API 完全不提供音频特征——没有速度、调性、响度、能量或效价。Spotify 的 audio-features 端点已于 2024-11-27 停止向新应用开放,AcousticBrainz 则于 2022 年退役。
playlist_flow.py 借助 Apple 确实会返回的 ISRC,通过一条免费且无需密钥的链路填补这一空白:
Apple Music track ──► ISRC
│
├─► api.reccobeats.com/v1/track?ids=<ISRC> → track UUID
│ └─► /v1/audio-features?ids=<UUID>
│ → tempo, key, mode, loudness, energy, valence,
│ danceability, acousticness, instrumentalness,
│ liveness, speechiness
└─ (fallback) musicbrainz.org ISRC lookup
结果会缓存在本地,因此每个播放列表只需支付一次网络开销。
覆盖率会如实报告,不会悄悄丢弃。 每个使用方都会打印一条漏斗,说明每首曲目为何无法测量:
Audio-feature coverage: 1,395/1,581 usable (88%)
· 80 tracks have no ISRC — the feature chain cannot start, so changing sources will not help
· 106 tracks are not in the current source — switch sources or analyse the audio locally
这一区别正是关键所在。没有 ISRC 意味着链路根本无法启动——更换特征来源也无济于事。未在来源中找到则意味着 ISRC 没问题,更换来源(或在本地分析音频)就能解决。把两者都归为「缺少特征」,就会丢掉唯一能告诉你下一步该怎么做的信息。
这比表面看起来更重要:tempo / key / energy / valence 是邻接规则和弧线唯一能据以采取行动的指标,因此覆盖率决定了排序质量的上限。覆盖率为 60% 时,十个位置中有四个从未参与评估——但成本数字看起来仍然很理想。因此,优化器会在成本行上方打印覆盖率,并在低于 90% 时发出警告。
优化器执行的排序规则
根据 docs/ 中收集的研究整理而成——包括一项由 130 位音乐专业人士对专辑进行排序的 PLOS ONE 研究,以及一项关于情绪自适应音乐排序的随机试验。
硬性相邻规则
- 不允许两首慢速曲目相邻
- 避免「仅略微变慢」的衔接(速度下降 0–12% 会让较慢的曲目显得拖沓)
- 相邻曲目在速度和调性上不能同时相似
- 不允许没有充分理由的大幅 BPM 跳变(>40%);不允许在调性不兼容时出现突兀的能量变化
这四条规则只有一个定义,位于 playlist_core.check_pair() 中,审核和优化器都会调用它。它们过去分别实现了两次,但两份实现并不一致:审核将低于速度第 25 百分位的曲目称为「慢速」,而优化器使用固定的 100 BPM;此外,审核完全没有检查 BPM 跳变规则。这就相当于工具按一套标准诊断、按另一套标准修复——因此,它报告的计数并不可信。
关于「慢速」阈值的说明。 该阈值是绝对值(100 BPM),而非基于数据得出,这是有意为之:优化器在退火过程中会对同一序列进行数千次评估,而百分位阈值会随着排列变化而漂移,导致成本永远无法稳定下来。代价是,速度普遍较慢的播放列表会将每一对相邻曲目都标记出来——这是实际情况,并非排序失败,报告也会对此作出说明。
全局叙事弧线是可选项。 不指定 --arc 时,优化器只考虑局部相邻关系,不会施加情绪或速度轨迹。宿主 LLM 应从简述中理解自由形式的故事,并在各个分组中保留其顺序;只有当用户明确要求某种曲线时,才使用指定预设。
python playlist_optimize.py stack.json --arc cinderella
python playlist_optimize.py --list-shapes
| 维度 | 目标 |
|---|---|
valence、energy、loudness | 仅在明确指定 --arc 时,采用所选原型 |
tempo | 倒 U 形——中段较快,仅在明确指定 --arc 时生效 |
六种可选形状:rags-to-riches、tragedy、man-in-a-hole、icarus、cinderella、oedipus。目标曲线和审核所归类的形状都来自 playlist_core.ARCHETYPES 中的同一张表。审核仍可能报告播放列表与哪种预设相似;但这种诊断并不意味着该预设是推荐方案或排序目标。
明确请求某种预设时,valence / energy / loudness 会遵循其情绪轨迹,而速度则使用单独的倒 U 形目标。不指定 --arc 时,不会应用这两种全局目标。
弧线成本表示与明确请求的特征曲线之间的距离,并不衡量播放列表的好坏。覆盖范围限制了它所能描述的内容;成本较低既不能凌驾于简述要求之上,也不能证明某个序列听起来更好。
优化器会保留你的分组(乐章 / 时代 / 情绪),只在各个分组内部重新排序,因此即使调整响度,也能保留主题结构。移除分组后,优化器就会自由重排——播放列表可以明显变得「更平滑」,但要以牺牲叙事为代价。
真实运行示例:保留分组时,成本从 104.46 降至 19.41;不分组时则降至 1.28。
调试前值得了解的注意事项
- 即使从未发送
Accept-Encoding,响应也可能经过 gzip 压缩。 将原始字节解码为 UTF-8 会得到乱码,看起来像是空响应正文。(此问题已在am_playlist.py中修复。) DELETE仅适用于amp-api.music.apple.com。 对播放列表和资料库歌曲执行删除操作时,文档中记录的主机api.music.apple.com会返回 401。- 不要向 amp-api 发送
x-apple-client-version,否则会导致 500 错误。 - 创建播放列表时,也会将其中的曲目添加到资料库。 删除播放列表不会将这些曲目移除。
- BPM 估算存在倍频歧义(同一首曲目可能估算为 90 或 180)。比较前应将数值折叠到
[70,160);否则,“相邻的两首慢歌”会被多报约 4 倍。 - 切勿将
"Title - Artist"直接传给目录搜索——你会得到现场版或重制版录音。请使用空格分隔的形式进行搜索,然后再对不同版本进行评分。 - 在某个商店的搜索中找不到艺人 ≠ 歌曲在该商店不可用。 请通过 ISRC 查找。
- 只有创建播放列表的客户端才能修改它——这是 Apple 方面的限制。
更多内容请参阅 docs/apple-music-api-notes.md 和
skill/reference.md。
文档
| 文档 | 内容 |
|---|---|
SETUP.en.md | 凭据:有哪些令牌、如何获取每种令牌、安全说明、故障排除 |
docs/client-setup.md | 特定客户端的 MCP、Docker、Cordis/DSH、通用运行框架和 Harness Platform 设置 |
docs/publishing.md | 仅供维护者使用的 PyPI 和官方 MCP Registry 发布检查清单 |
docs/apple-music-api-notes.md | 令牌模型、端点契约、实测 API 行为、7 种自动化方案评估 |
docs/how-to-build-a-good-playlist.md | 策展方法:相邻曲目规律、弧线数据、六种叙事形态、ISO 原则 |
docs/playlist-curation-survey.md | 已发布策展指南综述(平台规则、DJ 方法、学术研究结果) |
docs/evaluation-signals.md | 大模型原生策展:直接比较候选曲目、目录依据、可读约束,以及为何标量主题评分不应进入关键路径 |
docs/natural-language-curation-evidence.md | 关于宽泛音乐意图、参考与请求错误、意图幻觉、可审查的语言特征,以及可复用验证协议的原始研究 |
examples/ | 可复现的多语言策展评估:六份高难度需求说明、基准协议、可审计证据、隐私规则,以及不提供黄金曲目列表 |
docs/algorithm-review.md | 早期启发式方法的审查边界:哪些决策应交由大模型处理,哪些应由确定性算法保留 |
docs/platform-adapters.md | 平台适配器边界:哪些部分与平台无关、适配器必须提供什么,以及在不提供 ISRC 的服务上会出现哪些问题 |
llms.txt | 简明的 Agent 可读指南,介绍策展边界和最有用的项目文档 |
skill/ | Agent 技能:工作流 + 累积的注意事项列表 |
CHANGELOG.md | 发布历史,包括不同版本间的行为变化 |
preset/ | 用于挂载 MCP 服务的 Cordis Agent 预设模板 |
完整的简体中文指南请参阅 README_ZH_CN.md。
社区
许可证
MIT — 详见 LICENSE。
非官方社区工具,与 Apple 无关联,也未获得 Apple 背书。 个人使用时,请使用自己的 Apple Music 账户;并遵守 Apple 的服务条款。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。