Files
qianbian/docs/sdk/MCP.md
T

7.6 KiB
Raw Blame History

ppclock-mcp · MCP 服务器参考(v0.2.0-beta)

面向 agent 挂载与部署的工具级参考。SDK 签名见 docs/sdk/API.md,协议细节见 docs/protocol.md。

一句话

ppclock-mcp 是跑在蓝牙物理所在机器上的单层 MCP 服务器:13 个工具覆盖对时 / 模式 / 切换 / 传图 / 模板 / 倒计时 / 日历文字 / 休眠 / 刷屏 / raw 逃生舱,agent 经 stdio 或 streamable HTTP 直接驱动 4.2" 墨水屏设备。

安装

pip install -e ".[mcp]"   # 追加依赖:mcp>=1.23,<2

要求:Python ≥ 3.10、本机蓝牙适配器(bleak)。服务器与被控设备在同一台蓝牙主机上; 不需要互联网。

启动

入口为 console script ppclock-mcp(python -m ppclock.mcp_server 不受支持)。

# stdio —— 本机 agent 直挂
ppclock-mcp --mac AA:BB:CC:DD:EE:FF

# streamable HTTP —— 局域网 agent 平台远程调用
PPCLOCK_MCP_TOKEN=<token> ppclock-mcp --transport http --host 0.0.0.0 --port 8972

启动参数:

参数 默认 说明
--transport stdio stdio / http
--host 127.0.0.1 HTTP 绑定地址;绑非回环地址必须设 PPCLOCK_MCP_TOKEN,否则拒绝启动
--port 8972 HTTP 端口
--mac 无 设备 MAC;缺省自动扫描 NRF- 前缀并记住实际地址
--connect-timeout 90.0 守候连接秒数(覆盖设备 30-60s 广播窗口)
--idle-timeout 300.0 空闲断开秒数;0 = 每次调用独立连接
--allowed-hosts 无 HTTP Host 白名单(逗号分隔)。HTTP 模式绑非回环地址时必须把本机的局域网地址加进来(如 192.168.61.35:8972,localhost:8972),否则 LAN Host 请求被 DNS 重绑定防护拒绝(421);缺省仅 localhost 族

环境变量:PPCLOCK_MCP_TOKEN —— HTTP 模式 Bearer 鉴权令牌(仅 HTTP 使用;stdio 无鉴权, 信任本机进程)。

Agent 挂载示例

# Claude Code(stdio)
claude mcp add ppclock -- ppclock-mcp --mac AA:BB:CC:DD:EE:FF

streamable HTTP 端点为 http://<host>:8972/mcp,请求头携带 Authorization: Bearer <PPCLOCK_MCP_TOKEN>;token 不符返回 401。HTTP 为无状态模式 (stateless_http),无需会话保持。

13 工具参考

全部工具 async,返回统一契约(见下节)。参数与行为逐字对齐 src/ppclock/mcp_tools.py。

工具 参数 说明
scan_devices timeout: float = 5.0 扫描附近 NRF- 前缀墨水屏设备;返回形状 data.devices = [{name,address,rssi}]
device_status 无 查询连接状态/绑定 MAC/设备 ID/空闲秒数。会触发连接守候(最长 --connect-timeout 秒)并刷新空闲计时——周期轮询本工具会阻止 idle 自动断开
set_time tz: float = 8.0 对时;tz 为时区偏移(默认 8=北京时间)
set_mode mode: str 切换显示模式:clock1-3/calendar1-3/image0-3/tricolor/mono
toggle name: str 单字节切换:invert/font/rotate180/hour_format/clock_color
upload_image source: str, slot: int = 0, algo: str = "atkinson", mono: bool = False, threshold/diffusion/brightness/contrast/saturation/rotate: float|None = None 传图到指定槽位。source = 服务器路径或 base64(可带 data URI 前缀);algo ∈ none/floydsteinberg/atkinson/bayer/stucki/jarvis;6 个可选 adjust 参数:threshold/diffusion/brightness/contrast/saturation/rotate(仅显式传入时生效)
render_template name: str, payload: dict|None = None, slot: int = 0, algo: str = "atkinson" 本地渲染模板并上传:schedule/businesscard/memo/course/qrcode/custom
countdown date: str, mode: str = "clock", prefix: str|None = None 倒计时;date 为 ISO YYYY-MM-DD;mode = clock/calendar
countdown_off 无 关闭倒计时
calendar_text text: str 设置日历中文文字并切到日历模式一
set_sleep on: bool, start_h: int, end_h: int 设置休眠时段(0-23 时)
clear_screen 无 刷屏(EPD 清屏)
raw_send data_hex: str, channel: str = "alt" 逃生舱:直发十六进制字节串;channel = rxtx/epd/alt

device_status 返回字段:connected / mac / device_id(尽力而为,失败省略)/ idle_seconds / connect_count / connect_timeout / idle_timeout。

输出契约与错误码

与 CLI --json 同构的统一契约:

成功 {"ok": true,  "tool": "<name>", "data": {...}}
失败 {"ok": false, "tool": "<name>", "error": {"code", "message", "hint"?}}

错误码(5 种):

code 触发 hint
CONNECT_TIMEOUT 守候窗口内未连上设备 设备长睡眠、广播窗口 30-60s;调大 --connect-timeout 或稍后重试
DEVICE_NOT_FOUND 扫描未发现设备 未发现 NRF- 前缀设备;确认设备在位且未处于深睡
BLE_ERROR 其他传输层错误 无 hint
INVALID_PARAM 参数校验失败(非法 base64/非图片/非法日期/非法 hex 等) 无 hint,message 给出具体原因
INTERNAL 工具层兜底未分类异常 无 hint,message 为 类型: 详情

hint 仅对 CONNECT_TIMEOUT / DEVICE_NOT_FOUND 出现,语义是给 agent 的可执行恢复建议 (调参重试 / 检查设备),不是给人看的错误描述。

连接行为(方案 C:按需连接 + 空闲保持)

  • 守候窗口:首次操作发起连接,守候 --connect-timeout 秒(默认 90s,覆盖设备 30-60s 广播窗口);设备在深睡中也能等到其广播。
  • 空闲超时:操作完成后保持连接;空闲 --idle-timeout 秒(默认 300s)自动断开让 设备回睡眠。--idle-timeout 0 退化为每次调用独立连接。
  • 串行:所有设备操作经一把锁串行执行(BLE 适配器独占),并发调用自动排队,不会 互相打断。
  • 重连一次:操作中连接丢失(传输层异常全家:SDK TransportError、bleak 裸抛 BleakError、平台 OSError/超时)→ 断开重连并重试一次,再失败才向上返回错误。

Windows 部署(蓝牙所在机)

python -m venv .venv
.venv\Scripts\pip install -e ".[mcp]"
setx PPCLOCK_MCP_TOKEN "<token>"          # 或按服务方式注入环境变量
.venv\Scripts\ppclock-mcp --transport http --host 0.0.0.0 --port 8972 `
    --allowed-hosts "192.168.61.35:8972,localhost:8972"   # 换成本机局域网地址
  • 防火墙放行 8972/tcp,仅对局域网段开放(勿暴露公网;token 是唯一防线)。
  • --allowed-hosts 必须包含本机的局域网地址(Host 头按 <IP>:<port> 匹配), 漏配时局域网请求被 mcp 的 DNS 重绑定防护拒绝(421)。
  • 不动既有 8971 bridge 与其他服务:8972 为独立端口、独立进程。
  • --mac 建议显式指定设备地址,避免自动扫描误绑其他 NRF- 设备。

不暴露的能力

以下 SDK 能力有意不注册为 MCP 工具:

能力 原因
OTA 固件升级(ota) 高危写闪存,agent 误调用可砖机;只走 CLI 显式 --yes 授权路径
激活(activate/activate_auto) 一次性出厂级操作,日常 agent 场景不需要;保留在 SDK/CLI
LUT 校准(lut) 面板厂商级调试参数,误刷影响显示质量
WiFi 配置(wifi) 本固件为 no-op(固件证据),暴露只会误导 agent
轮播(rotation) 本固件为 no-op(固件证据),同上

需要这些能力时按 docs/sdk/API.md 走 SDK/CLI,不经 MCP 面。