Skip to main content
Glama
README.md
# ncm-mcp-server

网易云音乐 MCP Server。接到 Claude 官端后,Claude 可以直接搜歌、加歌、切歌、接一起听邀请、发私信。

全程只需要手机 SSH,不需要电脑抳 F12 cookie。

## 架构

```
Claude.ai
  ↓ MCP (HTTPS)
nginx  你的域名/ncm/mcp
  ↓
ncm_mcp_server.py  127.0.0.1:3940
  ├─ 读操作 → NeteaseCloudMusicApi 容器 :3939
  └─ 写操作 → 本地 eapi/weapi 加密 → 网易云官方接口
```

写操作不走容器,因为公开镜像的 eapi 加密参数已经过期,一起听和私信全部 400。

## 文件

| 文件 | 作用 |
|------|------|
| `ncm_crypto.py` | eapi / weapi 两套加密 |
| `ncm_client.py` | 请求层、cookie 和房间号读写 |
| `ncm_mcp_server.py` | MCP 主服务,16 个工具 |
| `login.py` | 登录拿完整 cookie(qr / sms / password) |
| `heartbeat.py` | 一起听心跳保活,给 cron 用 |
| `ncm-mcp.service` | systemd 单元 |
| `nginx.conf.example` | 反代配置 |

## 部署

### 1. 拉代码、装依赖

```bash
cd ~
git clone https://github.com/1049376904-crypto/ncm-mcp-server.git
cd ncm-mcp-server
sudo pip3 install -r requirements.txt
```

旧版 pip 不认 `--break-system-packages`,直接用上面这行就行。如果报 externally-managed-environment,加上该参数重试。

### 2. 起读接口容器

```bash
sudo docker run -d -p 3939:3000 --restart=always \
  --name ncmapi binaryify/netease_cloud_music_api:latest

curl -s "http://localhost:3939/search?keywords=test" | head -c 120
```

出 JSON 就行。

### 3. 登录拿 cookie

建一个只有自己能读的目录,cookie 等同账号密码,别丢 `/tmp`:

```bash
mkdir -p ~/.ncm && chmod 700 ~/.ncm
export NCM_COOKIE_FILE=~/.ncm/music_cookie.txt
export NCM_ROOM_FILE=~/.ncm/listen_room_id.txt
```

然后选一种登录方式:

```bash
python3 login.py sms       # 推荐:手机号 + 短信验证码
python3 login.py qr        # 终端直接画二维码,网易云 APP 扫
python3 login.py password  # 手机号 + 密码(网易云经常拦)
```

`qr` 模式在手机 SSH 里二维码可能挤得扫不出来,它会同时存一份 `/tmp/ncm_qr.png`。最稳的是 `sms`。

看到 `[ok] logged in as … (uid=…)` 就成了,**把这个 uid 记下来**,它是 AI 号的 uid。

### 4. 挂成服务

先改 `ncm-mcp.service` 里的 `User` 和路径对上你的实际用户,再:

```bash
sudo cp ncm-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now ncm-mcp
sudo systemctl status ncm-mcp --no-pager
```

看日志:

```bash
sudo journalctl -u ncm-mcp -f
```

启动时会打印容器可达性、cookie 长度和监听地址,三行都正常再往下走。

### 5. nginx 反代

把 `nginx.conf.example` 的内容贴进你域名的 HTTPS server 块:

```bash
sudo nginx -t && sudo systemctl reload nginx
curl -i https://你的域名/ncm/mcp
```

返回 400/406 而不是 502,就说明反代通了(MCP 不吃裸 GET,报错是正常的)。502 代表后端没起来。

### 6. 心跳 cron

```bash
crontab -e
```

加一行(路径改成你自己的):

```
* * * * * NCM_COOKIE_FILE=/home/ubuntu/.ncm/music_cookie.txt NCM_ROOM_FILE=/home/ubuntu/.ncm/listen_room_id.txt /usr/bin/python3 /home/ubuntu/ncm-mcp-server/heartbeat.py >> /home/ubuntu/.ncm/heartbeat.log 2>&1
```

没有活跃房间时它直接退出,不会乱发请求,可以一直挂着。

### 7. 接到 Claude

Claude.ai → Settings → Connectors → Add custom connector:

- URL:`https://你的域名/ncm/mcp`
- 名称:网易云音乐

连上后应该能看到 16 个工具。

## 使用

### 一起听

1. 你在网易云 APP 里给 AI 号发一起听邀请
2. 告诉 Claude:“我发了一起听邀请”
3. Claude 调 `get_private_list` → `get_private_messages` 解析出 roomId 和 inviterId
4. Claude 调 `accept_listen_together` 加入,房间号自动存下,cron 接手保活

### 点歌

1. Claude 调 `search_music` 拿 songId
2. `add_song` 加进列表
3. **你清一次 APP 后台重进**(列表同步只能这么弄)
4. 之后 `play_command` 切歌,实时生效

### 工具清单

写操作:`accept_listen_together` `end_listen_together` `listen_together_heartbeat` `listen_together_status` `get_room_playlist` `play_command` `add_song` `send_private_message`

读操作:`search_music` `get_song_detail` `get_private_list` `get_private_messages` `get_user_playlist` `get_playlist_detail` `get_login_status` `get_user_detail`

兜底:`http_request`

## 安全

MCP 服务本身没有鲉权。它只听 127.0.0.1,靠 nginx 暴露。**任何知道 `https://你的域名/ncm/mcp` 的人都能操作你的网易云账号**。两个建议:

- 路径别用 `/ncm/`,换成一串随机字符,比如 `/ncm-a7f3k9d2/`
- 或者在 nginx 里加 header 校验,Claude 的 connector 支持自定义 header

cookie 等同账号密码,别提交进仓库,`.gitignore` 已经挡了。

## 排查

| 现象 | 原因 |
|------|------|
| 写操作全 400 | cookie 不完整,缺 `__csrf`;重新跑 `login.py` |
| 读操作报错 | 容器挂了,`sudo docker restart ncmapi` |
| 一起听房间自己断 | 心跳没跑,看 `heartbeat.log` |
| nginx 502 | 服务没起,`systemctl status ncm-mcp` |
| Claude 连不上 | 证书问题或 URL 漏了 `/mcp` |
| 加歌了但 APP 看不到 | 正常,清后台重进 |

## 致谢

基于 Iris & Rei 的接入教程实现。