docs+release: MCP.md 工具参考与部署指南;0.2.0
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
9506490ce2
commit
de683fe9c2
7 files changed
+193
-11
No files matched your search
@@ -1,5 +1,24 @@
|
||||
# CHANGELOG
|
||||
|
||||
## [0.2.0] — 2026-07-30
|
||||
|
||||
新增 **ppclock-mcp**:跑在蓝牙物理所在机器上的单层 MCP 服务器,agent 经 stdio 或
|
||||
streamable HTTP 直驱墨水屏。
|
||||
|
||||
### MCP 服务器
|
||||
- `ppclock-mcp` 命令(`ppclock.mcp_server:main`):stdio / streamable HTTP 双模,
|
||||
HTTP 绑非回环地址强制 `PPCLOCK_MCP_TOKEN` Bearer 鉴权(ASGI 中间件,不符 401)
|
||||
- 13 个工具(`ppclock.mcp_tools`):scan_devices / device_status / set_time / set_mode /
|
||||
toggle / upload_image(路径或 base64,6 抖动+6 调整参数)/ render_template(6 模板)/
|
||||
countdown / countdown_off / calendar_text / set_sleep / clear_screen / raw_send
|
||||
- 统一输出契约与 CLI `--json` 同构:`{"ok","tool","data"|"error":{"code","message","hint"?}}`,
|
||||
错误码 CONNECT_TIMEOUT / DEVICE_NOT_FOUND / BLE_ERROR / INVALID_PARAM / INTERNAL
|
||||
- **DeviceManager 公开为子包能力**(`ppclock.device_manager`,方案 C 连接管理):
|
||||
按需连接 + 空闲保持,守候窗口覆盖设备 30-60s 广播窗口(`--connect-timeout` 默认 90s),
|
||||
空闲自动断开(`--idle-timeout` 默认 300s),全操作串行,掉线重连重试一次
|
||||
- 有意不暴露:OTA / 激活 / LUT / WiFi / 轮播(高危或本固件 no-op,走 SDK/CLI)
|
||||
- 文档:`docs/sdk/MCP.md`(工具参考 + agent 挂载 + Windows 部署)
|
||||
|
||||
## [0.1.0] — 2026-07-30
|
||||
|
||||
首个 SDK 化发布。4.2寸墨水屏设备(DA14585 BLE,400×300 黑白红三色)的**完全离线**开发包:
|
||||
|
||||
@@ -36,6 +36,24 @@ async with PPClient.via_bridge("192.168.61.35:8971") as dev: # 经 bridge
|
||||
设备操作全集:对时(tz)/模式/切换/传图/6 模板/倒计时/休眠/停车牌/轮播/LUT/WiFi/raw/OTA,
|
||||
见 [`docs/sdk/API.md`](docs/sdk/API.md)。
|
||||
|
||||
## MCP 服务器(agent 直挂)
|
||||
|
||||
`ppclock-mcp` 在蓝牙物理所在机器上跑单层 MCP 服务器,13 个工具覆盖对时/模式/传图/
|
||||
模板/倒计时/休眠等日常操作:
|
||||
|
||||
```bash
|
||||
pip install -e ".[mcp]" # 追加依赖 mcp
|
||||
|
||||
# stdio —— Claude Code 等本机 agent 直挂
|
||||
claude mcp add ppclock -- ppclock-mcp --mac AA:BB:CC:DD:EE:FF
|
||||
|
||||
# streamable HTTP —— 局域网 agent 平台(Bearer 鉴权,端点 /mcp)
|
||||
PPCLOCK_MCP_TOKEN=<token> ppclock-mcp --transport http --host 0.0.0.0 --port 8972
|
||||
```
|
||||
|
||||
连接管理为方案 C(按需连接+空闲保持、串行、掉线重连一次);OTA/激活/LUT/WiFi/轮播
|
||||
有意不暴露。工具参考与部署指南见 [`docs/sdk/MCP.md`](docs/sdk/MCP.md)。
|
||||
|
||||
## CLI 用法
|
||||
|
||||
```bash
|
||||
@@ -97,7 +115,7 @@ ppclock --json ota firmware.img --yes # SUOTA
|
||||
## 开发
|
||||
|
||||
```bash
|
||||
.venv/bin/python -m pytest tests/ -q # 165 测试
|
||||
.venv/bin/python -m pytest tests/ -q # 195 测试
|
||||
```
|
||||
|
||||
治理规则见 `GOVERNANCE.md`;变更记录 `CHANGELOG.md`;决策日志 `DECISIONS.md`。
|
||||
|
||||
+5
-2
@@ -1,6 +1,6 @@
|
||||
# ppclock SDK · API 参考(v0.1.0)
|
||||
# ppclock SDK · API 参考(v0.2.0)
|
||||
|
||||
> 面向二次开发的签名级参考。协议细节见 `docs/protocol.md`,固件内部见 `docs/firmware-analysis.md`。
|
||||
> 面向二次开发的签名级参考。协议细节见 `docs/protocol.md`,固件内部见 `docs/firmware-analysis.md`。MCP 服务器(ppclock-mcp)工具参考见 `docs/sdk/MCP.md`。
|
||||
|
||||
## 安装与入口
|
||||
|
||||
@@ -84,6 +84,9 @@ from ppclock import PPClient
|
||||
| `ppclock.firmware.image` | `parse_image/unpack_body/pack_image`('pQ' 镜像) |
|
||||
| `ppclock.firmware.ota` | `run_ota/package_image/xor_checksum/STATUS_ERRORS` |
|
||||
| `ppclock.bridge_server` | `run()`(`ppclock-bridge` 入口) |
|
||||
| `ppclock.mcp_server` | `main()`(`ppclock-mcp` 入口,stdio/HTTP 双模)、`build_server`、`TokenAuthMiddleware` |
|
||||
| `ppclock.device_manager` | `DeviceManager`(方案 C:按需连接+空闲保持、串行、重连重试一次) |
|
||||
| `ppclock.mcp_tools` | `register_tools`(13 工具注册)、`decode_image_source` |
|
||||
|
||||
## Bridge RPC 协议(v1,JSONL/TCP,默认 8971)
|
||||
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
# ppclock-mcp · MCP 服务器参考(v0.2.0)
|
||||
|
||||
> 面向 agent 挂载与部署的工具级参考。SDK 签名见 `docs/sdk/API.md`,协议细节见 `docs/protocol.md`。
|
||||
|
||||
## 一句话
|
||||
|
||||
ppclock-mcp 是跑在**蓝牙物理所在机器**上的单层 MCP 服务器:13 个工具覆盖对时 / 模式 /
|
||||
切换 / 传图 / 模板 / 倒计时 / 日历文字 / 休眠 / 刷屏 / raw 逃生舱,agent 经 stdio 或
|
||||
streamable HTTP 直接驱动 4.2" 墨水屏设备。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
pip install -e ".[mcp]" # 追加依赖:mcp>=1.10,<2
|
||||
```
|
||||
|
||||
要求:Python ≥ 3.10、本机蓝牙适配器(bleak)。服务器与被控设备在同一台蓝牙主机上;
|
||||
不需要互联网。
|
||||
|
||||
## 启动
|
||||
|
||||
入口为 console script `ppclock-mcp`(`python -m ppclock.mcp_server` 不受支持)。
|
||||
|
||||
```bash
|
||||
# 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` = 每次调用独立连接 |
|
||||
|
||||
环境变量:`PPCLOCK_MCP_TOKEN` —— HTTP 模式 Bearer 鉴权令牌(仅 HTTP 使用;stdio 无鉴权,
|
||||
信任本机进程)。
|
||||
|
||||
## Agent 挂载示例
|
||||
|
||||
```bash
|
||||
# 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- 前缀墨水屏设备,返回 `[{name,address,rssi}]` |
|
||||
| `device_status` | 无 | 查询连接状态/绑定 MAC/设备 ID/空闲秒数 |
|
||||
| `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` 同构的统一契约:
|
||||
|
||||
```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 适配器独占),并发调用自动排队,不会
|
||||
互相打断。
|
||||
- **重连一次**:操作中连接丢失(TransportError)→ 断开重连并重试一次,再失败才向上
|
||||
返回错误。
|
||||
|
||||
## Windows 部署(蓝牙所在机)
|
||||
|
||||
```powershell
|
||||
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
|
||||
```
|
||||
|
||||
- 防火墙放行 **8972/tcp**,仅对局域网段开放(勿暴露公网;token 是唯一防线)。
|
||||
- 不动既有 **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 面。
|
||||
@@ -1,6 +1,6 @@
|
||||
# ppclock — 4.2寸墨水屏设备(DA14585 BLE)离线 SDK
|
||||
|
||||
> AI 消费向项目卡(llms.txt v0.1.0)。人用文档见 README.md;签名级 API 见 docs/sdk/API.md。
|
||||
> AI 消费向项目卡(llms.txt v0.2.0)。人用文档见 README.md;签名级 API 见 docs/sdk/API.md;MCP 服务器见 docs/sdk/MCP.md。
|
||||
|
||||
## 一句话
|
||||
|
||||
@@ -10,12 +10,13 @@ ppclock 是 4.2" 400×300 黑白红三色墨水屏设备(Dialog DA14585,广
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
||||
.venv/bin/python -m pytest tests/ -q # 165 全绿
|
||||
.venv/bin/python -m pytest tests/ -q # 195 全绿
|
||||
```
|
||||
|
||||
- 库:`from ppclock import PPClient`
|
||||
- CLI:`ppclock [--json] [--mac X] [--via bridge://host[:port]] <cmd>`
|
||||
- BLE 桥:`ppclock-bridge --host 0.0.0.0 --port 8971`(在他机蓝牙物理所在机运行,本机经 `--via` 透明使用)
|
||||
- MCP 服务器:`ppclock-mcp [--mac X] [--transport http --host 0.0.0.0 --port 8972]`(`PPCLOCK_MCP_TOKEN` 鉴权;extra `.[mcp]`)
|
||||
|
||||
## 快速示例
|
||||
|
||||
@@ -28,6 +29,8 @@ async with PPClient.via_bridge("192.168.61.35:8971", mac="18:BC:5A:5D:BF:28") as
|
||||
await dev.activate_auto() # 离线激活(破解厂商云)
|
||||
```
|
||||
|
||||
MCP 挂载(agent 直挂 13 工具):`claude mcp add ppclock -- ppclock-mcp --mac X`,或 HTTP 端点 `http://<host>:8972/mcp` + Bearer token;详见 docs/sdk/MCP.md。
|
||||
|
||||
## 架构(关键不变量)
|
||||
|
||||
1. **命令走 331f(alt 通道)**:1f1f 只 ATT-ACK 不执行(实机证据,勿用)。
|
||||
@@ -38,11 +41,11 @@ async with PPClient.via_bridge("192.168.61.35:8971", mac="18:BC:5A:5D:BF:28") as
|
||||
|
||||
## 目录
|
||||
|
||||
- `src/ppclock/`:client.py(门面)/ protocol / image_pipeline / templates / transports(base,local,bridge) / firmware(image,ota) / cli / bridge_server
|
||||
- `src/ppclock/`:client.py(门面)/ protocol / image_pipeline / templates / transports(base,local,bridge) / firmware(image,ota) / cli / bridge_server / ppclock-mcp(mcp_server 入口 / device_manager 连接管理 / mcp_tools 13 工具)
|
||||
- `tools/`:fw_info/fw_pack(镜像工具)、field_test(真机引导测试)、flash_run、gpio_probe、rppclock.sh(守候重试)
|
||||
- `docs/`:protocol.md(协议规范·唯一事实源)、sdk/API.md、architecture.md、firmware-analysis.md、firmware-layout.md、field-test-result.md
|
||||
- `docs/`:protocol.md(协议规范·唯一事实源)、sdk/API.md、sdk/MCP.md、architecture.md、firmware-analysis.md、firmware-layout.md、field-test-result.md
|
||||
- `analysis/`:三线逆向证据(web/apk/firmware)
|
||||
- `tests/`:165 测试
|
||||
- `tests/`:195 测试
|
||||
|
||||
## 设备事实(实测 NRF-5DBF28)
|
||||
|
||||
@@ -60,4 +63,4 @@ async with PPClient.via_bridge("192.168.61.35:8971", mac="18:BC:5A:5D:BF:28") as
|
||||
|
||||
## 版本
|
||||
|
||||
0.1.0(CHANGELOG.md)。治理:GOVERNANCE.md(证据纪律/门禁);历史决策:DECISIONS.md。
|
||||
0.2.0(CHANGELOG.md)。治理:GOVERNANCE.md(证据纪律/门禁);历史决策:DECISIONS.md。
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ppclock"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
description = "4.2寸墨水屏设备离线 CLI 上位机(DA14585 BLE,agent 友好)"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
- transports:local(bleak)/bridge(RPC) 传输实现
|
||||
- firmware:镜像解析重打包(image)与 SUOTA(ota)
|
||||
- bridge_server:BLE 桥服务端(ppclock-bridge 命令)
|
||||
- device_manager / mcp_tools / mcp_server:MCP 服务器(ppclock-mcp 命令)
|
||||
"""
|
||||
__version__ = "0.1.0"
|
||||
__version__ = "0.2.0"
|
||||
|
||||
from .client import PPClient
|
||||
from .transports.base import Transport, TransportError
|
||||
|
||||
Reference in new issue
Block a user