Skip to main content
Glama
mp911de

siglent-scpi-mcp

by mp911de

Siglent SCPI MCP Server

siglent-scpi-mcp connects Siglent oscilloscopes and power supplies using SCPI over TCP to clients that support the Model Context Protocol.

The server provides typed tools for supported instruments, validates tool inputs before writing to the instrument, and reports the SCPI commands applied by each mutating call. Structured logs and OpenTelemetry observability are built in.

IMPORTANT

One bench session has run against an SDS1204X HD and an SPD3303X-E. It confirmed the waveform scaling chain end to end and a handful of round trips, and it found firmware behaviour the guides do not document.

NOTE

At the risk of stating the obvious: Giving AI access to real-world machines that interact with electricity might lead to various outcomes. Use this tooling with appropriate caution and make sure to familiarize yourself with thesecurity model built into the MCP server.

Supported instruments

The table describes the built-in model routing. It does not mean that each model has been tested on hardware.

Instrument family

Models supported by the built-in inventory

Command set

SDS1000X-E

SDS1xxxX-E

Legacy PG01-E02C

SDS1000X-C

SDS1xxxX-C

Legacy PG01-E02C using the X-E chapter as an unverified match

SDS1000X

SDS1xxxX and SDS1xxxX+

Legacy PG01-E02C

SDS2000X

SDS2xxx and SDS2xxxX

Legacy PG01-E02C

SDS1000 non-SPO

SDS1xxxCFL, A, CML+, CNL+, DL+, E+, and F+

Legacy PG01-E02C

SDS X HD

SDS models ending in X HD, including SDS800X HD and the SDS1000X, SDS2000X, and SDS3000X HD families

EN11F SCPI

SDS X Plus

SDS models ending in X Plus, including SDS2000X Plus

EN11F SCPI

SDS5000X, SDS6000, and SDS7000

Model strings beginning with SDS5xxx, SDS6xxx, or SDS7xxx

EN11F SCPI

SHS800X and SHS1000X

SHS8xxX and SHS1xxxX

EN11F SCPI

SPD1000X

SPD1168X and SPD1305X

SPD1000X command set

SPD3303

SPD3303X, SPD3303X-E, and SPD3303C

SPD3303 command set

An unsupported instrument still gets the identify and status tools. Raw SCPI tools can also be enabled, but their command support is unknown and they are not exposed by default.

You can extend model recognition with an inventory file.

Related MCP server: keyscope-mcp

Requirements

  • Node.js 24 or newer

  • Network access from the server to the instrument

  • SCPI over TCP enabled on the instrument, normally on port 5025

  • An MCP client that supports Streamable HTTP

Quick start

Docker image

Run the prebuilt image published by the latest successful main build:

export SIGLENT_MCP_TOKEN="$(openssl rand -hex 32)"
echo "Token: $SIGLENT_MCP_TOKEN"
docker run --rm \
  -p 127.0.0.1:3000:3000 \
  -e SIGLENT_MCP_TOKEN \
  ghcr.io/mp911de/siglent-scpi-mcp:main \
  --listen 0.0.0.0 \
  192.168.1.50

The container requires a bearer token because it listens on a non-loopback address internally.

npm

Install the command globally from npm:

npm install --global @mp911de/siglent-scpi-mcp
siglent-scpi-mcp 192.168.1.50

To install the latest GitHub revision instead, use the repository shorthand:

npm install --global mp911de/siglent-scpi-mcp
siglent-scpi-mcp 192.168.1.50

Replace 192.168.1.50 with the instrument host or IP address. Add :<port> when the instrument does not use port 5025.

Startup connects to the instrument and reads *IDN? before it opens the MCP endpoint at:

http://127.0.0.1:3000/mcp

In another terminal, confirm that the server is running and the instrument connection is open:

curl http://127.0.0.1:3000/healthz

{"status":"ok","instrument":{"connected":true}}

Register the endpoint with an MCP client. For example, register the Docker container with its bearer token in Claude Code:

claude mcp add --transport http siglent http://127.0.0.1:3000/mcp \
  --header "Authorization: Bearer $SIGLENT_MCP_TOKEN"

For the default npm command, which binds directly to host loopback without a token, use:

claude mcp add --transport http siglent http://127.0.0.1:3000/mcp

The server must remain running while the client uses the instrument.

Configuration

Command line

Usage: siglent-scpi-mcp [options...] <host>[:port]

Option

Purpose

<host>[:port]

Instrument address. The SCPI port defaults to 5025

-l, --listen <address>

HTTP bind address. Defaults to 127.0.0.1

-p, --port <port>

HTTP port. Defaults to 3000

--path <path>

MCP endpoint path. Defaults to /mcp. Must be an absolute path other than / or /healthz, without a trailing slash

-t, --token <token>

Require a bearer token. Prefer the SIGLENT_MCP_TOKEN environment variable

--inventory <file>

Merge a JSON model inventory over the built-in table

--max-response-timeout <ms>

Longest wait for a single instrument response, 1000 to 3600000. Defaults to 180000

--enable-dangerous-commands

Expose reboot, shutdown, calibration, LAN, and raw SCPI tools

--enable-screenshots

Expose screenshot tools

--save-screenshots [format]

Also save every capture to a session directory in the working directory, as png (default) or bmp. Requires --enable-screenshots

--enable-lock

Expose tools that can lock the front panel

--unlock

Clear the front-panel remote lock on connect

--disable-commands <names>

Hide comma-separated tool names

--disable-setup-commands

Hide tools annotated as setup mutations

--disable-destructive-commands

Hide tools annotated as destructive

--log-level <level>

Set fatal, error, warn, info, debug, or trace. Defaults to info. Passing the flag switches the console to the raw JSON log stream

-v, --verbose

Log SCPI traffic as raw JSON lines without the spinner. Same as --log-level debug

-h, --help

Show command help

-V, --version

Show the version

Exit status:

  • 0 after a clean shutdown

  • 1 when startup cannot reach or identify the instrument

  • 2 for a usage error

Terminal colors are used only when stdout and stderr are terminals and NO_COLOR is not set.

Tool discovery

The selected driver determines which tools are available. Typical oscilloscope tool groups include acquisition, channels, trigger, waveform search, serial decode, mask testing, waveform, math and FFT, measurements, cursors, saved setups and stored files, system settings, screenshots, and device-specific features. The newer dialect also exposes waveform generator and handheld multimeter tools. Neither is hidden per model, because nothing in the instrument identity reports the generator option.

Security model

  • The server binds to loopback by default.

  • Loopback requests validate Host and Origin to reduce DNS rebinding risk.

  • A non-loopback bind requires bearer authentication.

  • Prefer SIGLENT_MCP_TOKEN to --token, since command lines may be visible to other users.

The health endpoint does not require authentication. It reports only server status and whether the instrument connection is open.

Safe tool exposure

The server hides destructive/dangerous tools by default:

  • reboot_scope

  • shutdown_scope

  • calibrate_scope

  • configure_lan

  • scpi_command

  • scpi_query

  • save_waveform_file

  • clear_measurements

  • capture_screenshot

  • lock_front_panel

Enable reboot, shutdown, calibration, LAN, and raw SCPI tools with:

siglent-scpi-mcp --enable-dangerous-commands 192.168.1.50

Enable screenshots separately:

siglent-scpi-mcp --enable-screenshots 192.168.1.50

Add --save-screenshots to also write every capture to disk in a session directory like 2026-09-01T1421_SDS1204X-HD/.

This can be useful to prevent LLMs from taking shortcuts.

You can narrow the exposed surface further:

siglent-scpi-mcp \
  --enable-dangerous-commands \
  --disable-commands scpi_command \
  --disable-destructive-commands \
  192.168.1.50

--disable-commands takes a comma-separated list of tool names. --disable-setup-commands hides setup mutations. --disable-destructive-commands hides destructive tools. Disable options always take precedence over enable options.

Front panel lock

A remote lock makes an instrument read as stuck to a person standing at it, so locking is opt-in and unlocking is always allowed.

  • --unlock clears the lock when the server connects.

  • --enable-lock enables locking (disabled by default).

The SDS1204X HD engages its remote lock on its own during waveform transfers, undocumented firmware behaviour observed on the bench.

Custom model inventory

--inventory <file> overlays additional model matches onto the built-in family table. A key that names a built-in family can add models without repeating the family declaration. A new key must define at least its device kind.

{
  "SDS X HD": {
    "models": ["SDS1204X HD", {"pattern": "^SDS8\\d{2}X HD"}]
  },
  "Lab supply": {
    "kind": "power-supply",
    "psu": "SPD1000X",
    "models": ["SPD1168X-CUSTOM"]
  }
}

Exact model strings take precedence over regular expression patterns. Inventory entries take precedence over the built-in table.

Observability

Traces

One tool call is one trace. Its root span is named tool <name> and carries the tool name in the mcp.tool.name attribute. Every SCPI exchange the call makes becomes a child span named scpi.query, scpi.command, or scpi.binary, carrying the line sent in the scpi.command attribute. A get_timebase call, for instance, is one root span over four scpi.query children. The connection handshake runs before any tool call, so *IDN? and CHDR OFF show up as short traces of their own at startup.

The server depends on the OpenTelemetry API alone, so every span is a no-op until a tracing SDK is registered in the process. Nothing leaves the server until you attach one.

Traces in Grafana

examples/observability holds a backend and the preload module that turns the spans on. The backend is grafana/otel-lgtm, Grafana's own single-container OpenTelemetry stack for demos and development. It publishes Grafana on port 3000, Tempo on 3200, and the OTLP HTTP endpoint on 4318.

The preload needs @opentelemetry/sdk-node, which is a development dependency of this project.

Start the backend:

docker compose -f examples/observability/compose.yaml up -d

Start the server with the preload:

OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318 \
  node --import ./examples/observability/otel.ts src/cli.ts --port 3001 192.168.1.50

Docker

Build the image:

docker build -t siglent-scpi-mcp .

Run it with the HTTP port published only on host loopback:

docker run --rm \
  -p 127.0.0.1:3000:3000 \
  -e SIGLENT_MCP_TOKEN=change-me \
  siglent-scpi-mcp \
  --listen 0.0.0.0 \
  192.168.1.50

The process must bind to 0.0.0.0 inside the container for Docker port publishing to reach it. A non-loopback bind requires a bearer token. Configure the same token in the MCP client. The container must also be able to reach the instrument on TCP port 5025.

Documentation

License

Siglent SCPI MCP Server is released under version 2.0 of the Apache License.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that enables AI assistants to control Siglent SDS oscilloscopes over a local network using SCPI commands. It allows users to measure signals, configure channel and acquisition settings, and capture waveforms or screenshots through natural language.
    13
    4
    7
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    AI-native oscilloscope control. A pure-Python MCP service that lets LLM agents control Keysight EDUX1052G oscilloscopes via a compact DSL.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    An MCP server that enables AI agents to operate an oscilloscope through high-level tools like signal capture and measurement, abstracting vendor-specific SCPI commands.
    18
    3
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI to control RIGOL DHO/HDO oscilloscopes and SIGLENT SDG1000X signal generators via SCPI commands through a local stdio MCP server.
    1
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mp911de/siglent-scpi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server