Skip to main content
Glama
xiazhe-xz
by xiazhe-xz
README.md
# ESP32-C3 MCP Music Server

这个项目的根目录是 MCP 服务器,用来让 OpenClaw、Claude Desktop 或其他 MCP agent 通过 MQTT 控制 ESP32-C3 音频客户端播放音乐。

ESP32-C3 固件说明在 `esp32-c3-client/README.md`。

## 功能

- 通过 MQTT 向 ESP32-C3 下发播放、暂停、停止、音量、下一首等控制指令
- 从 HTTP 音乐目录读取歌曲列表
- 支持按歌曲名搜索并播放
- 支持顺序播放整个音乐列表
- 支持把播放列表写入 MQTT retained topic,由 ESP32-C3 自己按顺序播放
- 支持清除 ESP32-C3 已保存的 Wi-Fi 配置并重新进入手机配网模式

## 运行要求

- Node.js 18 或更高版本
- 一个可访问的 MQTT broker
- ESP32-C3 客户端已烧录并连接到同一个 MQTT broker
- 一个 HTTP 音乐目录,例如 nginx 暴露的 MP3 文件目录

## 安装

```bash
npm install
```

复制环境变量模板:

```bash
copy .env.example .env
```

Windows PowerShell 也可以用:

```powershell
Copy-Item .env.example .env
```

然后按实际情况修改 `.env`。

## 环境变量

```env
MQTT_BROKER=mqtt://esp32:esp32mqtt2026@localhost:1883
MQTT_TOPIC=esp32-c3/music/play
MQTT_PLAYLIST_TOPIC=esp32-c3/music/playlist/active
MUSIC_LIBRARY_URL=http://47.102.147.204:8080/mp3/
FETCH_TIMEOUT_MS=8000
MAX_PLAYLIST_FETCHES=3
MAX_PLAYLIST_ITEMS=50
```

说明:

- `MQTT_BROKER`: MQTT broker 连接地址,支持带用户名密码的 URL
- `MQTT_TOPIC`: ESP32-C3 接收控制指令的 topic
- `MQTT_PLAYLIST_TOPIC`: 播放列表 retained 缓存 topic 前缀
- `MUSIC_LIBRARY_URL`: HTTP 音乐目录地址,末尾可以不带 `/`
- `FETCH_TIMEOUT_MS`: 拉取音乐目录或播放列表文件的超时时间
- `MAX_PLAYLIST_FETCHES`: 最多解析多少个播放列表文件
- `MAX_PLAYLIST_ITEMS`: 顺序播放时最多缓存多少首歌

## MCP 配置示例

在支持 MCP stdio server 的 agent 中,把命令配置为:

```json
{
  "mcpServers": {
    "esp32-c3-music": {
      "command": "node",
      "args": ["D:\\ESP32-C3-MCP\\index.js"],
      "cwd": "D:\\ESP32-C3-MCP"
    }
  }
}
```

如果 agent 支持环境变量,也可以把 `.env` 里的变量直接放到 MCP server 配置里。

## 可用工具

### `list_music_library`

扫描 `MUSIC_LIBRARY_URL`,返回发现的歌曲名称和 URL。

### `play_music`

播放指定歌曲。可以传:

- `url`: 直接播放这个 URL
- `song_name`: 从音乐库中按名称查找并播放

如果同时传入 `url` 和 `song_name`,优先使用 `url`。

### `play_song_from_library`

只按 `song_name` 从音乐库查找并播放。

### `play_playlist`

按顺序播放音乐库列表。

它会先把列表写入 MQTT retained topic:

```text
esp32-c3/music/playlist/active/meta
esp32-c3/music/playlist/active/item/0
esp32-c3/music/playlist/active/item/1
```

然后向 `MQTT_TOPIC` 发送:

```json
{"action":"play_playlist","start_index":0}
```

ESP32-C3 收到后会从本机缓存的列表开始播放,播完当前歌曲后自己播放下一首。这样 MCP 服务器不需要一直在线。

参数:

- `start_index`: 从第几首开始,默认 `0`
- `max_songs`: 最多缓存并播放多少首,默认 `MAX_PLAYLIST_ITEMS`

### `next_music`

下一首或切歌。

- 传 `url` 或 `song_name`: 直接切到指定歌曲,保持原来的单首播放逻辑
- 不传参数: 发送 `playlist_next`,让 ESP32-C3 在播放列表模式下跳到下一首

### `pause_music`

暂停播放。ESP32-C3 会停止当前播放,但保留最后一次 URL。

### `stop_music`

停止播放并清空最后一次 URL。播放列表模式也会退出。

### `set_volume`

设置音量,范围 `0-100`。

### `reset_wifi`

发送:

```json
{"action":"reset_wifi"}
```

ESP32-C3 收到后会清除保存的 Wi-Fi 配置并重启,重启后开启手机配网热点。

注意:这个工具要求 ESP32-C3 当前仍然在线并连接 MQTT。如果设备已经离线,它收不到这条 MQTT 消息,只能等固件连接失败后自动开启配网热点。

## MQTT 消息约定

控制 topic 默认是:

```text
esp32-c3/music/play
```

常见控制消息:

```json
{"action":"play","url":"http://example.com/song.mp3"}
{"action":"next","url":"http://example.com/next.mp3"}
{"action":"pause"}
{"action":"stop"}
{"action":"set_volume","volume":65}
{"action":"play_playlist","start_index":0}
{"action":"playlist_next"}
{"action":"reset_wifi"}
```

播放列表 topic 默认前缀是:

```text
esp32-c3/music/playlist/active
```

MCP 服务器会发布 retained 消息,ESP32-C3 订阅:

```text
esp32-c3/music/playlist/active/#
```

## 本地检查

检查 Node.js 语法:

```bash
node --check index.js
```

当前 `package.json` 还没有自动化测试脚本。