MyFramework User 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
..
tests 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
.env.example 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
README.md 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
audio_server.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
mcp_pipe.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
mcp_server_http.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
mcp_server_local.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
push_book.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
requirements.txt 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
schedule_push.bat 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
self_test.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
start.bat 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
start.sh 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
verify_all.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
verify_local.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă
verify_pipe.py 21db9a9a16 chore: 入仓 mcp-for-xiaozhi 项目源码 (.env/.venv/__pycache__/*.log 已 gitignore) 1 lună în urmă

README.md

AI有声书 MCP Server(小智AI 智能音箱接入)

把本仓库的 audiobook 后端能力,通过 Model Context Protocol 暴露给小智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_urlget_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 控制台拿到智能体的 MCP 接入点 URL

2. 安装 & 配置

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

启动(首次会自动创建虚拟环境并安装依赖):

# 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. 验证

# 激活虚拟环境
.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)推荐:

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_detailsprogress 字段。
  • 章节的 audioUrl 必须是非 /uploads/ 前缀的公网 OSS 地址(项目里的 BootWatchdog 会检查);若发现 404,按仓库 CLAUDE.mdfix-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

未改动业务代码,纯新增模块。