Skip to main content
Glama

🎵 方糖音乐 (cubesugar-music)

NAS 音乐库下载壳子 — 配合 Navidrome / Plex / Emby / Subsonic 等自托管音乐服务器,提供壳子 + 多源聚合 + MCP 协议,让你下载的歌曲能正确写 ID3 tag、被播放器识别。

License Python PostgreSQL


⚠️ 重要声明

本项目不内置任何插件。 支持 LX Music 插件格式(用户自行导入)。

  • 用户需要自行通过 Web UI 导入或下载到 sources/ 目录

  • 本项目仅提供:

    • ✅ 壳子(HTTP API + 数据库 + 队列)

    • ✅ 多源聚合上游

    • ✅ MCP 协议(供 AI Agent 接入)

    • ✅ ID3 tag 写入(Navidrome 识别用)

    • ✅ 批量歌单导入

    • ✅ 4 层防重

    • ✅ 本地音乐库索引

    • 不内置任何音源插件


✨ 核心功能

功能

说明

🔍 跨源搜歌

默认走多源聚合

📦 插件支持

支持 LX Music 插件格式,通过 Web UI 导入(Node VM 沙箱执行)

📥 下载队列

2 worker 后台线程,原子抢任务,音质降级(hires → master → atmos → flac24bit → flac → 320k → 128k)

🎵 批量歌单

歌单 URL 一键导入,自动跳过已下载/已存在任务

🚫 4 层防重

①文件系统 ②数据库精确 ③文件模糊匹配 ④本地索引库

🎼 本地索引

自动扫描下载目录建立索引,存 PostgreSQL,跨源跨 ID 查重

🆔 ID3 tag

下载后自动写 FLAC Vorbis Comments / MP3 ID3v2 — Navidrome/Plex 直接识别

🔌 MCP 服务

10 个工具供 Claude / Hermes / Cursor 等 AI Agent 接入(SSE 模式 + 30 天 token)

🌙 主题切换

白天/夜间双主题,CSS 变量切换,localStorage 持久化

🔑 用户管理

JWT 鉴权、修改密码、退出登录


🏗️ 架构

┌─ Web UI (浏览器/外网)
│   ├─ 登录页 (admin/admin)
│   ├─ 搜索/下载/任务
│   └─ 设置 (插件导入 / 音乐库 / MCP / 服务状态)
│
├─ MCP (Claude/Hermes AI Agent 接入, SSE 模式)
│
├─ REST API (8765 端口)
│
└─ Backend
    ├─ upstream 多源聚合 (公开 API)
    ├─ PostgreSQL 5 表
    ├─ Worker threads × 2 (原子抢任务, FOR UPDATE SKIP LOCKED)
    ├─ 插件 (Node VM 沙箱) — 需用户自行导入
    └─ 4 层防重 + ID3 tag 自动写入

🚀 快速开始

方式 1: Docker Compose (推荐)

git clone https://github.com/fangtang0206/cubesugar-music.git
cd cubesugar-music

# 配置环境变量 (可选)
export PG_PASSWORD=your_secure_password
export JWT_SECRET=$(openssl rand -hex 32)
export DOWNLOAD_DIR=/path/to/music  # 默认 ./music

# 启动 (首次会构建镜像,需要 2-3 分钟)
docker compose up -d

# 等 30 秒让服务起来
curl http://127.0.0.1:8765/api/health
# → {"status": "ok", "runtime": "ok", "upstream": "ok", "postgres": "ok", "worker_running": true}

# 打开 Web UI
open http://127.0.0.1:8765/
# 默认账号: admin / admin (登录后立即修改!)

端口占用:

  • 8765 (Web UI + API)

  • 8098 (Node runtime)

  • 54321 (PostgreSQL)

如有冲突,修改 docker-compose.yml 里的端口映射。

方式 2: 直接运行 (开发)

# 1. 准备 PostgreSQL
psql -U root -c "CREATE DATABASE fangtang_music"

# 2. 安装依赖
pip3 install mutagen psycopg[binary]

# 3. 启动 Node runtime
cd node-runtime && node server.js &

# 4. 启动主服务
cd app && python3 server.py

🔌 导入 LX Music 插件

项目不内置任何插件。支持 LX Music 插件格式(.js 文件),首次使用需要导入:

通过 Web UI

  1. 登录 → 右上角 ⚙ 设置 → 📦 插件 tab

  2. 填入插件 JS 文件的 URL → 点击"URL 导入"

  3. 或下载到本地 → 用"文件上传"按钮

通过文件系统

# 复制插件 JS 到 sources 目录
cp /path/to/plugin.js /vol1/1000/docker/cubesugar-music/sources/

# 重启服务 (或点 Web UI 刷新)

推荐插件来源

重要提醒

  • 插件上游 API 可能失效(Cloudflare 拦截、KEY 过期等),多源聚合已能覆盖大部分歌曲

  • 导入前请检查插件代码安全性


⚙️ 配置

环境变量

变量

默认值

说明

PORT

8765

HTTP 服务端口

DOWNLOAD_DIR

/vol2/1000/music

下载目录(host 路径, 必须可写

SOURCES_DIR

/vol1/1000/docker/cubesugar-music/sources

插件目录(需用户填充

WORKER_COUNT

2

后台 worker 线程数

MAX_RETRIES

3

任务最大重试次数

PG_HOST

127.0.0.1

PostgreSQL 主机

PG_PORT

54321

PostgreSQL 端口

PG_USER

root

数据库用户

PG_PASSWORD

cubeSugar_postgresql

数据库密码

PG_DATABASE

fangtang_music

数据库名

LX_RUNTIME_BASE

http://127.0.0.1:8098

Node runtime 地址

SELF_BASE_URL

http://127.0.0.1:8765

MCP 内部调用自己时用

JWT_SECRET

cubesugar-music-default-secret-change-me

生产环境必须改


📚 API 文档

鉴权

# 登录
curl -X POST http://127.0.0.1:8765/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin"}'
# → {"token": "eyJhbG...","user": {...}}

# 后续请求带 token
curl http://127.0.0.1:8765/api/tasks/list \
  -H "Authorization: Bearer eyJhbG..."

# 签发 MCP 长 token (30 天)
curl -X POST http://127.0.0.1:8765/api/auth/mcp-token \
  -H "Authorization: Bearer <token>"
# → {"token": "eyJhbG...","expires_in": 2592000}

搜歌

# 默认跨源
curl "http://127.0.0.1:8765/search?name=海阔天空&artist=Beyond" \
  -H "Authorization: Bearer <token>"

# 指定源
curl "http://127.0.0.1:8765/search?name=test&source=tx"

提交下载任务

curl -X POST http://127.0.0.1:8765/api/tasks/submit \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "wy",
    "song_id": "1357375695",
    "name": "海阔天空",
    "artist": "Beyond",
    "quality": "flac"
  }'

批量歌单导入

curl -X POST http://127.0.0.1:8765/api/playlist/import \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://music.163.com/playlist?id=12345",
    "quality": "flac"
  }'

任务列表 (分页 + 状态筛选)

# 默认 status=all, page=1, page_size=20
curl "http://127.0.0.1:8765/api/tasks/list" -H "Authorization: Bearer <token>"

# 筛选下载成功 / 失败 / 待重试
curl "http://127.0.0.1:8765/api/tasks/list?status=success" -H "Authorization: Bearer <token>"
curl "http://127.0.0.1:8765/api/tasks/list?status=error"   -H "Authorization: Bearer <token>"
curl "http://127.0.0.1:8765/api/tasks/list?status=retry"   -H "Authorization: Bearer <token>"

# 分页
curl "http://127.0.0.1:8765/api/tasks/list?page=2&page_size=50" -H "Authorization: Bearer <token>"

本地音乐库索引

# 状态
curl "http://127.0.0.1:8765/api/library/stats" -H "Authorization: Bearer <token>"

# 查询
curl "http://127.0.0.1:8765/api/library/lookup?artist=Beyond&name=海阔天空" \
  -H "Authorization: Bearer <token>"

# 触发重建 (后台 4-5 分钟)
curl -X POST "http://127.0.0.1:8765/api/library/rescan" -H "Authorization: Bearer <token>"

🔌 MCP 集成 (Claude / Hermes / Cursor)

# ~/.hermes/config.yaml 或 ~/.claude/mcp_servers.json
mcp_servers:
  cubesugar-music:
    url: http://your-host:8765/mcp/sse
    transport: sse
    headers:
      Authorization: Bearer <从 /api/auth/mcp-token 拿到的 30 天 token>
      X-Client: hermes-agent

MCP 工具列表 (10 个)

工具

说明

search_music

搜歌 (跨源)

download_music

下载单首到队列

import_playlist

批量导入歌单

list_tasks

列下载任务 (带状态过滤)

get_task_status

单个任务状态

list_plugins

列插件

import_plugin

导入插件 (URL/文件)

library_stats

本地音乐库统计

library_lookup

查本地库 (artist + name)

library_rescan

触发重建索引


🗂️ 数据库结构

说明

users

用户 (默认 admin)

plugins

插件元数据

download_tasks

下载任务 (status: pending/processing/success/error)

local_library

本地音乐索引 (artist, name, album, file_path)

index_status

索引状态 (最后扫描时间)


🛠️ 开发

项目结构

cubesugar-music/
├── app/                        # Python 主服务
│   ├── server.py               # 主 HTTP 路由
│   ├── fetcher.py            # 多源聚合上游
│   ├── library_index.py        # 本地音乐库扫描器 + 索引查重
│   ├── id3_writer.py           # FLAC/MP3 ID3 tag 写入
│   ├── worker/worker.py        # 后台下歌 worker
│   ├── auth/                   # JWT + PBKDF2 密码哈希
│   ├── db/                     # PostgreSQL 连接池
│   ├── api/mcp.py              # MCP server (SSE)
│   └── playlist.py             # 歌单 URL 解析
├── node-runtime/               # Node 沙箱 (8098 端口)
├── sources/                    # (空) 插件目录 - 用户自行填充
├── docker-compose.yml          # 一键启动
├── Dockerfile
└── README.md

启动开发模式

# 1. 启动 postgres
docker run -d --name cubesugar-db \
  -e POSTGRES_PASSWORD=cubeSugar_postgresql \
  -e POSTGRES_DB=fangtang_music \
  -p 54321:5432 \
  postgres:15-alpine

# 2. 启动 runtime
cd node-runtime && node server.js &

# 3. 启动主服务
cd app
PORT=8765 DOWNLOAD_DIR=/vol2/1000/music \
PG_HOST=127.0.0.1 PG_PORT=54321 \
python3 server.py

🐛 常见问题

Q: 启动后 runtime 提示 500 / plugins 列表空?

A: 项目不内置插件。需要手动导入 LX Music 格式的 .js 插件文件。 A: 正常, 仓内不内置插件, sources/ 目录是空的, 需要自己导入插件 JS 文件。

Q: 搜歌结果显示的歌曲都搜不到?

A: 多源聚合已能覆盖大部分歌曲。如果某首歌搜不到, 检查:

  • upstream 是否在线 (/api/health 状态)

  • 插件是否需要登录账号

  • 公开 API 限流 (稍等再试)

Q: 下载的文件 Navidrome/Plex 显示 "Unknown Artist"?

A: 老文件没 ID3 tag, 手动补:

cd app/
python3 -c "from id3_writer import backfill_existing_files; print(backfill_existing_files('/vol2/1000/music'))"

会扫所有 FLAC/MP3, 从数据库元数据 + 文件路径回推写入 ID3 (4199 首约 30 分钟)

Q: 怎么给 Navidrome/Plex 用?

A: 两者都扫 /vol2/1000/music/ 目录:

  • 库目录指向 /vol2/1000/music/

  • 启用"扫描 ID3 tag"选项

  • 几分钟后歌名/歌手/专辑全部就位


📜 License

MIT License - 见 LICENSE 文件


Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fangtang0206/cubesugar-music'

If you have feedback or need assistance with the MCP directory API, please join our Discord server