Skip to main content
Glama
andy-qingcai

MHO98 MCP Server

by andy-qingcai
README.md
# MHO98 MCP Server

Rigol **MHO98** 示波器的 Model Context Protocol (MCP) 服务器。
基于官方《MHO98 Programming Guide》(PGA45102-1110) 做全量参数化封装,
通过 **PyVISA (raw TCP socket 5555 / USBTMC)** 控制仪器。

- 手册摘要:`docs/NOTES.md`;功能规划:`docs/PLAN.md`;手册原文:`docs/MHO98_ProgrammingGuide_EN.pdf`
- **默认暴露 18 个工具(动作/配置三层结构)**(`MHO98_TOOL_PROFILE=full` 可全量暴露 142 个);手册全部 28 个命令子系统逐命令核对覆盖——**改状态走 `configure(scope, target, params)`,查状态走 `get_config(subsystem, target, full)`,其余是动词**(run/autoscale/measure/capture/screenshot/save/navigate)
- **波形数据只落盘**(CSV/NPY),绝不在 MCP 返回值中内联采样数组,防止撑爆大模型上下文;返回值为统计摘要 + 文件路径,供后续脚本按协议解析

## 快速开始

```bash
cd /Users/andylos/mcp_gen/rigol/mho98
python3 -m venv .venv
.venv/bin/pip install -e .          # 或 pip install mcp'>=1.2,<2' pyvisa pyvisa-py numpy
.venv/bin/python -m pytest tests/   # 离线单元测试(mock 仪器)
.venv/bin/python scripts/probe_device.py   # 真机全功能自检
```

## 配置(环境变量)

| 变量 | 默认 | 说明 |
|---|---|---|
| `MHO98_RESOURCE` | `TCPIP0::169.254.112.67::5555::SOCKET` | VISA 资源串;USB 形如 `USB0::0x1AB3::0x****::***::INSTR` |
| `MHO98_SOURCE_IP` | 自动检测 | macOS 直连 link-local 网段时绑定本机源地址(en 口 169.254.*) |
| `MHO98_DATA_DIR` | `./data` | 波形 CSV/NPZ、截图、设置文件的保存目录 |
| `MHO98_TOOL_PROFILE` | `lean` | 工具暴露面:`lean`(18 个三层结构,省上下文)/ `full`(142 个全量);旧值 `core` 为弃用别名 |

> **macOS 直连网线注意**:仪器使用 link-local 地址(169.254.x.x)时,系统默认把流量
> 路由到主网卡导致连不上。本服务会自动发现本机 169.254.* 地址并绑定;若仍有问题,
> 可 `sudo route -host add 169.254.112.67 -interface en7` 持久修复。

## 接入 MCP 客户端

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

```json
{
  "mcpServers": {
    "mho98": {
      "command": "/Users/andylos/mcp_gen/rigol/mho98/.venv/bin/python",
      "args": ["-m", "mho98_mcp.server"],
      "cwd": "/Users/andylos/mcp_gen/rigol/mho98",
      "env": {
        "MHO98_RESOURCE": "TCPIP0::169.254.112.67::5555::SOCKET",
        "MHO98_DATA_DIR": "/Users/andylos/mcp_gen/rigol/mho98/data",
        "MHO98_TOOL_PROFILE": "lean"
      }
    }
  }
}
```

## 工具暴露面:lean(默认,18 个)/ full(142 个)

142 个工具的全量 schema 对大模型上下文负担太重。默认 **lean** profile 按
「动作 / 配置」结构轴切分,规则一句话:**改状态走 `configure`,查状态走
`get_config`,其余是动词**(`MHO98_TOOL_PROFILE=full` 切回全量暴露,功能等价)。

### ① 配置写(1 个)

```python
configure(scope, target=None, params=None, extra=None)
```

`scope` 覆盖全部 32 个配置域:channel / timebase / acquire / autoset / display /
trigger / trigger_common / bus / math / reference / awg / awg_modulation /
awg_output / bode / thresholds / statistics / cursor / counter / dvm / measure /
histogram / mask / search / navigate / record / la / system / lan / save / smb /
ieee4888 / datetime。`target` 是二级选择器(触发类型、`"1/CAN"` 式总线+协议、
通道/槽位号、measure 小节名)。示例:

```python
configure("channel", "1", {"scale": 0.05, "coupling": "AC", "probe": 10})
configure("trigger", "CAN",  {"baud": 500000, "when": "ID"})
configure("bus", "1/SPI",    {"sclk": "CH1", "miso": "CH2"})
configure("awg", "1",        {"function": "SINusoid", "frequency": 10e3})
configure("awg_output", "1", {"state": True, "sync_phase": True})
```

`params` 的键按底层包装函数的签名校验:拼错键名报 ValueError 并**列出全部
合法键**——错误信息即完整参数文档。

### ② 配置读(1 个)

`get_config(subsystem, target, full)` ——32 个子系统读回合一(通道/时基/任意
触发类型/总线/数学/AWG/录制/LA/LAN/SMB/IEEE488.2/选件等;选件查询带挂死守卫,
默认跳过)。

### ③ 动作(16 个)

| 类别 | 工具 |
|---|---|
| 会话/状态 | `connect` `disconnect` `list_resources` `get_idn` `get_status` `reset` `wait_complete` `scpi`(任意 SCPI 逃生舱) |
| 采集动作 | `run`(RUN/STOP/SINGLE/FORCE/CLEAR) `autoscale` `capture`(波形落盘 CSV/NPY+统计,绝不内联) `measure`(44 项,单项/批量/统计值) `screenshot` |
| 存储/导航 | `save_on_instrument(kind, path)` `load_on_instrument(kind, path)` `navigate_to_event` |

长尾/组合参数仍可通过 `configure(..., extra={"KEYWORD": value})` 白名单透传到
`:子系统:KEYWORD value`(白名单按手册逐命令核对,非法关键字报 ValueError)。

## 已验证固件特性(00.01.00,实机 MHO9A274501356)

- `:SYSTem:OPTion:STATus?` / `:OPTion:VALid?` 会挂死(不响应),`get_system_info` 已跳过;`get_option_status` 默认跳过,仅 `opt_in=True` 才真正查询
- `:DVM:CURRent?` 在 DVM 关闭时挂死,`read_dvm` 已做使能守卫
- `:CURSor:MANual:TYPE` 合法值为 `TIME|AMPLitude`(非 X/Y)
- `:TRIGger:PATTern:PATTern` 需要 `H,H,L,L` 逗号分隔(工具自动转换 `HHLL`)
- `:DISPlay:GRADing:TIME` 只接受 `MIN|数值秒|INFinite`(不接受 `1S`/`1.0`)
- `:NAVigate:MODE` 需要 STOP 状态(`configure_navigate(stop_first=True)`)
- SCPI 错误入队有延迟,写后错误检查带 50 ms 稳定期防止误归属

## 手册逐条核对带来的修正(v0.1 → v0.2)

- `:CHANnel<n>:POSition` 是偏置电压(V)而非垂直格数
- 测量阈值命令为 `:MEASure:SETup:MAX/MID/MIN`(非 `:MEASure:THReshold:*`);统计查询必带类型参数 `:MEASure:STATistic:ITEM? <type>,<item>`
- PATTern/DURation 触发的 `LEVel` 需 `<源>,<电平>` 二元形式;`holdoff` 下限 8 ns
- 此型号无 `:MATH<n>:DATA?`,数学波形经 `:WAVeform:SOURce MATH<n>` 读取;REF 插槽为 1–10;FFT 窗函数集为 {RECTangle|BLACkman|HANNing|HAMMing|FLATtop|TRIangle}
- AWG 调制仅支持 AM/FM/PM(无 SWP/Burst);AM 深度 0–120%;频率 2 mHz–100 MHz
- Bode:`sweep_type` 合法值 `LOG|LINE`;`:BODeplot:VOLTage` 需 `<量程>,<幅值>` 双参数
- LA 阈值按 POD 组设置(POD1=D0–D7,POD2=D8–D15),非逐通道
- 录制帧间隔命令为 `:RECord:WRECord:FINTerval`(非 INTerval);搜索类型仅 EDGE|PULSe
- `power_on` 合法值 `LATest`;语言设置用 13 种长格式
- `:SAVE:IMAGe:DATA?` 截图与 `:SAVE:*`/`:LOAD:*` U 盘路径、SMB 共享均已封装

## 数据文件格式

- 波形 CSV:两行 `#` 注释头(含 preamble 换算参数)+ `t_s,v_V` 两列
- 波形 NPY:`np.load(f)["t_s"]` / `["v_V"]`(npz,RAW 大采集推荐)
- 电压换算:`v = (code - yorigin - yreference) × yincrement`

TDQS

C2.7/5.0

Scored across 142 tools

Disambiguation2/5

There are many overlapping families: get_channel vs get_channel_full, get_timebase vs get_timebase_full, get_math_config vs get_math_config_full, configure_bus vs configure_bus_rs232/iic/spi/etc., set_counter vs set_measure_counter, and multiple screenshot/save-image tools. Descriptions often clarify differences, but the set has several tool pairs whose boundaries an agent could easily misselect among.

Naming Consistency4/5

Mostly consistent snake_case verb_noun naming (get_, set_, configure_, measure_, save_, load_, read_) is used throughout. Minor deviations exist, such as bare verbs reset/autoscale, noun-like scpi, and get_screenshot vs get_screenshot_data, but the overall convention is readable and predictable.

Tool Count1/5

142 tools is an extreme mismatch for an MCP server, far beyond the typical 3-15 range. The surface is effectively a full SCPI wrapper, creating excessive cognitive load and making tool selection impractical for an agent despite the exhaustive coverage.

Completeness5/5

The server covers nearly every major oscilloscope subsystem: system, LAN, save/load, triggers, channels, timebase, acquisition, measurements, cursors, counter/DVM, waveform, math, reference, bus decode, AWG, Bode, display, histogram, mask, search, record, logic analyzer, and connection management. The scpi escape hatch also prevents dead ends for undocumented or unexposed operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues