Skip to main content
Glama
andy-qingcai

PPK2 MCP Server

by andy-qingcai
README.md
# PPK2 MCP Server

Nordic Semiconductor **Power Profiler Kit II (PPK2)** 的 Model Context Protocol (MCP) 服务器。
让 LLM 直接完成功耗剖析:控制硬件采集电流(500 nA–2000 mA @ 100 kSa/s + 8 路逻辑口)、
给 DUT 供电(源表 0.8–5 V),采集数据落盘 npz,再做离线分析——统计、功耗分段、
电池续航估算,回答"睡眠电流多少 / 活动占空比多少 / 一节 CR2032 能跑多久"。

- 开发方式:**DDD**(四层 + 依赖倒置),见 `docs/PLAN.md`
- 协议逆向与真机验证笔记:`docs/NOTES.md`(真机 18 项自检 0 FAIL)
- **19 个 MCP 工具**:连接/配置/采集落盘/离线分析
- **采样数据只落盘**(npz),工具返回摘要 + 包络 + 路径,绝不内联数组
- 协议层自研(规避 GPLv2 的 ppk2-api),对照 Nordic 官方开源 app 逐条验证,
  增加了官方 app 同款的**模 64 计数器丢样检测**(IRNAS 库没有)

## 快速开始

```bash
cd /Users/andylos/mcp_gen/PPK2
python3 -m venv .venv
.venv/bin/pip install -e . pytest
.venv/bin/python -m pytest tests/            # 56 个测试:mock 设备全栈 + MCP 协议级
.venv/bin/python scripts/probe_device.py     # 真机端到端自检(18 项)
PPK2_MOCK=1 .venv/bin/ppk2-mcp               # 无硬件演示(mock 设备)
```

PPK2 经 USB CDC 串口连接(免驱);插入后绿灯亮即可,无需其他配置。
macOS 上会出现两个 `cu.usbmodem*` 口,服务器自动探测 0x19 应答识别命令口。

## 配置(环境变量)

| 变量 | 默认 | 说明 |
|---|---|---|
| `PPK2_PORT` | 自动发现 | 指定串口(跳过探测) |
| `PPK2_DATA_DIR` | `./data` | 采集 npz 保存目录 |
| `PPK2_CAPTURE_MAX_S` | `60` | `capture` 工具时长上限(长采集用 start/stop) |
| `PPK2_TIMEOUT` | `15` | 普通操作超时(秒) |
| `PPK2_MOCK` | 关 | `1` = 内存模拟设备(无硬件演示/CI) |

## 接入 MCP 客户端

ZCode(`.zcode/settings.json`)或 Claude Desktop:

```json
{
  "mcpServers": {
    "ppk2": {
      "command": "/Users/andylos/mcp_gen/PPK2/.venv/bin/python",
      "args": ["-m", "ppk2_mcp.server"],
      "cwd": "/Users/andylos/mcp_gen/PPK2",
      "env": {
        "PPK2_DATA_DIR": "/Users/andylos/mcp_gen/PPK2/data"
      }
    }
  }
}
```

## 工具总览(19 个)

| 分组 | 工具 |
|---|---|
| 系统/连接 (5) | `list_devices` `connect` `disconnect` `get_status` `raw_command`(逃生舱;RESET 需 confirm) |
| 配置 (5) | `set_mode`(AMPERE/SOURCE) `set_source_voltage`(800-5000mV) `set_dut_power` `set_resistor_range`(锁定/恢复自动) `set_spike_filtering` |
| 采集 (4) | `capture`(定长→落盘→摘要+包络) `start_capture`/`stop_capture`(长采集) `get_capture_status` |
| 离线分析 (5) | `analyze_capture`(统计+子窗+包络) `detect_activity_segments`(功耗分段/占空比) `estimate_battery_life`(续航) `read_logic_channels`(逻辑口 stats/edges) `list_captures` |

## 典型工作流

```
list_devices -> connect -> set_mode(AMPERE)      # 或 SOURCE + set_source_voltage(3300)
capture(5.0)                                      # 采集 5s,返回摘要+1000 点包络+路径
analyze_capture("cap_x", start_s=1, end_s=2)     # 子窗统计(µC 电量 / µJ 能量)
detect_activity_segments("cap_x", threshold_ua=50, min_duration_s=0.01)
estimate_battery_life(capture_id="cap_x", capacities_mah=[120, 240])
read_logic_channels("cap_x", channel=0, mode="edges")   # 逻辑口与电流同步采样
```

DUT 供电流程:SOURCE 模式下 `set_source_voltage(3300)` → `set_dut_power(true)`
→ `capture(...)` → `set_dut_power(false)`。图表语义与官方 app 一致:SPM 模式
显示的仍是负载电流,电压即设定值。

## 架构(DDD)

```
interfaces(server.py 组合根,19 工具)
   └── application(PPK2Service 用例编排,不变式校验)
          └── domain(值对象/换算器+尖峰滤波状态机/分析服务纯函数/Port 接口)
                 └── infrastructure 实现 Port:串口协议+设备网关 / npz 仓库 / mock 设备
```

依赖方向自外向内;domain 零 IO 零框架。测试金字塔:领域纯函数 → 协议编解码
(真机元数据 fixture)→ mock 设备全栈用例 → FastMCP 协议级内存会话。

## 已知边界

- 设备未校准(`Calibrated: 0`)时按官方缺省系数换算,工具响应带告警;
  校准请在官方 nRF Connect Power Profiler 中完成
- 模式切换/DUT 上电后设备有预热延迟,首采样本数可能偏低——响应带告警,建议重采
- `raw_command` 发 0x20(RESET)会触发 USB 重枚举,服务器自动清理会话,
  需重新 connect
- 长采集(start/stop)无时长上限,但 npz 体积 ≈500 KB/s,注意磁盘

TDQS

A3.7/5.0

Scored across 19 tools

Disambiguation5/5

Each tool targets a distinct action or resource: discovery vs. connection, device configuration setters, capture lifecycle, and post-capture analysis. The only adjacent pair is capture vs. start/stop_capture, but the blocking <=60s vs. background long-capture distinction is explicit, so misselection is unlikely.

Naming Consistency4/5

Names are uniformly snake_case and almost all follow verb_noun or verb_object patterns (list_captures, set_mode, get_capture_status). Minor deviations like connect, disconnect, capture, and raw_command are conventional and readable rather than inconsistent.

Tool Count4/5

19 tools is on the higher side but reasonable for a full-featured PPK2 client spanning device discovery, configuration, capture, analysis, and logic channels. No obvious redundant tool exists, though the capture lifecycle could be seen as slightly expansive.

Completeness4/5

The surface covers the core lifecycle: discover, connect, configure, capture (short and long), monitor, stop, analyze, segment, estimate battery, and read logic channels. Minor gaps like deleting/exporting captures, explicit sample-rate control, or calibration writes are mostly addressable via raw_command.

Maintenance

ActivityMaintained
ResponsivenessNo issues