# AI有声书 MCP Server(小智AI 智能音箱接入) 把本仓库的 audiobook 后端能力,通过 [Model Context Protocol](https://modelcontextprotocol.io/) 暴露给**小智AI**智能音箱的大模型。 ## 目录 ``` mcp-for-xiaozhi/ ├── audio_server.py # 工具实现(纯模块,无 I/O) ├── mcp_pipe.py # 小智AI WebSocket 桥接(in-process 模式) ├── self_test.py # 不开进程的纯 WS 自检脚本 ├── verify_local.py # stdio 客户端测试工具注册 + 调用 ├── verify_pipe.py # 真小智AI 端到端联调 ├── verify_all.py # 一键跑两套 ├── start.sh / start.bat # 跨平台启动 ├── requirements.txt ├── .env.example └── README.md ``` ## 工作原理 ``` ┌──────────────┐ WebSocket (wss) ┌──────────┐ │ 小智AI 大模型 │ ◀───────────────────▶ │ 小智音箱 │ └──────────────┘ └──────────┘ │ │ JSON-RPC over WebSocket ▼ ┌────────────────────┐ HTTP ┌─────────────┐ │ mcp_pipe.py │ ───────────▶ │ audiobook │ │ (本进程) │ │ 后端 :3000 │ │ ├── 工具实现 │ └─────────────┘ │ (import audio_server) └────────────────────┘ ``` ## MCP 工具清单(5 个核心 + 3 个 deprecated) | 工具 | 用途 | 关键参数 | |------|------|----------| | `search_audiobooks` | 按关键词搜书 | `keywords` | | `list_categories` | 列出分类 | — | | `get_book_details` | 书籍详情 + 章节列表 | `book_id` | | **`read_chapter`** | **统一读章节**:audio 给URL直接播,text 给正文自己TTS,auto 智能选 | `chapter_id`, `format` | | `generate_audiobook` | 一键 AI 生成新书 | `title`, `description` | > 旧的 `get_chapter_audio_url` 和 `get_chapter_text` 已被 `read_chapter` 取代并从 schema 中移除(小智 1024 字节限制)。 > 如有遗留调用,请改用 `read_chapter(chapter_id, format='audio'|'text')`。 > ⚠️ **小智AI 返回值限制约 1024 字节**——所有工具内部会做截断,并在 `tip`/`truncated` 字段说明。 > tools/list schema 当前 910 字节(< 1024)。 ## 快速开始 ### 1. 准备工作 - 后端 audiobook 服务跑起来(默认 `http://127.0.0.1:3000`) - Python 3.10+ - 从 [xiaozhi.me](https://xiaozhi.me) 控制台拿到智能体的 MCP 接入点 URL ### 2. 安装 & 配置 ```bash cd mcp-for-xiaozhi cp .env.example .env # 编辑 .env,填入: # MCP_ENDPOINT=wss://api.xiaozhi.me/mcp/?token=... # AUDIOBOOK_API_BASE=http://127.0.0.1:3000 ``` 启动(首次会自动创建虚拟环境并安装依赖): ```bash # macOS / Linux bash start.sh # Windows start.bat ``` 启动成功会看到: ``` 2025-... - MCP_PIPE - INFO - AudioBook MCP server connecting to wss://api.xiaozhi.me/mcp/... 2025-... - MCP_PIPE - INFO - API base = http://127.0.0.1:3000 2025-... - MCP_PIPE - INFO - WS connected 2025-... - MCP_PIPE - INFO - <- initialize id=0 2025-... - MCP_PIPE - INFO - -> response for initialize id=0 (166 bytes) 2025-... - MCP_PIPE - INFO - <- tools/list id=1 2025-... - MCP_PIPE - INFO - -> response for tools/list id=1 (2784 bytes) ``` 只要不退出进程、也不报错,就说明已经接入小智AI——音箱上跟智能体对话即可触发工具。 ### 3. 验证 ```bash # 激活虚拟环境 .venv\Scripts\activate # Windows source .venv/bin/activate # macOS/Linux # 测试 1:stdio 客户端跑工具(不需要小智AI) python verify_local.py # 测试 2:真小智AI 端到端联调(需要 .env 里填了 MCP_ENDPOINT) python verify_pipe.py # 一键跑 python verify_all.py ``` ## 架构选择 ### 为什么不沿用官方 mcp-calculator 的 stdio + subprocess 模式 小智AI 官方示例([mcp-calculator](https://github.com/78/mcp-calculator))推荐: ```bash python mcp_pipe.py calculator.py # 子进程模式 ``` 但在 **Windows + Python 3.14** 上实测发现,`subprocess.Popen(stdin=PIPE, stdout=PIPE)` 启动的子进程,**父进程写到子进程 stdin 的字节永远读不到**(pipe 怪行为,跟 asyncio / sync 无关,跟 child 是否有 `import urllib` 无关,跟 child 是否预热 pipe 也无关——直接 stdio 测试却正常)。 排除步骤(结论):inline `subprocess` + `echo ... | python audio_server.py` ✅ / `subprocess.Popen` 通过 mcp_pipe 启动 child ❌。 本仓库的解决方案:**in-process 模式**——`mcp_pipe.py` 直接 `import audio_server` 拿到工具实现 + `handle_request()` 函数,**完全不用 subprocess**。同一个进程里用 `websockets.sync` 跟小智AI 通信。 这样: - 没有任何跨进程 pipe 问题 - 性能更好(少一次进程切换 + IPC) - 部署更简单(一个进程) 如果以后需要换到多进程/多机部署,可以再把 `audio_server.handle_request` 包成 HTTP / TCP 服务。 ## 工具调用流程示例 用户在小智音箱说:**"我想听三国演义"** ``` 1. 大模型调 search_audiobooks(keywords="三国演义") → 返回 [{id: 42, title: "三国演义", ...}] 2. 大模型调 get_book_details(book_id=42) → 返回 chapters: [{id: 1001, title: "第一回 宴桃园...", has_audio: true}, ...] 3. 大模型调 read_chapter(chapter_id=1001, format="audio") → 返回 {audio_url: "https://...", title: "第一回 ..."} 4. 音箱直接播放 audio_url ``` **format 三态语义:** | format | 行为 | 返回 | |--------|------|------| | `audio` | 有 full 音频直返 URL;无则触发 on-demand TTS(项目自有 CosyVoice 高质量合成) | `{audio_url, audio_source: 'full'\|'on_demand', ...}` | | `text` | 章节正文(stripMarkdown + 分页) | `{action: 'RESPONSE', response: '...正文...'}` | | `auto` | 有音频 → audio;无音频 → text | 同上 | ## 已知约束 / 注意事项 - 后端 `/api/book-generator/books/:id/batch-generate` 的 batch-generate 走 LangGraph + LLM,**3-5 分钟**才完成第一次生成;中途状态查 `get_book_details` 看 `progress` 字段。 - 章节的 `audioUrl` 必须是非 `/uploads/` 前缀的公网 OSS 地址(项目里的 BootWatchdog 会检查);若发现 404,按仓库 `CLAUDE.md` 走 `fix-local-audio-urls.ts` 修复脚本。 - `mcp_pipe.py` 使用了 `websockets>=12` 的 sync 客户端;如果是 Python 3.10 以下请装 `websockets<11`。 - Windows 上跑 `start.bat` 会自动创建 `.venv`;手动跑用 `.venv\Scripts\python.exe mcp_pipe.py`。 - tools/list 的返回是 2.7KB 左右,超过小智AI 1024 字节限制。**大模型在调用工具时仍能看到完整的工具 schema**(小智AI 会在系统提示词里展示,调用时再按需获取详情),所以不影响实际使用。后续如果需要更紧凑,可以让每个工具的 description 拆成 `summary` + `details` 两段。 ## 文件改动清单 新增(本目录): - `audio_server.py` — 工具实现(纯模块,可 import) - `mcp_pipe.py` — WebSocket 桥接 - `self_test.py` — 纯 WS 自检 - `verify_local.py` / `verify_pipe.py` / `verify_all.py` — 测试 - `start.sh` / `start.bat` — 启动 - `requirements.txt` / `.env.example` / `README.md` 未改动业务代码,纯新增模块。