后端 (book_mcp_server.py, 335 行, 15 个 MCP 工具):
- create_book / add_document / mark_html_ready / mark_json_ready / mark_failed
- update_book_status / soft_delete_book / retry_failed
- get_book / list_books / get_document / list_documents / get_document_url
- upload_to_rustfs / health
- 走 JSON-RPC + stateless_http + json_response(前端可直接调)
- launchd 守护 / 6 秒拉起(macOS)
- systemd 守护脚本(Linux/codelab)
存储:
- MongoDB (mongo:8.0 容器) - book/book_document/document_file 三表
- RustFS 对象存储(fs.code-lab.cn/scan/)- book/<id>/docs/<doc_id>/{docx,html,json}
- 幂等设计: zip_sha256 唯一 + (book_id+original_path) 唯一
前端 (Vue 3 + TS + Arco Design):
- 列表页 /book/list - 搜索 + 状态过滤 + 进度
- 详情页 /book/:id - 文档折叠 + 文件下载
- MCP 客户端 src/api/mcp.ts (JSON-RPC over fetch)
部署:
- deploy/install.sh (codelab 一键装 backend + systemd)
- deploy/install-frontend.sh (vite dev / 生产构建)
- docs/deploy.md (运维手册)
测试:
- tests/test_basic.py (sanity 7 项)
- tests/test_e2e.py (完整 e2e: docx→HTML→入库→上传→校验)
213 lines
5.3 KiB
Markdown
213 lines
5.3 KiB
Markdown
# book-mcp 部署文档
|
||
|
||
## 架构
|
||
|
||
```
|
||
Agent (任意 Agent 客户端)
|
||
↓ HTTP/JSON-RPC
|
||
book-mcp (8100) ──┬─→ MongoDB (27018/book_mcp) ← docker container
|
||
└─→ RustFS (fs.code-lab.cn/scan/) ← 对象存储
|
||
└─→ wordparse (8089) ← docker container docx4j
|
||
```
|
||
|
||
## 组件
|
||
|
||
| 组件 | 位置 | 端口 | 启动方式 |
|
||
|---|---|---|---|
|
||
| **book-mcp** | `~/WorkSpace/book-mcp/book_mcp_server.py` | 8100 | launchd `ai.book-mcp.server` |
|
||
| **MongoDB** | docker container `book-mcp-mongo` | 27018 | `docker start book-mcp-mongo` |
|
||
| **RustFS** | `fs.code-lab.cn` | 443 | 远程 |
|
||
| **wordparse (docx4j)** | docker container `wordparse-test` | 8089 | `docker start wordparse-test` |
|
||
|
||
## 安装(一次性)
|
||
|
||
### 1. MongoDB 容器
|
||
|
||
```bash
|
||
docker run -d \
|
||
--name book-mcp-mongo \
|
||
-p 27018:27017 \
|
||
-e MONGO_INITDB_ROOT_USERNAME=book_admin \
|
||
-e MONGO_INITDB_ROOT_PASSWORD=book_mongo_2026 \
|
||
-e MONGO_INITDB_DATABASE=book_mcp \
|
||
-v book-mcp-mongo-data:/data/db \
|
||
--restart unless-stopped \
|
||
mongo:8.0
|
||
```
|
||
|
||
### 2. Python venv(一次性)
|
||
|
||
```bash
|
||
python3.13 -m venv /tmp/wordparse_venv
|
||
/tmp/wordparse_venv/bin/pip install -r ~/WorkSpace/book-mcp/requirements.txt
|
||
```
|
||
|
||
依赖:`fastmcp boto3 pymongo pyyaml`
|
||
|
||
### 3. MongoDB 索引
|
||
|
||
```bash
|
||
/tmp/wordparse_venv/bin/python ~/WorkSpace/book-mcp/book_mcp_server.py --init-db
|
||
```
|
||
|
||
输出:
|
||
```
|
||
✓ MongoDB 已就绪(db: book_mcp, collections: [...])
|
||
✓ 8 个索引创建完成
|
||
```
|
||
|
||
### 4. LaunchAgent
|
||
|
||
```bash
|
||
# 装(已装好:~/Library/LaunchAgents/ai.book-mcp.server.plist)
|
||
launchctl load -w ~/Library/LaunchAgents/ai.book-mcp.server.plist
|
||
```
|
||
|
||
## 日常运维
|
||
|
||
### 状态查询
|
||
|
||
```bash
|
||
# launchd 状态
|
||
launchctl print gui/501/ai.book-mcp.server | grep -E "state|pid"
|
||
|
||
# 端口
|
||
lsof -i :8100
|
||
|
||
# 健康
|
||
curl http://127.0.0.1:8100/mcp
|
||
# fastmcp 在 /mcp 走 HTTP
|
||
|
||
# 实时日志
|
||
tail -f ~/.hermes/services/book-mcp/logs/server.log
|
||
```
|
||
|
||
### 重启
|
||
|
||
```bash
|
||
# 软重启(SIGTERM,launchd 30s ThrottleInterval)
|
||
kill $(lsof -ti :8100)
|
||
|
||
# launchd 自动拉起
|
||
sleep 5
|
||
ps aux | grep book_mcp_server | grep -v grep
|
||
```
|
||
|
||
### 调试
|
||
|
||
```bash
|
||
# 1. 跑 e2e 测试
|
||
/tmp/wordparse_venv/bin/python ~/WorkSpace/book-mcp/tests/test_e2e.py
|
||
|
||
# 2. 直接调 MCP 工具(fastmcp client)
|
||
/tmp/wordparse_venv/bin/python << 'PYEOF'
|
||
import asyncio
|
||
from fastmcp.client import Client
|
||
async def main():
|
||
async with Client("http://127.0.0.1:8100/mcp") as c:
|
||
r = await c.call_tool('health', {})
|
||
print(r.data)
|
||
asyncio.run(main())
|
||
PYEOF
|
||
|
||
# 3. mongo 直连
|
||
/tmp/wordparse_venv/bin/python << 'PYEOF'
|
||
from db import get_collection, COL_BOOK
|
||
print(f"books count: {get_collection(COL_BOOK).count_documents({})}")
|
||
PYEOF
|
||
```
|
||
|
||
## 配置
|
||
|
||
`~/WorkSpace/book-mcp/config.yaml`:
|
||
|
||
```yaml
|
||
server:
|
||
port: 8100 # MCP server 端口
|
||
database:
|
||
url: mongodb://book_admin:book_mongo_2026@127.0.0.1:27018/book_mcp?authSource=admin
|
||
db_name: book_mcp
|
||
rustfs:
|
||
endpoint: https://fs.code-lab.cn
|
||
default_bucket: scan
|
||
wordparse:
|
||
url: http://127.0.0.1:8089/api/v3/server_office_file/file/parse
|
||
timeout: 600
|
||
```
|
||
|
||
## MCP 工具列表(15 个)
|
||
|
||
| # | 工具 | 类别 |
|
||
|---|---|---|
|
||
| 1 | create_book | 写入 |
|
||
| 2 | add_document | 写入 |
|
||
| 3 | mark_html_ready | 写入 |
|
||
| 4 | mark_json_ready | 写入 |
|
||
| 5 | mark_failed | 写入 |
|
||
| 6 | update_book_status | 写入 |
|
||
| 7 | get_book | 查询 |
|
||
| 8 | list_books | 查询 |
|
||
| 9 | get_document | 查询 |
|
||
| 10 | list_documents | 查询 |
|
||
| 11 | get_document_url | 查询 |
|
||
| 12 | upload_to_rustfs | 辅助 |
|
||
| 13 | soft_delete_book | 辅助 |
|
||
| 14 | retry_failed | 辅助 |
|
||
| 15 | health | 诊断 |
|
||
|
||
## 数据流
|
||
|
||
```
|
||
zip 上传 RustFS
|
||
↓ create_book(zip_sha256)
|
||
→ book.id
|
||
↓ 循环每 docx
|
||
→ add_document(filename, path)
|
||
→ doc.doc_id = sha1(book_id|path)[:16]
|
||
→ wordparse.convert_one (cleaner + docx4j + MathJax)
|
||
→ RustFS upload → mark_html_ready(url)
|
||
→ Agent 解析 HTML → structure.json
|
||
→ RustFS upload → mark_json_ready(url)
|
||
→ update_book_status("done")
|
||
```
|
||
|
||
## 故障排查
|
||
|
||
| 现象 | 原因 | 解决 |
|
||
|---|---|---|
|
||
| `mongo` health=False | 容器没起 | `docker start book-mcp-mongo` |
|
||
| `wordparse` health=False | docx4j 容器没起 | `docker start wordparse-test` |
|
||
| 8100 端口未 listen | 进程挂了 | `kill $(lsof -ti :8100)` 走 launchd 自动拉起 |
|
||
| `add_document` 报 NoneType | 数据库索引问题(已修复) | 重跑 `--init-db` |
|
||
| 上传 403 Forbidden | 桶不存在 | 检查 `default_bucket` 是否在 RustFS 实际存在 |
|
||
| e2e 测试报 `uk_name_version` | 同名教辅已存在 | 改 name 或 version 加时间戳 |
|
||
|
||
## 备份
|
||
|
||
- **MongoDB 数据**:`book-mcp-mongo-data` docker volume(在 docker 里)
|
||
- **RustFS 文件**:`https://fs.code-lab.cn/scan/book/<book_id>/...`
|
||
- **代码**:`~/WorkSpace/book-mcp/`
|
||
|
||
## 升级路径
|
||
|
||
```bash
|
||
# 1. 拉新代码
|
||
cd ~/WorkSpace/book-mcp
|
||
git pull # 假设推到 git
|
||
|
||
# 2. 升级依赖
|
||
/tmp/wordparse_venv/bin/pip install -r requirements.txt --upgrade
|
||
|
||
# 3. 重启 launchd
|
||
kill $(lsof -ti :8100)
|
||
sleep 5
|
||
ps aux | grep book_mcp_server | grep -v grep
|
||
```
|
||
|
||
## 相关链接
|
||
|
||
- 设计文档:`docs/book-mcp-design.md`
|
||
- Schema:`db/schema_doc.md`
|
||
- wordparse 工具:`services/wordparse/`
|
||
- 启动日志:`~/.hermes/services/book-mcp/logs/server.log`
|
||
- 错误日志:`~/.hermes/services/book-mcp/logs/server.error.log` |