Files
book-mcp/docs/deploy.md
Quentin 9b0910ccb1 Initial commit: book-mcp 教辅处理 MCP server + Arco Vue 管理端
后端 (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→入库→上传→校验)
2026-10-11 18:03:57 +08:00

5.3 KiB
Raw Blame History

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 容器

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(一次性)

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 索引

/tmp/wordparse_venv/bin/python ~/WorkSpace/book-mcp/book_mcp_server.py --init-db

输出:

✓ MongoDB 已就绪(db: book_mcp, collections: [...])
  ✓ 8 个索引创建完成

4. LaunchAgent

# 装(已装好:~/Library/LaunchAgents/ai.book-mcp.server.plist)
launchctl load -w ~/Library/LaunchAgents/ai.book-mcp.server.plist

日常运维

状态查询

# 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

重启

# 软重启(SIGTERM,launchd 30s ThrottleInterval)
kill $(lsof -ti :8100)

# launchd 自动拉起
sleep 5
ps aux | grep book_mcp_server | grep -v grep

调试

# 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:

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/

升级路径

# 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