Skip to main content
Glama
shaag7967

mcp-server-siglent-sdm3045x

by shaag7967
README.md
# mcp-server-siglent-sdm3045x

An [MCP](https://modelcontextprotocol.io) server that lets AI assistants take measurements with a
**Siglent SDM3045X** bench multimeter connected via USB or LAN.

> Unofficial project, not affiliated with or endorsed by Siglent.
> Tested with an SDM3045X, firmware 5.02.01.10, over USB (Linux) and LAN.

## Tools

| Tool | Description |
|---|---|
| `read` | One reading with the function and range set on the instrument, without changing them |
| `measure` | Select a function (DC/AC voltage and current, 2/4-wire resistance, capacitance, frequency, period, continuity, diode, temperature) and take one reading |
| `sample` | Timestamped readings over a period (max 600 s, interval ≥ 0.1 s) with min/max/mean/stdev |
| `burst` | Up to 10000 readings as fast as the instrument can (about 180/s at speed fast), with statistics |
| `get_device_info` | Model, serial number, firmware, connection and the present measurement configuration |

Every reading comes with its unit, the range used and, where the data sheet gives a single
figure, its accuracy (e.g. `±(0.06 % of reading + 8 counts)` as an absolute value). Overloads
are reported as `"overload": true` instead of the instrument's 9.9E37.

With `--allow-scpi` one more tool is available:

| Tool | Description |
|---|---|
| `scpi` | Send any SCPI command or query from the Remote Manual (statistics, limits, null, …) |

The raw SCPI tool is off by default because it can change any setting, including the LAN
configuration.

## Requirements

- Python ≥ 3.10 and [uv](https://docs.astral.sh/uv/)
- The instrument connected to the USB device port on the rear, or to the network.
- **Linux, USB:** the kernel `usbtmc` driver makes the instrument available as `/dev/usbtmc0`.
  Give logged-in users access with a udev rule:

  ```bash
  echo 'SUBSYSTEM=="usbmisc", KERNEL=="usbtmc[0-9]*", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/70-usbtmc.rules
  sudo udevadm control --reload && sudo udevadm trigger
  ```

- **Windows / macOS, USB:** install a VISA (NI-VISA or Keysight IO Libraries) and start the
  server with `--visa-backend @ivi`.
- **LAN:** no extra software. The instrument needs an address in your subnet; then the server
  finds it by itself. On the instrument open *Utility → I/O Config → LAN Settings* and turn on
  DHCP, or enter a static IP address, subnet mask and gateway under *Modify Settings* (User
  Manual, section *I/O Configuration*, available on the
  [Siglent product page](https://int.siglent.com/products-annex/sdm3045/)). Check that the
  instrument's subnet matches your network: ours came with the static address 10.11.13.220,
  which the broadcast search does not reach. While USB is connected,
  `SYST:COMM:LAN:IPAD?` (e.g. with the `scpi` tool) shows the address in use.

## Configuration

### Claude Code

```bash
claude mcp add siglent-sdm3045x -- uvx mcp-server-siglent-sdm3045x
# fixed address instead of auto-detection:
claude mcp add siglent-sdm3045x -- uvx mcp-server-siglent-sdm3045x --resource 192.168.1.50
```

### Claude Desktop and other clients

```json
{
  "mcpServers": {
    "siglent-sdm3045x": {
      "command": "uvx",
      "args": ["mcp-server-siglent-sdm3045x"]
    }
  }
}
```

### Options

| Option | Environment variable | Default |
|---|---|---|
| `--resource RESOURCE` | `SDM_RESOURCE` | auto-detect on USB, then LAN |
| `--serial SERIAL` | `SDM_SERIAL` | any SDM3045X |
| `--allow-scpi` | `SDM_ALLOW_SCPI=1` | off |
| `--visa-backend BACKEND` | `SDM_VISA_BACKEND` | `@py` (pyvisa-py) |
| `--log-level LEVEL` | `SDM_LOG_LEVEL` | `WARNING` |

`RESOURCE` can be a device file (`/dev/usbtmc0`), an IP address or host name (VXI-11), or any
VISA resource string such as `TCPIP::192.168.1.50::5025::SOCKET` (raw socket) or
`USB0::0xF4EC::0x1203::SDM34XXXXXXXXX::INSTR`. Port 5024 is a telnet console and does not work
as a socket resource.

Auto-detection tries `/dev/usbtmc*` first, then Siglent instruments listed by VISA on USB, then
VXI-11 instruments in the local network (UDP broadcast to the portmapper, about 1 s). It accepts
the first one that identifies itself as an SDM3045X. With several instruments, `--serial` picks
one by its serial number (shown by `get_device_info`, on the rear label and under
*Utility → System Setup → System Info*). Set `--resource` instead if the instrument is in
another subnet, where the broadcast does not reach it; the two options exclude each other.

## Measurement notes

- The server cannot see how the test leads are connected. It tells the assistant to only switch
  to functions that match the wiring: currents need the red lead in the **I** jack; resistance,
  continuity, diode and capacitance drive a test current of up to 1 mA through the circuit.
- Switching function or range remotely also changes what the front panel shows.
- Once the server has sent a command, the instrument is in remote mode: the front panel shows
  "Immediate Trig" and its keys are locked. Press **Shift** to return to front panel operation.
  The instrument offers no remote command for this, so the server cannot release it by itself.
- Above 7 A, the data sheet recommends 30 s off after 30 s on.
- Accuracy figures are the one-year data sheet values (23 °C ± 5 °C, 30 min warm-up, speed slow).
  2-wire resistance adds 0.2 Ω unless the leads were nulled; AC accuracy depends on the signal
  frequency and is given per frequency band; thermocouple figures exclude the cold junction
  error (up to ±3.5 °C with the built-in sensor).

## Development

```bash
uv sync
uv run pytest                                   # tests use a simulated instrument
npx @modelcontextprotocol/inspector uv run mcp-server-siglent-sdm3045x   # try the tools interactively
```

To check a real instrument, connect it and run:

```bash
uv run python scripts/hardware_test.py                      # voltage-type functions only
uv run python scripts/hardware_test.py --with-test-current  # also resistance, current, capacitance, …
uv run python scripts/hardware_test.py --reconnect          # also unplug/replug USB when asked
```

The basic checks only use functions that put no current into the inputs. Observed instrument
behaviour, including where it differs from the Remote Manual, is described in
[docs/protocol.md](https://github.com/shaag7967/mcp-server-siglent-sdm3045x/blob/main/docs/protocol.md).

## License

MIT

<!-- mcp-name: io.github.shaag7967/mcp-server-siglent-sdm3045x -->

TDQS

A3.9/5.0

Scored across 5 tools

Disambiguation4/5

The tools are mostly distinct, but read vs. measure both return a single reading, and sample vs. burst both return statistics plus multiple readings. The detailed descriptions clarify the differences (preserve settings vs. change function; computer-paced timed sampling vs. instrument-paced count-based burst), so confusion should be limited.

Naming Consistency4/5

All names use consistent lower_snake_case, with readable action-oriented terms. Most are single verbs (read, measure, sample, burst), while get_device_info uses a verb_noun form, which is a minor deviation from the otherwise uniform pattern.

Tool Count5/5

Five tools is well-scoped for a multimeter server: single reading, configured measurement, timed sampling, fast burst acquisition, and device information. Each tool maps to a meaningful operation without unnecessary surface area.

Completeness4/5

The core measurement lifecycle is covered: current-settings reading, function/range selection, timed acquisition, fast burst acquisition, and device/configuration inspection. Minor gaps exist for advanced instrument features such as zero/relative, limit testing, or explicit configuration without immediately taking a reading, but standard workflows are supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues