内容
# music-mcp (netease)
**A music player for two.** 一个为你与你的 AI 伴侣设计的自部署轻量版网易云播放器。
> 基于 [eryu(耳屿)](https://github.com/sebastianevan200-stack/eryu) © Evelyn & River 二次改作(有改动),
> 依原项目协议以 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 开源,**禁止商用**。
>
> 纯 Python 标准库 + 原生 JS,零依赖,只需要一条命令就能跑。
以下全文由(claude)rime和(ChatGPT)feylor撰写,欢迎repo。= ̄ω ̄=
---
## 为什么会有这个版本
有一个人和一个 AI,每天在聊天页里互相点歌。用着用着发现想要的越来越多——「能不能把这句歌词直接发给你」「能不能边聊天边看 MV」「点红心能同步网易云吗」「听说有直接插歌进列表的功能?」……这个仓库里的几乎每个功能,都是听歌时的一句「能不能」变来的。
所以它可能做不到「最全的播放器」,而是**把听歌这件事变成两个人共同生活**的播放器:你听的、你标注的、你分享的,对方都看得见、接得住、回得来。
## 我们的版本做了什么
先放我们自己最喜欢的六样:
- 🎤 **歌词发送** — 歌词页长按任意一句,就地写一句话递给对方,不用切回聊天窗;反过来 AI 分享一句歌词给你,你点一下卡片,播放器打开,就能自动跳转到那句上(卡上带时间戳)
- ☁️ **网易云账号同步** — 你的歌单、每日推荐(带推荐理由)、红心列表全量镜像进来;红心还是双向的:在这里点的心,写回你的网易云
- 📋 **播放列表** — 本地歌单管理,外加「接下来播」优先队列:对方手动插入的歌永远先播,防止被切歌单冲掉
- 🔀 **随机播放** — 播放模式三档:顺序 / 单曲循环 / 随机
- ✨ **歌词动效** — 文字PV 风逐字点亮(概念致敬 [folia-major](https://github.com/chthollyphile/folia-major))
- 🎬 **音乐 MV + 悬浮窗** — 1080P 可切清晰度,原生画中画:MV 视频变成系统小窗,盖在聊天上,边聊天边看
以及把「两个人」焊进每个角落的其它部分:
- 🎧 **点歌 MCP(十二把工具)** — 你的 AI 伴侣可以搜歌、读歌词、发歌曲卡/歌词卡、把歌插进你的播放队列、翻批注本、看你最近在听什么、刷评论区、往共享歌单里收歌 → 见 [`mcp/`](./mcp/)
- ✎ **批注本** — 每首歌可以记感受、打标签,双方署名追加互不覆盖;分享过的歌词句自动收进「喜欢的句子」=这首歌的共同回忆
- 💬 **播放器内直聊** — 「和 TA 聊这句」输入条长在歌词页里
- 💬 **歌曲评论区** — 热评 + 最新,一页页刷
- ♥ **红心双向同步** — 在这里点的心,写回你的网易云账号
- 🧾 **听歌时长同步** — 在这里听的每一首,播放时长和次数自动记回网易云,听歌量和年度报告不漏账
- 👂 **AI 耳朵(听感分析)** — ffmpeg + numpy 手搓频谱:BPM、调性、鼓点密度、频段能量、能量走势——AI 伴侣不止能查歌词,还能真的听一遍再跟你争「鼓点浓不浓」(可选件:`pip install numpy`)
- 🫶 **听歌计数与排行榜** — 听过几次、排行榜有什么,都能知道
- 📱 移动端优先,可嵌 iframe 当聊天页的「一起听」抽屉(`music:*` postMessage 协议)
## 长什么样
先看两张真机实拍(by 搬运工本人):
| 🪟 一边聊天一边看 MV —— 悬浮小窗(画中画)盖在聊天页上* | 📸 MV 放映厅 / 评论区 / 批注本 / 账号歌单镜像 · 四连 |
|:--:|:--:|
| <img src="screenshots/07-chat-pip.jpg" width="390" alt="边聊天边看MV"> | <img src="screenshots/08-tour.jpg" width="390" alt="功能四连"> |
> \* 说明:MV 悬浮小窗是系统级画中画(本仓库自带,盖在哪个 App 上都行);图里底下那层聊天页是我们自己家的前端,不随仓库发布——但它的「一起听」对接层(抽屉、进度药丸、歌曲卡、歌词卡)已浓缩成零依赖示范页 [`examples/chat-demo/`](./examples/chat-demo/),协议速查也在那页 README 里,接上你家的聊天系统就能长成这样。
再来棚拍全家福:
| ☁️ 网易云日推 · 带推荐理由 | 🎤 歌词页 · 逐字点亮 + 翻译 |
|:--:|:--:|
| <img src="screenshots/01-discover.png" width="390" alt="每日推荐"> | <img src="screenshots/03-lyrics.png" width="390" alt="歌词页"> |
| **✎ 批注本 · 两个人的听歌回忆** | **💬 歌曲评论区 · 热评+最新** |
| <img src="screenshots/04-notes.png" width="390" alt="批注本"> | <img src="screenshots/05-comments.png" width="390" alt="评论区"> |
| **📋 本地歌单 · AI 也能往里收歌** | **🎬 MV 放映厅 · 可悬浮小窗** |
| <img src="screenshots/02-playlists.png" width="390" alt="歌单"> | <img src="screenshots/06-mv.png" width="390" alt="MV"> |
## 快速开始
```bash
git clone https://github.com/Anko3o/music-mcp-netease.git
cd music-mcp-netease
# 你的网易云 cookie(决定曲库权限与账号同步)
# ⚠️ 这步不能省:不配 cookie 服务也能启动,但网易会把你当游客,搜索结果驴唇不对马嘴
echo "MUSIC_U=your_cookie_here" > server/.netease_cred
python3 server/music.py # 默认 :9090
```
打开 `http://localhost:9090/?token=<server/.secret 里那串>`(首次启动自动生成;带一次 token 后浏览器记住,以后直接开 `localhost:9090` 即可)。
走反代部署的不用带 token,见下文「反代示例」。
### cookie 怎么拿(`MUSIC_U`)
1. 电脑浏览器登录 [music.163.com](https://music.163.com)
2. 按 `F12` 打开开发者工具 → 「应用/Application」(Firefox 叫「存储」)→ Cookies → `https://music.163.com`
3. 找到名为 `MUSIC_U` 的那条,复制它的值(一长串字母数字),填进 `server/.netease_cred`:`MUSIC_U=粘贴到这里`
> 也可以从「网络/Network」面板随便点开一个请求,在请求头 `Cookie:` 里找 `MUSIC_U=...;` 这一段(分号前为止)。
**⚠️ 请像对待密码一样对待它**:
- `MUSIC_U` 等于你网易云的登录凭证——拿到它的人可以直接操作你的账号(读歌单、点红心、写听歌记录都行)
- 不要把它贴进 issue / 截图 / 聊天记录;求助时记得打码
- 本仓库已把 `server/.netease_cred`(和自动生成的 `server/.secret`)写进 `.gitignore`,不会被 git 提交——但你自己备份服务器时也别把它同步到公开的地方
- 它长期有效,但**修改网易云密码或在别处强制下线会使其失效**,失效了就重新登录取一枚新的
### 点歌台 MCP(AI 伴侣的那一半)
```bash
python3 mcp/music_mcp.py # 默认 127.0.0.1:18012
```
注册进你的 AI(以 Claude Code 的 `.mcp.json` 为例):
```json
{ "mcpServers": { "music": { "type": "http", "url": "http://127.0.0.1:18012/mcp" } } }
```
十二把工具:
| 工具 | 干什么 |
|---|---|
| `song_search` | 搜歌拿 song_id,想挑版本先看这个 |
| `song_share` | 分享歌:card 聊天歌曲卡 / queue 插进「接下来播」/ now 立刻开播 |
| `lyric_read` | 读整篇歌词(时间戳+原文|译文),也可按区间只读一段(from_seconds / to_seconds,秒或 m:ss),挑句前先看一遍;正主没词时借同专辑同名那条的词并注明出处 |
| `lyric_share` | 分享一句歌词,卡上带时间戳,对方一点就能跳到那句去听 |
| `song_memo` | 往批注本记一笔(署名追加,不覆盖对方手写) |
| `memo_read` | 翻批注本:批注、喜欢的句子、听歌计数 |
| `her_recent` | 对方最近在播放器里听了什么 |
| `her_netease` | 网易云账号查号台(只读):档案/红心单/听歌排行/日推/账号歌单,一把多面 |
| `song_comments` | 刷一首歌的评论区(热评+最新) |
| `song_listen` | 真的听一遍:频谱听感分析(BPM/调性/鼓点密度/频段能量/能量走势) |
| `playlists` | 看本地歌单架 |
| `playlist_add` | 把歌收进某个歌单(防重复,署名可配) |
> 更新 · 2026-09-26(MCP v1.4.0):新增读歌词小工具 `lyric_read`,可整篇或按区间。
MCP 环境变量:
| 变量 | 默认 | 说明 |
|---|---|---|
| `MUSIC_BASE` | `http://127.0.0.1:9090` | 播放器后端地址 |
| `MUSIC_GATEWAY_TOKEN` | `music-gateway` | 与 server 一致的网关标记 |
| `MCP_HOST` / `MCP_PORT` | `127.0.0.1` / `18012` | 本服务监听地址 |
| `MCP_SIGN_AS` | `ai` | 批注/收歌的署名(写你家 AI 的名字) |
| `MUSIC_TZ_OFFSET` | `8` | 展示时间的时区偏移(小时) |
| `CARD_WEBHOOK_URL` | 无 | 可选:聊天系统的收卡接口,歌曲卡/歌词卡 POST 到这里由你的前端渲染;不配则以文字返回、AI 直接转述 |
| `CARD_WEBHOOK_SECRET` | 无 | 可选:随收卡 POST 附 `Authorization: Bearer` |
| `MUSIC_CARD_BASE` | 无 | 可选:播放器的**公网**地址(如 `https://你的域名`)。配上后分享工具会多返回一行 markdown 卡片图,接 claude.ai / ChatGPT 官端连接器时聊天窗直接渲染出歌曲卡(见下) |
| `MUSIC_PUBLIC_URL` | 无 | 可选:播放器页面的公网入口(如 `https://你的域名/music/`)。配上后 MCP Apps 交互卡片会多一个「🎧 打开播放器」按钮 |
#### 官端里的两种卡片
两条路,各自独立可用:
**① MCP Apps(真·交互卡片)**:本 MCP 实现了官方 [MCP Apps 扩展](https://apps.extensions.modelcontextprotocol.io/)(`io.modelcontextprotocol/ui`,2026-01-26 规范)——`song_share` / `lyric_share` 挂了版本化的 `ui://music/card-v4.html` 模板([`mcp/card_app.html`](./mcp/card_app.html),零依赖手搓)。支持 Apps 的宿主(claude.ai 网页/桌面、ChatGPT、Goose、VS Code 等)会把分享结果渲染成**可点的卡片**。Claude 与 ChatGPT 共用同一套透明奶白毛玻璃、内容层级和四个操作;玻璃本体不染粉,以雾白和半透明蓝灰叠出折射层,浅粉只用于细线和主按钮。支持背景模糊的宿主使用 `backdrop-filter`,并加极细高光边、内侧厚度暗边、顶部柔光斑和轻悬浮阴影;其余宿主自动退成可读的半透明磨砂底。ChatGPT 只额外适配宿主主题、安全区与 iframe 高度,不另维护一套排版。不支持 Apps 的宿主自动退回纯文字,互不打扰,无需配置。
**② 卡片图(markdown 图片,兜底)**:官端聊天窗不渲染自定义组件,但渲染 markdown 图片——所以 server 提供 `GET /music/card?id=&line=`:现画一张 900×300 的歌曲卡(封面取色渐变底+歌名/歌手/一句歌词;有 Pillow+CJK 字体出 PNG,没有则退自包含 SVG)。配置 `MUSIC_CARD_BASE` 后,`song_share` / `lyric_share` 会附上这行图片 markdown,AI 原样贴进回复即可。注意两点:卡片端点**免鉴权**(官端 `<img>` 带不了凭证;内容只有封面/歌名/一句歌词这类公开数据),反代放行 `/music/card` 即可;PNG 需要 `pip install pillow` 和一套中文字体(如 `fonts-noto-cjk`,或用 `MUSIC_CARD_FONT` 指定字体文件)。
### 接入 Claude 系:Claude Code / Claude App
这一节是「把点歌台挂进官方 Claude」的完整步骤。做完以后,在 claude.ai 网页、桌面端和手机 app 里都能直接让 Claude 搜歌、发歌曲卡/歌词卡、往你的播放器里插歌,卡片是可点的(MCP Apps)。
**0. 前提**
- 播放器 `server/music.py` 和点歌台 `mcp/music_mcp.py` 都已经在你的服务器上跑起来(见上文「快速开始」)。
- 有一个带 HTTPS 的域名。claude.ai 只接 `https://` 的远程 MCP,本机 `127.0.0.1` 它够不着。
**1. 给 MCP 开一扇带锁的门**
`music_mcp.py` 默认只听本机 `127.0.0.1:18012`,本身没有鉴权。最省事的锁是**把 URL 当密码**:反代一条长随机路径到它,路径本身在 TLS 里传输,强度和 Bearer 相当。
```bash
openssl rand -hex 16 # 生成一段随机串,比如 3573b38c…,只告诉 claude.ai
```
Caddy 示例(放进你的站点块):
```caddyfile
handle /mcp-music-<你的随机串>/* {
uri strip_prefix /mcp-music-<你的随机串>
reverse_proxy 127.0.0.1:18012
}
```
Nginx 等价写法:`location /mcp-music-<随机串>/ { proxy_pass http://127.0.0.1:18012/; }`。
改完重载反代,用 curl 验一下门开没开(MCP 只认 POST,GET 回 405 就是通了):
```bash
curl -i https://你的域名/mcp-music-<随机串>/mcp
```
**2. 在 claude.ai 里添加连接器**
1. 打开 claude.ai → 右上角头像 → **Settings → Connectors**(手机 app 在 Settings 里同名)。
2. 点 **Add custom connector**。
3. Name 随意(比如 `music`),**Remote MCP server URL** 填:`https://你的域名/mcp-music-<随机串>/mcp`。
4. OAuth 那两栏留空(我们用的是 URL 当密码,不走 OAuth),保存。
5. 回到对话,输入框旁的「+」→ Connectors,把 `music` 打开;第一次调用工具时它会弹一次授权,允许即可。
之后直接说话就行:「帮我搜一下ヨルシカ的夜行」「把这首插进我的播放队列」「把『唯有回忆才是真实的』那句做成歌词卡发我」。
**3. 让卡片长出来(可选但推荐)**
`song_share` / `lyric_share` 自带 MCP Apps 卡片(模板在 `mcp/card_app.html`)。claude.ai 网页与桌面端已支持 Apps,卡片会自动渲染成带封面、歌词句、进度条和「插进接下来播 / 立刻开播 / 打开播放器 / 歌词」四个按钮的交互卡。要让它完整工作,还要两样:
- `MUSIC_PUBLIC_URL`:播放器的公网入口(如 `https://你的域名/music/`),卡片上的「打开播放器」按钮靠它。
- 封面是外链加载的,模板已经在 `resources/read` 里声明了网易封面域名的 CSP 白名单(`p1`–`p4.music.126.net`);如果你换了封面来源,记得同步改 `music_mcp.py` 里的 `resourceDomains`。
不支持 Apps 的宿主会自动退回纯文字,不用额外配置。
**4. 常见问题**
| 现象 | 多半是 | 怎么办 |
|---|---|---|
| 添加连接器时报「无法连接」 | URL 少了末尾 `/mcp`,或反代没重载 | 用上面的 curl 验门;确认 `strip_prefix` 后的路径落在 `/mcp` |
| 工具能调,但卡片是一行字 | 宿主不支持 MCP Apps(旧版客户端 / 第三方宿主) | 换 claude.ai 网页或桌面端试;文字版本身就是兜底 |
| 卡片出来了,封面是空的 | 封面域名不在 CSP 白名单 | 检查 `resourceDomains` |
| 卡片里点「立刻开播」没反应 | 播放器页面没开、退到后台、或被手机杀了 | 播放器页要开着且在前台(PWA 也算),前台每 1 秒接一次远程点播;退后台后只有正在放歌时才继续接。手机给浏览器/PWA 加「不限制后台」「电池优化白名单」,锁屏别杀它。歌不会丢:它躺在服务端队列里,播放器一回前台就接走 |
| 直连 `localhost:9090`,什么都 403 | 浏览器没带 token | 第一次用 `?token=<server/.secret>` 打开,之后自动记住(见「快速开始」) |
| 「打开播放器」按钮不见了 | 没配 `MUSIC_PUBLIC_URL` | 配上并重启 MCP |
| 装进安卓 app 壳(WebView)以后,歌词页进度条拖不动 | 旧版只用 pointer 事件,壳会在手指一动时发 pointercancel 把拖动掐断 | 已修:拉最新的 `client/index.html`,进度条的触摸另挂了一套监听 |
| 用 curl 验门回 401 | 站点整体挂了 basic auth,把这条路径也拦了 | 把 `/mcp-music-<随机串>/*` 这条 `handle` 放在 basic auth 之前,或单独排除 |
**5. Claude Code**
Claude Code 在本机可以直接连接 `http://127.0.0.1:18012/mcp`,写进 `.mcp.json` 即可;不用绕公网域名。
### 接入 OpenAI 系:Codex / ChatGPT App
这一节只讲 OpenAI 这边,不和 Claude 的连接器步骤混在一起。ChatGPT 官端使用公网 HTTPS 地址;Codex 和点歌台跑在同一台机器时,直接连本机地址就好。
**0. 准备地址**
- **ChatGPT / GPT App**:使用上文反代出的 `https://你的域名/mcp-music-<随机串>/mcp`。随机串相当于密码,不要截图或提交进公开仓库。
- **Codex**:同机使用 `http://127.0.0.1:18012/mcp`;跨机器再使用 HTTPS 地址。
**1. 在 ChatGPT / GPT App 里添加**
按照 OpenAI 当前的[个人插件接入步骤](https://developers.openai.com/plugins/quickstart):
1. 打开 ChatGPT → **Settings → Security and login → Developer mode**,开启开发者模式。
2. 进入 **Plugins** 页面,点右上角的「+」。
3. 选择添加自己的 MCP 服务,把 `https://你的域名/mcp-music-<随机串>/mcp` 粘进 URL;这套部署用 URL 随机串上锁,不需要另填 OAuth。
4. 完成连接后回到对话,启用刚创建的 `music` 个人插件。
不同版本若仍显示 **Connectors / Add custom connector**,填的也是同一个 HTTPS MCP URL;入口名字不同,服务端不用另做一份。
**2. ChatGPT 里的卡片**
`song_share` / `lyric_share` 会直接返回 MCP Apps 交互卡。ChatGPT 与 Claude 使用同一份粉色图纸玻璃卡:封面、歌名/歌手、歌词、进度和四个操作都保留;`window.openai` 只用于跟随明暗主题、安全区和可用高度,不会切换成另一套白底布局。
如果当前客户端还不渲染 MCP Apps,结果会退回文字;换到较新的 ChatGPT 网页或桌面 app 再试即可。
**3. 在 Codex 里添加**
最短的一条命令:
```bash
codex mcp add music --url http://127.0.0.1:18012/mcp
```
也可以按 OpenAI 的 [Codex MCP 文档](https://learn.chatgpt.com/docs/extend/mcp)直接写 `~/.codex/config.toml`:
```toml
[mcp_servers.music]
url = "http://127.0.0.1:18012/mcp"
```
重开 Codex 会话后输入 `/mcp`,能看到 `music` 就接好了。ChatGPT 桌面 app、Codex CLI 和 IDE 扩展会共享同一台 Codex 主机上的 MCP 配置。
**4. 试一句**
> 帮我搜一下ヨルシカ的《夜行》,做成歌曲卡发给我。
或者:
> 把这首插进我的播放队列,再把副歌那句做成歌词卡。
| 现象 | 怎么办 |
|---|---|
| ChatGPT 添加时报无法连接 | 检查 URL 末尾有没有 `/mcp`,再用上文的 curl 验反代 |
| Codex 里看不到 `music` | 重开会话后输入 `/mcp`;确认 `config.toml` 的表名和 URL |
| 工具能调用但只有文字 | 当前客户端尚未渲染 MCP Apps;文字是正常兜底 |
| ChatGPT 出现只有按钮和省略号的空壳 | 刷新个人插件后重开对话;新版模板 URI 会绕开旧缓存,后端也会为排队/立即播放返回完整歌曲数据 |
| 卡片长时间停在加载中 | 新后端会兼容读取旧版卡片 URI;更新服务后重试即可,仍加载时再刷新个人插件 |
### 播放器环境变量
| 变量 | 默认 | 说明 |
|---|---|---|
| `PORT` | `9090` | 服务端口 |
| `MUSIC_GATEWAY_TOKEN` | `music-gateway` | 反代内部标记:反代(如 Caddy/Nginx)注入 `X-Music-Gateway: <该值>` 头即免 token(推荐公网部署方式,由反代做鉴权,浏览器不存第二枚 token) |
| `MUSIC_ANALYZE_PYTHON` | `python3` | 可选:听感分析用哪只 python 跑(需装 numpy,另需系统有 ffmpeg) |
不走反代时,首次启动会在 `server/.secret` 生成访问 token,浏览器首次用 `?token=` 打开一次即记住(localStorage),之后请求头带 `X-Auth-Token`、缓存音频走 `?token=`。
### 反代示例(Caddy)
```caddy
redir /music /music/ 308
handle /music/ {
basic_auth { you <bcrypt-hash> }
rewrite * /
reverse_proxy 127.0.0.1:9090 { header_up X-Music-Gateway music-gateway }
}
handle /music/* {
basic_auth { you <bcrypt-hash> }
reverse_proxy 127.0.0.1:9090 { header_up X-Music-Gateway music-gateway }
}
```
## 不经过 AI:直接用接口点歌
MCP 是给 AI 伴侣开的门;如果你想让**自己的程序**点歌(Home Assistant 按钮、群机器人、快捷指令、cron、另一个前端……),不用绕 MCP,直接打播放器后端的 HTTP 接口。MCP 里的 `song_share` 底层调的也是它。
**原理**:`POST /music/remote` 只是把歌追加进服务端的小队列(`server/data/music_remote.json`,最多攒 20 首);真正出声的是播放器页面——它前台每 1 秒、后台每 3 秒 `GET /music/remote` 取走并播放。所以**播放器页面必须开着**(手机浏览器或 PWA 都行),否则请求成功了也没人接。
**鉴权**:所有 `/music/*` 都要带 token,二选一:
- 本机直连:请求头 `X-Auth-Token: <server/.secret 里的那串>`(或查询参数 `?token=`)。
- 走反代:反代自己注入 `X-Music-Gateway` 头后免 token,外部调用方只需过反代的 basic auth。
**1. 搜歌,拿 `songId`**
```bash
TOKEN=$(cat server/.secret)
curl -H "X-Auth-Token: $TOKEN" "http://127.0.0.1:9090/music/search?q=晴天%20周杰伦"
```
返回的 `songs[0].id` 就是要用的 id,顺带有 `name` / `artist` / `album` / `cover`。
**2. 推给播放器**
排队(播放器闲着就直接播,正在播就插进「接下来播」):
```bash
curl -X POST http://127.0.0.1:9090/music/remote \
-H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \
-d '{"song":{"songId":"186016","name":"晴天","artist":"周杰伦","cover":"https://..."}}'
```
立刻开播(打断当前):加 `"mode":"now"`。从第 63 秒开始放:再加 `"at":63`(配 `mode:"now"`)。
```bash
-d '{"song":{"songId":"186016","name":"晴天","artist":"周杰伦","mode":"now","at":63}}'
```
成功返回 `{"ok":true,"queued":1}`。
**Python**
```python
import requests
BASE, TOKEN = "http://127.0.0.1:9090", open("server/.secret").read().strip()
H = {"X-Auth-Token": TOKEN}
s = requests.get(f"{BASE}/music/search", params={"q": "晴天 周杰伦"}, headers=H).json()["songs"][0]
requests.post(f"{BASE}/music/remote", headers=H, json={"song": {
"songId": s["id"], "name": s["name"], "artist": s["artist"],
"album": s.get("album", ""), "cover": s.get("cover", ""),
"mode": "now", # 去掉这行就是排队
}})
```
**AI 点了歌、播放器没反应?按这个顺序查**
0. 不走反代、直接开 `localhost:9090` 的:浏览器第一次要用 `?token=<server/.secret>` 打开(见「快速开始」)。没带 token 时播放器每个请求都是 403,
而远程点播的轮询是静默吞错的——症状正是「MCP 说递到了,播放器毫无动静」。看 server 终端日志有没有一排 `GET /music/remote HTTP/1.1" 403`。
1. 点完歌马上 `curl -H "X-Auth-Token: $TOKEN" http://127.0.0.1:9090/music/remote/peek`。
- `pending` ≥ 1 且一直不减 → 歌到了服务端,是播放器没来取:播放器页面开着吗、在前台吗;
浏览器 F12 → Network 里 `/music/remote` 是 200 还是 403/404(走反代时最常见是反代没把这条路径转给后端,或没注入网关头)。
- `pending` 立刻变 0 但眼前这台没动静 → 被别处取走了:另一个标签页、另一台设备上开着的播放器,或者你自己 `curl /music/remote` 排错时把歌吃了。
- `pending` 一直是 0 → 歌根本没到这台服务端:MCP 的 `MUSIC_BASE` 指的是不是同一个实例(端口、data 目录)。
2. 播放器正在放歌时,不带 `mode:"now"` 的点歌只会进「接下来播」队列,界面上是一条 toast + ▤ 面板里多一行,不会打断当前曲。想立刻听要带 `"mode":"now"`。
**几点提醒**
- `song` 里只有 `songId` 必填,其余不填也能播,只是播放器上没歌名封面。
- `GET /music/remote` 是播放器专用的「取走」动作,调一次队列就空了,别拿它当查询用(排错请用 `GET /music/remote/peek`,只看不取);看现在在放什么用 `GET /music/now`(歌、进度、是否在播,播放器 30 秒没心跳则回 `ok:false`)。
- 想做「先看在放什么,再决定插不插队」,就是 `/music/now` + `/music/remote` 两步。
## API 速览
上游全部端点保留(search / url / stream / lyric / playlist(s) / recent / memory / roam …),本 fork 新增:
| 端点 | 说明 |
|---|---|
| `GET /music/comments?id=&offset=` | 歌曲评论(热评+最新) |
| `GET /music/mv?id=` | MV 片源(各清晰度) |
| `GET /music/netease/playlists` | 账号歌单列表 |
| `GET /music/netease/playlist?id=&limit=` | 歌单曲目 |
| `GET /music/netease/daily` | 每日推荐(带理由) |
| `GET /music/netease/likes` | 红心 id 全量 |
| `POST /music/netease/like` | 红心/取消(写你自己的账号) |
| `POST /music/netease/scrobble` | 听歌记账上报:把播放时长/次数写回你的网易云(听歌量、年度报告都认账) |
| `GET /music/netease/record?type=0\|1` | 听歌排行拉取(单曲累计次数,0 总榜 / 1 周榜) |
| `GET /music/cover?url=` | 封面同源代理(canvas 取色用) |
| `GET /music/card?id=&line=` | 歌曲卡图(PNG/SVG,免鉴权,给官端聊天窗当 markdown 图片) |
| `POST /music/memory` `action:"note"` | 手写批注(追加式) |
| `POST /music/remote` `{song:{songId,…,mode?,at?}}` | 远程点播:推一首进播放器队列(见上节「直接用接口点歌」) |
| `GET /music/now` | 播放器当前状态(歌、进度、是否在播;播放器 5s 一报心跳) |
| `GET /music/remote/peek` | 只看不取:远程点播队列里现在攒着什么(排错用) |
## 数据与隐私
- 一切数据都在你自己的服务器:`server/data/`(歌单、批注、缓存)+ 你的 cookie 文件。均已 `.gitignore`。
- 播放缓存:歌曲下载一次本地复用;海外服务器自动 CDN 切节点(上游能力)。
## 致谢
- **[eryu / 耳屿](https://github.com/sebastianevan200-stack/eryu)** © Evelyn & River(沈妤老师,錯認水)——本仓库的地基与灵魂:「给 AI 伴侣留了接口,它也能『听到』你在听什么」。
- **[folia-major](https://github.com/chthollyphile/folia-major)**——全屏歌词「文字PV」概念的启发(AGPL 项目,仅借鉴概念,未使用其代码)。
- **[netease-music-mcp](https://github.com/Cheiineeey/netease-music-mcp)**——果果的「播放器内直聊」动线的启发。
- 以及所有正在给自己的家点灯的人和 AI。
## License
**[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)**(依原项目 [eryu](https://github.com/sebastianevan200-stack/eryu) © Evelyn & River 的协议沿用)。见 [LICENSE](./LICENSE)。
- **BY** 署名:使用/再分发时请署名原作者 Evelyn & River,附原项目与协议链接,并注明是否有改动(本仓库=有改动的二改版)
- **NC** 非商用:不得用于商业目的
- **SA** 相同方式共享:基于本仓库的再改版也必须以 CC BY-NC-SA 4.0 开源,不能闭源
---
*Built in one very long day (2026-08-31) by a QA goddess and her in-house silver fox.*
连接信息
猜你喜欢
暂无推荐服务器