|
1 | | -# Changelog |
| 1 | +# SmartTune MCP 能力对齐 — 变更文档 |
2 | 2 |
|
3 | | -All notable changes to SmartTune CLI will be documented in this file. |
| 3 | +**日期:** 2026-05-19 |
| 4 | +**范围:** MCP Server / Services 层 / 图表生成 |
| 5 | +**测试:** 141 passed, 0 failed |
4 | 6 |
|
5 | | -## [2.3.1] — 2026-05-19 |
| 7 | +--- |
| 8 | + |
| 9 | +## 1. 变更总览 |
| 10 | + |
| 11 | +本次升级解决了 MCP 接口远落后于 CLI 的问题。CLI 有 8 条命令(`platforms`, `quality`, `analyze`, `pid`, `fft`, `magfit`, `sysid`, `filter`, `hardware`),而旧版 MCP 只暴露了 3 个 tool 且实现简陋。 |
| 12 | + |
| 13 | +| 维度 | 升级前 | 升级后 | |
| 14 | +|------|--------|--------| |
| 15 | +| MCP Tools | 3 | **10** | |
| 16 | +| analysis.py 公开函数 | 3 (`load_flight_data`, `get_log_quality`, `analyze_log`) | **9** (+`analyze_pid/fft/magfit/sysid/filter/hardware`) | |
| 17 | +| serialize.py 序列化器 | 5 | **8** (+`sysid/filter/extra`) | |
| 18 | +| 图表生成 | 无 | **新模块 `plot.py`** — 3 种图表 base64 PNG | |
| 19 | +| 代码行数 | 936 行(3 文件) | **2231 行**(4 文件) | |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## 2. 文件清单 |
| 24 | + |
| 25 | +| 文件 | 行数 | 状态 | 说明 | |
| 26 | +|------|------|------|------| |
| 27 | +| `smarttune/mcp_server.py` | 422 → 724 | **重写** | 3 tool → 10 tool | |
| 28 | +| `smarttune/services/analysis.py` | 240 → 746 | **重写** | 3 函数 → 9 函数 | |
| 29 | +| `smarttune/services/serialize.py` | 274 → 337 | **增补** | +3 序列化器 | |
| 30 | +| `smarttune/services/plot.py` | 0 → 424 | **新增** | base64 图表生成 | |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +## 3. MCP Tool 对照表 |
| 35 | + |
| 36 | +### 3.1 已有 Tool(保留或增强) |
| 37 | + |
| 38 | +| # | MCP Tool | CLI 命令 | 变更说明 | |
| 39 | +|---|----------|----------|----------| |
| 40 | +| 1 | `smarttune_list_platforms` | `stune platforms` | 无改动 | |
| 41 | +| 2 | `smarttune_log_quality` | `stune quality` | **重写**:补齐 4 维评分 | |
| 42 | +| 3 | `smarttune_analyze_log` | `stune analyze` | **扩充**:新增 sysid/filter/extra 模块 | |
| 43 | + |
| 44 | +`smarttune_log_quality` 旧版仅调用 `fd.validate()`,现在与 CLI 完全一致: |
| 45 | + |
| 46 | +- **数据完整性** — PID/gyro/mag/motor/battery 各通道是否存在 |
| 47 | +- **飞行时长** — 是否满足最低分析要求 |
| 48 | +- **摇杆激励** — 每轴检测 step response 窗口数 |
| 49 | +- **采样率一致性** — 计算 jitter 和 drop rate |
| 50 | + |
| 51 | +`smarttune_analyze_log` 新增模块: |
| 52 | + |
| 53 | +- `sysid` — ARX 系统辨识(通过 `include_modules` 选择) |
| 54 | +- `filter` — 滤波器传递函数 |
| 55 | +- `extra` — 平台专属分析器(Betaflight FF/RPM/DTerm) |
| 56 | +- Markdown 渲染器同步补齐这三个 section |
| 57 | + |
| 58 | +### 3.2 新增 Tool |
| 59 | + |
| 60 | +| # | MCP Tool | CLI 命令 | 参数 | |
| 61 | +|---|----------|----------|------| |
| 62 | +| 4 | `smarttune_analyze_pid` | `stune pid` | `log_path`, `platform`, `axis`, `max_recommendations` | |
| 63 | +| 5 | `smarttune_analyze_fft` | `stune fft` | `log_path`, `platform`, `max_recommendations` | |
| 64 | +| 6 | `smarttune_analyze_magfit` | `stune magfit` | `log_path`, `platform`, `max_recommendations` | |
| 65 | +| 7 | `smarttune_analyze_sysid` | `stune sysid` | `log_path`, `platform`, `axis`, `na`, `nb` | |
| 66 | +| 8 | `smarttune_analyze_filter` | `stune filter` | `log_path`, `platform`, `gyro_filter_hz`, `notch_freq_hz`, `auto_derive` | |
| 67 | +| 9 | `smarttune_analyze_hardware` | `stune hardware` | `log_path`, `platform` | |
| 68 | +| 10 | `smarttune_generate_plot` | `stune pid/fft/filter --visual` | `log_path`, `plot_type`, `platform`, `axis`, `theme` | |
| 69 | + |
| 70 | +### 3.3 `smarttune_generate_plot` 详细说明 |
| 71 | + |
| 72 | +CLI 的 `--visual` 将 matplotlib 图保存为本地 PNG 文件。MCP 不能写文件给用户,因此改为返回 **base64 Data URL**,agent 可直接用 `<img src="...">` 渲染,或转存为 PNG。 |
| 73 | + |
| 74 | +**参数:** |
| 75 | + |
| 76 | +| 参数 | 类型 | 默认值 | 说明 | |
| 77 | +|------|------|--------|------| |
| 78 | +| `log_path` | str | 必填 | 日志文件路径 | |
| 79 | +| `plot_type` | str | `"pid"` | `"pid"` / `"fft"` / `"filter"` | |
| 80 | +| `platform` | str | `"auto"` | 平台覆写 | |
| 81 | +| `axis` | str | `"all"` | 仅 PID 有效:`"roll"` / `"pitch"` / `"yaw"` / `"all"` | |
| 82 | +| `theme` | str | `"light"` | `"light"` / `"dark"` | |
| 83 | + |
| 84 | +**返回示例:** |
| 85 | + |
| 86 | +```json |
| 87 | +{ |
| 88 | + "image_base64": "data:image/png;base64,iVBORw0KGgo...", |
| 89 | + "plot_type": "pid", |
| 90 | + "axes_plotted": ["roll", "pitch", "yaw"], |
| 91 | + "platform": "ArduPilot", |
| 92 | + "log_file": "flight.bin", |
| 93 | + "format": "png" |
| 94 | +} |
| 95 | +``` |
| 96 | + |
| 97 | +**三种图表:** |
| 98 | + |
| 99 | +| plot_type | 图表内容 | 对应 CLI | |
| 100 | +|-----------|----------|----------| |
| 101 | +| `pid` | 阶跃响应曲线(每轴子图),标注 rise time / overshoot / settling time,10%/90% 参考线 | `stune pid --visual` | |
| 102 | +| `fft` | FFT 频谱图,连续频谱曲线或峰值柱状图,标注峰值频率/噪声底 | `stune fft --visual` | |
| 103 | +| `filter` | Bode 图(幅度+相位双面板),-3dB 参考线,±45° 相位区 | `stune filter --visual` | |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## 4. Services 层变更 |
6 | 108 |
|
7 | | -### Added |
8 | | -* Added a dedicated `skill-mcp/` package for read-only MCP-connected agents that must not use shell, `exec`, or the `stune` CLI. |
9 | | -* Documented MCP-only agent workflow, supported log extensions, tool selection, and safety boundaries for customer-support deployments. |
| 109 | +### 4.1 `analysis.py` — 新增 6 个公开函数 |
| 110 | + |
| 111 | +| 函数 | 对应 CLI | 核心逻辑 | |
| 112 | +|------|----------|----------| |
| 113 | +| `analyze_pid()` | `stune pid` | PIDReviewer → serialize_pid_result | |
| 114 | +| `analyze_fft()` | `stune fft` | FFTAnalyzer → serialize_fft_result | |
| 115 | +| `analyze_magfit()` | `stune magfit` | MAGFit → serialize_magfit_result | |
| 116 | +| `analyze_sysid()` | `stune sysid` | SysIDAnalyzer → serialize_sysid_results | |
| 117 | +| `analyze_filter()` | `stune filter` | 平台专属 filter_transfer 模块,auto/manual 双模式 | |
| 118 | +| `analyze_hardware()` | `stune hardware` | 平台专属 hardware_report 模块 | |
| 119 | + |
| 120 | +### 4.2 关键 Bug 修复 |
| 121 | + |
| 122 | +**Hardware import 路径错误:** |
| 123 | + |
| 124 | +```python |
| 125 | +# 旧版(错误) |
| 126 | +from smarttune.analyzers.hardware_report import generate_hardware_report |
| 127 | + |
| 128 | +# 新版(与 CLI 一致) |
| 129 | +mod = importlib.import_module(f"smarttune.platform.{adapter.name}.hardware_report") |
| 130 | +mod.generate_hardware_report(fd.params, flight_data=fd) |
| 131 | +``` |
| 132 | + |
| 133 | +旧版使用通用路径,而实际上 ArduPilot / Betaflight / PX4 各有独立的 hardware_report 实现。 |
| 134 | + |
| 135 | +### 4.3 `serialize.py` — 新增 3 个序列化器 |
| 136 | + |
| 137 | +| 函数 | 输入 | 处理 | |
| 138 | +|------|------|------| |
| 139 | +| `serialize_sysid_results()` | `Dict[str, SysIDResult]` | 调用 `SysIDResult.to_dict()`,封装为 axes 结构 | |
| 140 | +| `serialize_filter_result()` | Bode 原始数据 | 压缩为关键频率点格式(不含原始数组) | |
| 141 | +| `serialize_extra_analyzers_results()` | 平台 extra_analyzers 输出 | 通用 dict 处理 | |
| 142 | + |
| 143 | +### 4.4 `plot.py` — 新模块 |
| 144 | + |
| 145 | +纯函数式设计,不依赖任何 MCP / CLI 代码: |
| 146 | + |
| 147 | +| 函数 | 功能 | |
| 148 | +|------|------| |
| 149 | +| `generate_pid_plot(pid_result, theme)` | 接受 PIDAnalysisResult 或序列化 dict → base64 PNG | |
| 150 | +| `generate_fft_plot(fft_result, spectrum_data, theme)` | 接受 FFT 结果 + 可选完整频谱 → base64 PNG | |
| 151 | +| `generate_filter_bode_plot(filter_result, theme)` | 接受含 `bode_data` 的 filter 结果 → base64 PNG | |
| 152 | +| `generate_plot(log_path, plot_type, ...)` | 高层调度:解析 → 分析 → 绘图,一步到位 | |
| 153 | + |
| 154 | +`analyze_filter()` 新增内部参数 `_include_bode_data=True`(不暴露给 MCP),启用时在返回值中附带完整频率/幅度/相位数组供绘图使用。 |
10 | 155 |
|
11 | 156 | --- |
12 | 157 |
|
13 | | -## [2.3.0] — 2026-05-19 |
| 158 | +## 5. MCP 架构改进 |
| 159 | + |
| 160 | +### 5.1 `_call_service()` 统一封装 |
| 161 | + |
| 162 | +所有 tool(除 list_platforms 和 analyze_log)均通过 `_call_service(func, log_path, **kwargs)` 调用: |
| 163 | + |
| 164 | +1. 路径验证 → PathValidationError → JSON error |
| 165 | +2. 调用业务函数 |
| 166 | +3. SmartTuneError → 结构化 JSON error(含 code + hint) |
| 167 | +4. 未知异常 → logger.exception + JSON error |
14 | 168 |
|
15 | | -### Added |
16 | | -- **Read-only MCP server** — `smarttune-mcp` exposes SmartTune analysis to OpenClaw and other MCP clients without shell access. |
17 | | -- `smarttune_list_platforms` MCP tool — reports CLI-supported extensions and MCP-accepted extensions separately. |
18 | | -- `smarttune_log_quality` MCP tool — returns structured log quality, data availability, and validation metadata. |
19 | | -- `smarttune_analyze_log` MCP tool — returns compact JSON or Markdown analysis for PID, FFT, MagFit, and hardware modules. |
20 | | -- Pure service layer under `smarttune/services/` for analysis and JSON-safe serialization. |
21 | | -- MCP security tests covering extension allowlists, path traversal, symlink escape, and file size limits. |
| 169 | +消除了旧版各 tool 各自处理异常的重复代码。 |
22 | 170 |
|
23 | | -### Security |
24 | | -- MCP path validation resolves symlinks with `resolve(strict=True)`, enforces allowed roots, and rejects arbitrary file extensions. |
25 | | -- MCP tools do not expose subprocess, shell execution, arbitrary output paths, parameter writes, or filesystem mutation. |
26 | | -- Betaflight `.txt` logs remain CLI-supported but are intentionally excluded from the MCP allowlist. |
| 171 | +### 5.2 Tool Annotations |
27 | 172 |
|
28 | | -### Fixed |
29 | | -- Fixed `smarttune/analyzers/magfit.py` indentation so MagFit imports cleanly. |
30 | | -- Hardware analysis service now uses the existing `generate_hardware_report()` function path. |
31 | | -- Runtime `SMARTTUNE_MCP_MAX_FILE_MB` changes are respected during path validation. |
| 173 | +所有 tool 共享 `_READ_ONLY_ANNOTATIONS`: |
| 174 | + |
| 175 | +```python |
| 176 | +{ |
| 177 | + "readOnlyHint": True, |
| 178 | + "destructiveHint": False, |
| 179 | + "idempotentHint": True, |
| 180 | + "openWorldHint": False, |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +### 5.3 输入校验 |
| 185 | + |
| 186 | +所有 tool 在调用 service 前校验: |
| 187 | + |
| 188 | +- `axis` ∈ {`all`, `roll`, `pitch`, `yaw`} |
| 189 | +- `response_format` ∈ {`json`, `markdown`} |
| 190 | +- `include_modules` ⊆ {`pid`, `fft`, `magfit`, `hardware`, `filter`, `sysid`} |
| 191 | +- `plot_type` ∈ {`pid`, `fft`, `filter`} |
| 192 | +- `na`, `nb` clamp 到 [1, 10] |
| 193 | +- `max_recommendations` clamp 到 [1, 100] |
32 | 194 |
|
33 | 195 | --- |
34 | 196 |
|
35 | | -## [2.0.0] — 2026-05-03 |
36 | | - |
37 | | -### Added |
38 | | -- **Multi-platform architecture** — Unified `FlightData` intermediate representation |
39 | | -- **Platform Adapter Layer** — `PlatformAdapter` ABC + auto-detection + registry |
40 | | -- **Betaflight support** — Pure Python BBL parser (950 lines), FF/RPM/D-term noise analyzers |
41 | | -- **ParamRef system** — Generic parameter names → platform-native mapping |
42 | | -- **6-layer Knowledge Base** — common → platform → user common → user platform → Pro common → Pro platform |
43 | | -- **Error code system** — E10xx (file) / E20xx (parse) / E30xx (data) / E40xx (input) / E50xx (analysis) |
44 | | -- `stune platforms` command — list available adapters |
45 | | -- `stune filter --auto` — auto-derive filters from params |
46 | | -- Betaflight-specific analyzers: `FeedforwardAnalyzer`, `RPMFilterAnalyzer`, `DTermNoiseAnalyzer` |
47 | | - |
48 | | -### Changed |
49 | | -- **CLI renamed** — `ap-tune` → `stune` |
50 | | -- **Package renamed** — `ap_tune` → `smarttune` |
51 | | -- **Architecture restructured** — flat module layout → layered (platform/analyzers/knowledge/output/models) |
52 | | -- Knowledge loader now accepts `platform` parameter for platform-specific rules |
53 | | -- Pro knowledge base renamed and restructured: `ardupilot-knowledge-pro` → `smarttune-knowledge-pro` v0.2.0 |
54 | | - |
55 | | -### Removed |
56 | | -- `--vision` option (MiniMax CLI integration not included in open-source version) |
57 | | -- `output/` directory with cached analysis images from old repo |
| 197 | +## 6. 平台能力矩阵 |
| 198 | + |
| 199 | +各 MCP tool 自动检查平台 `capabilities()` 后再执行: |
| 200 | + |
| 201 | +| 能力 | ArduPilot | Betaflight | PX4 | |
| 202 | +|------|-----------|------------|-----| |
| 203 | +| pid | ✅ | ✅ | ✅ | |
| 204 | +| fft | ✅ | ✅ | ✅ | |
| 205 | +| magfit | ✅ | ❌ | ❌ | |
| 206 | +| sysid | ✅ | ❌ | ❌ | |
| 207 | +| filter | ✅ | ✅ | ✅ | |
| 208 | +| hardware | ✅ | ✅ | ✅ | |
| 209 | +| quality | ✅ | ✅ | ✅ | |
| 210 | + |
| 211 | +不支持的 tool 返回结构化 error(含 code 和 hint),不会 crash。 |
58 | 212 |
|
59 | 213 | --- |
60 | 214 |
|
61 | | -## [1.0.0] — 2026-04-29 |
| 215 | +## 7. Agent 推荐工作流 |
| 216 | + |
| 217 | +``` |
| 218 | +1. smarttune_list_platforms |
| 219 | + → 确认日志格式是否支持 |
62 | 220 |
|
63 | | -### Added |
64 | | -- Full ArduPilot WebTools algorithm alignment (PIDReview, FilterReview, HardwareReport, MAGFit) |
65 | | -- WMM 2020 geomagnetic model (19×37 grid + bilinear interpolation) |
66 | | -- SysID module (ARX system identification) |
67 | | -- Filter analysis (Bode plot, multi-notch, harmonic notch) |
68 | | -- Hardware report (IMU, compass, barometer, GPS, battery) |
69 | | -- Layered knowledge base (builtin → user) |
70 | | -- 309 tests, 0 xfail |
| 221 | +2. smarttune_log_quality(log_path) |
| 222 | + → 评估数据质量(0-100 分),决定是否继续 |
71 | 223 |
|
72 | | -### Changed |
73 | | -- Open-source restructuring: knowledge in `rules/` subdirectory, user loading from `~/.ap-tune/knowledge/` |
| 224 | +3. smarttune_analyze_log(log_path, response_format="markdown") |
| 225 | + → 综合分析,给用户完整报告 |
| 226 | +
|
| 227 | +4. smarttune_generate_plot(log_path, plot_type="pid") |
| 228 | + → 阶跃响应图表,辅助解释 PID 调参建议 |
| 229 | +
|
| 230 | +5. 按需单独调用: |
| 231 | + smarttune_analyze_sysid(log_path, na=3, nb=2) |
| 232 | + smarttune_analyze_filter(log_path) |
| 233 | +``` |
74 | 234 |
|
75 | 235 | --- |
76 | 236 |
|
77 | | -## [0.1.0-beta] — 2026-04-07 |
| 237 | +## 8. 2GB 服务器注意事项 |
| 238 | + |
| 239 | +- `generate_plot` 每次调用会加载 matplotlib + 解析日志 + 绘图,峰值内存约 200-400MB |
| 240 | +- 建议不要在一次对话中连续调用多种 plot_type(pid + fft + filter),可以按需分步 |
| 241 | +- matplotlib 使用 `Agg` backend,不需要 X11 / display server |
| 242 | +- 如果 matplotlib 未安装,`generate_plot` 返回 ImportError 而非 crash |
| 243 | + |
| 244 | +--- |
| 245 | + |
| 246 | +## 9. 未涉及项 |
| 247 | + |
| 248 | +以下问题在本次升级范围外,记录备查: |
78 | 249 |
|
79 | | -### Added |
80 | | -- Initial release: PID reviewer, FFT analyzer, MagFit, log parser |
81 | | -- Built-in knowledge base (pid_rules, filter_rules, magfit_rules) |
82 | | -- 7 CLI commands: analyze, pid, fft, filter, sysid, hardware, magfit |
83 | | -- 159 tests |
| 250 | +| 项目 | 说明 | |
| 251 | +|------|------| |
| 252 | +| Serialize 层脆弱性 | dict vs dataclass 格式不统一,serialize 函数需要同时处理两种格式 | |
| 253 | +| Betaflight .bbl 数据缺失 | motor/battery/PID 参数在 .bbl 格式中经常缺失,quality 评分会偏低 | |
| 254 | +| MCP vs Plugin 架构 | OpenClaw 实际使用 native plugin 而非 MCP 协议,两套接口需长期维护 | |
| 255 | +| pyproject.toml | 未更新 MCP tool 文档 | |
| 256 | +| README.md | 未更新 tool 列表(旧版仅列 3 个) | |
0 commit comments