Skip to main content
Glama
uni-t-uts-mcp

uni-t-uts-mcp

by Reid-n0rc

uni-t-uts-mcp

codecov

A Model Context Protocol (MCP) server for controlling UNI-T UTS series spectrum analyzers (UTS1000B/T, UTS3000B) over SCPI.

Status: under active development. The tools below work and are verified on a UNI-T UTS3036B (firmware V1.04.0040) over LAN; see docs/verified-hardware.md. Progress is tracked in the roadmap issue. See Install for setup.

Front panel: while the server is talking to the analyzer it is in remote mode and its touch screen and buttons are locked. Press Esc on the analyzer to return it to local mode (:SYSTem:LOCK 0, VXI-11 unlock and a simulated :KEY:ESC do not work on the tested firmware). See docs/verified-hardware.md.

Tools available

Group

Tools

Connection

connect (host: "auto" finds the analyzer), discover_instruments, disconnect, identify

Raw SCPI

scpi_query, scpi_command (with a confirm-required safety denylist)

Frequency

get_frequency, set_frequency

Amplitude

get_amplitude, set_amplitude

Bandwidth, sweep, detector

get_bandwidth, set_bandwidth, get_sweep, set_sweep, get_detector, set_detector

Acquisition

get_acquisition, set_acquisition, start_sweep, single_sweep, wait_for_sweep_complete

Trace configuration

get_trace, set_trace, restart_trace, set_trace_math

Trace data

get_trace_data

Markers

get_marker, set_marker, marker_search, marker_to_instrument, markers_all_off, get_peak_criteria, set_peak_criteria, get_marker_function, set_marker_function, get_marker_ndb, set_marker_ndb, get_frequency_counter, set_frequency_counter

Limit lines

get_limit_line, set_limit_line, delete_limit_line (no pass/fail read-back exists)

Measurements

get_measurement, configure_measurement, read_measurement, exit_measurement, measure (channel power, time-domain power, OBW, ACPR, TOI, C/N, harmonics)

Tracking generator

get_tracking_generator, set_tracking_generator (output, level, offset, reference trace, normalization; needs the option)

Measurement function module

get_instrument_module, select_instrument_module (spectrum analyzer, EMI, analog demodulation)

EMI function

get_emi_settings, set_emi_scan_table, set_emi_measurement, get_emi_limit_line, set_emi_limit_line, delete_emi_limit_line, get_emi_correction, set_emi_correction, get_emi_marker, set_emi_marker, emi_marker_search, emi_markers_all_off, get_emi_peak_criteria, set_emi_peak_criteria, emi_signal_list, get_emi_signal_list_sort, set_emi_signal_list_sort, emi_run, emi_stop (needs the option; research-stage, see tools reference)

Analog demodulation

enter_analog_demod, exit_analog_demod, get_ad_settings, set_ad_frequency, set_ad_demod_timing, set_ad_filters, set_ad_audio, get_demod_result, set_ad_display, ad_marker, ad_marker_search, get_ad_marker, ad_markers_all_off (needs the option; research-stage, see tools reference)

Screenshot

screenshot (PNG image of the screen; needs VXI-11, see tools reference)

Parameters and behavior: docs/tools-reference.md. Set UTS_IP (see Install; optionally also UTS_PORT, default 5025) to connect automatically at startup; UTS_INSTRUMENTS (name=host:port,... or JSON) adds further named analyzers that are connected at startup too, each on its own connection with its own queue and lock ; every tool takes an optional instrument argument to pick one (default: the default instrument or the only one), and list_instruments shows them. Calls to different instruments run in parallel; calls to the same instrument are queued. The default transport is auto: VXI-11 when the analyzer offers it (verified on the UTS3036B), otherwise raw SCPI over TCP; UTS_TRANSPORT=raw or vxi11 forces one (setting only UTS_PORT also means raw), and UTS_VXI11_DEVICE (default inst0) names the VXI-11 device. UTS_VXI11_PROBE_TIMEOUT_S (default 15) is the total time allowed to reach VXI-11, retries included; raise it on a slow VPN or Tailscale path. VXI-11 queues commands during a sweep instead of dropping them, lets single_sweep wait with one blocking *OPC?, and does not truncate the screenshot transfer; see the programming guide.

Parallel tool calls are safe. The instrument has a single command stream, so the server runs tool calls one at a time per instrument, first in first out: each tool's whole command sequence is atomic, results and errors are never mixed up between calls, and a long operation such as single_sweep makes other calls wait (they fail with Instrument busy after UTS_BUSY_TIMEOUT_S seconds, default 120). Details: Concurrency.

Related MCP server: econtest-bench-mcp

Project layout

Modeled on siglent-sds-mcp: TypeScript, stdio transport, vitest tests, npm and Docker publishing via tag-triggered GitHub Actions.

  • src/connection.ts – serialized SCPI queue with timeouts, *OPC?-synced commands and hold-off after unsupported queries, on top of a pluggable transport

  • src/discovery.ts, src/autoHost.ts – network discovery (portmapper UDP broadcast on each local subnet, *IDN? of the responders) behind discover_instruments and host=auto

  • src/transports/ – the Transport interface with capability flags, the raw SCPI over TCP transport (raw.ts), the VXI-11 transport (vxi11.ts) and transport selection (select.ts: UTS_TRANSPORT, UTS_VXI11_DEVICE, the auto probe)

  • src/sessionLock.ts – the FIFO exclusive-session lock behind connection.runExclusive; every tool is registered through defineTool (src/tools/util.ts), which runs it inside a session

  • src/tools/screenshot.ts – the screenshot tool (PNG via :DISPlay:DATA?, picture format restored in a finally)

  • src/blocks.ts, src/scpi.ts – binary block parser; SCPI helpers and the safety denylist

  • src/instrument.ts, src/errors.ts, src/acquisition.ts – applying settings with error-queue checks, sweep synchronization

  • src/vxi11/ – dependency-free ONC RPC/XDR client, portmapper, VXI-11 core-channel client (used by the VXI-11 transport) and the interrupt-channel listener (interrupt.ts, SRQ client; not used by any tool)

  • src/tools/ – one file per tool group, registered in src/server.ts

  • tests/ – unit and mocked integration tests, a fake SCPI server, a transport contract suite (transportContract.ts), and captured instrument fixtures

  • scripts/conformance.mjs, scripts/conformance-lib.mjs – simulator conformance: the same scripted exchange against the simulator (CI) and, on demand, a real analyzer (see docs/releasing.md)

  • mcpb/manifest.json, scripts/build-mcpb.mjs – the Claude Desktop MCP bundle (.mcpb): manifest and the Node-only build script (npm run build:mcpb)

  • scripts/client-snippets.mjs – single source for the per-client configs and links (README table, wiki page, site section); npm run clients:sync regenerates them

  • scripts/client-config.mjs – the npm run client-config printer; also the single place that holds the install specs and the NPM_PUBLISHED switch

  • scripts/sync-wiki.mjs – builds the wiki page set from the docs (see Wiki); docs/wiki/ holds the hand-written wiki pages

  • docs/ – manual-testing-guide.md, tools-reference.md, verified-hardware.md, programming-guide.md, references.md

Install

Everything in this section works today (v1.1.0, also on npm). You need Node.js 22 or newer (or Docker). Use your analyzer's address in place of 192.168.1.100.

UTS_IP is optional. Set it to auto (or ask the assistant to connect with host auto) to find the analyzer on your local subnet without knowing its address; this works when exactly one analyzer answers and is unauthenticated, so check the model and address it reports. If you leave it out, tell the assistant "connect to the analyzer at 192.168.1.100" and it will use the connect tool.

Add to your client

Client

How

One-click

Claude Code

terminal, or .mcp.json in a project

-

Claude Desktop

download the .mcpb, or claude_desktop_config.json

Download the .mcpb (GitHub releases)

Cursor

install link, or ~/.cursor/mcp.json / .cursor/mcp.json

Add to Cursor

VS Code

.vscode/mcp.json, or code --add-mcp

-

Windsurf

mcp_config.json (Cascade > Open MCP config file)

-

Other stdio clients

any client that launches an MCP server over stdio

-

Copy-paste configs for each client, and what has and has not been verified, are on the Add to Client wiki page and the project site.

More detail follows per client.

Claude Code

Easiest: the Claude Code plugin (this repository is also a plugin marketplace). Inside Claude Code:

/plugin marketplace add Reid-n0rc/uni-t-uts-mcp
/plugin install uni-t-uts@uni-t-uts-mcp

or from a shell: claude plugin marketplace add Reid-n0rc/uni-t-uts-mcp and claude plugin install uni-t-uts@uni-t-uts-mcp. The plugin runs npx -y uni-t-uts-mcp pinned to this release (1.1.0) and asks for the analyzer address, port and transport (all optional; change them later in /plugin). The server's tools then appear under the plugin. On Windows, where npx is a .cmd file, use the manual claude mcp add ... cmd /c npx commands below if the plugin's server does not start. Plugin and marketplace formats follow https://code.claude.com/docs/en/plugins-reference and https://code.claude.com/docs/en/plugins/marketplace-reference.md; the plugin files are generated by npm run clients:sync.

Or register the server by hand; pick one, each registers the server under the name uni-t-uts.

# From the npm registry (shortest; npx downloads and runs it)
claude mcp add uni-t-uts -e UTS_IP=192.168.1.100 -- npx -y uni-t-uts-mcp

# From the release tarball (same files as npm, fetched from GitHub: no build step, no install scripts)
claude mcp add uni-t-uts -e UTS_IP=192.168.1.100 -- npx -y https://github.com/Reid-n0rc/uni-t-uts-mcp/releases/download/v1.1.0/uni-t-uts-mcp-1.1.0.tgz

# From the git tag (npm clones the repository and builds it; needs git)
claude mcp add uni-t-uts -e UTS_IP=192.168.1.100 -- npx -y github:Reid-n0rc/uni-t-uts-mcp#v1.1.0

# Docker (Linux image, amd64 and arm64)
claude mcp add uni-t-uts -- docker run -i --rm -e UTS_IP=192.168.1.100 ghcr.io/reid-n0rc/uni-t-uts-mcp:1.1.0

On Windows, where npx is a .cmd file that clients cannot launch directly, put cmd /c in front of it:

claude mcp add uni-t-uts -e UTS_IP=192.168.1.100 -- cmd /c npx -y uni-t-uts-mcp

# or from the release tarball
claude mcp add uni-t-uts -e UTS_IP=192.168.1.100 -- cmd /c npx -y https://github.com/Reid-n0rc/uni-t-uts-mcp/releases/download/v1.1.0/uni-t-uts-mcp-1.1.0.tgz

Claude Desktop: download the .mcpb and double-click

The bundle uni-t-uts-mcp-1.1.0.mcpb (an MCP bundle, the Claude Desktop extension format) is attached to the v1.1.0 GitHub release. You can also build the file yourself (npm ci && npm run build && npm run build:mcpb, which writes dist/uni-t-uts-mcp-<version>.mcpb). Installing it in Claude Desktop itself has not been verified yet.

  1. Download the .mcpb file.

  2. Double-click it (or drag it onto Claude Desktop, or use Settings > Extensions > Advanced settings > Install Extension).

  3. In the install dialog fill in the settings, then install:

    • Analyzer address (optional): the analyzer's address, for example 192.168.1.100. Leave it empty and tell the assistant "connect to the analyzer at 192.168.1.100" instead.

    • Port: 5025 (raw SCPI); change it only if your analyzer differs.

    • Transport: raw (default), vxi11 or auto.

The bundle contains the compiled server and its dependencies and uses the Node.js that comes with Claude Desktop, so nothing else needs installing (it needs Node 22 or newer). It is not code-signed, so Claude Desktop shows its usual unverified-extension notice. The bundle is built and checked in CI and started over stdio from an unpacked copy, but installing it in Claude Desktop itself has not been verified yet (issue #86 tracks the manual check).

Claude Desktop (JSON), Cursor, VS Code and other clients

Add this mcpServers entry to the client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: ~/.cursor/mcp.json; VS Code-style clients use the same entry, some under a servers key instead of mcpServers).

macOS / Linux:

{ "mcpServers": { "uni-t-uts": { "command": "npx", "args": ["-y", "uni-t-uts-mcp"], "env": { "UTS_IP": "192.168.1.100" } } } }

Or from the release tarball:

{ "mcpServers": { "uni-t-uts": { "command": "npx", "args": ["-y", "https://github.com/Reid-n0rc/uni-t-uts-mcp/releases/download/v1.1.0/uni-t-uts-mcp-1.1.0.tgz"], "env": { "UTS_IP": "192.168.1.100" } } } }

Windows:

{ "mcpServers": { "uni-t-uts": { "command": "cmd", "args": ["/c", "npx", "-y", "uni-t-uts-mcp"], "env": { "UTS_IP": "192.168.1.100" } } } }

Or from the release tarball:

{ "mcpServers": { "uni-t-uts": { "command": "cmd", "args": ["/c", "npx", "-y", "https://github.com/Reid-n0rc/uni-t-uts-mcp/releases/download/v1.1.0/uni-t-uts-mcp-1.1.0.tgz"], "env": { "UTS_IP": "192.168.1.100" } } } }

Docker (any OS with Docker):

{ "mcpServers": { "uni-t-uts": { "command": "docker", "args": ["run", "-i", "--rm", "-e", "UTS_IP=192.168.1.100", "ghcr.io/reid-n0rc/uni-t-uts-mcp:1.1.0"] } } }

The github: spec works in the same place as the package name or tarball URL (replace the last argument).

From a clone (contributors)

git clone https://github.com/Reid-n0rc/uni-t-uts-mcp.git
cd uni-t-uts-mcp
npm ci && npm run build
npm run client-config -- --host 192.168.1.100

npm run client-config only prints, it never writes a file. It shows the exact Claude Code command and the JSON block for your OS and for the absolute path of this clone (Windows paths and cmd /c included). Use --from npm, --from tarball, --from github or --from docker to print the other forms, and leave out --host to print the config without UTS_IP.

Supported platforms

Linux, macOS and Windows, with Node.js 22 or newer (CI builds and tests on ubuntu-latest, macos-latest and windows-latest with Node 22 and 24). A Docker image (Linux) is also provided. The analyzer must be reachable over the LAN on TCP port 5025 (raw SCPI); allow outbound connections to that port in any host firewall. For VXI-11 (UTS_TRANSPORT=vxi11 or auto) also allow outbound TCP to port 111 (the portmapper) and to the dynamic core-channel port the portmapper reports (it changes between instrument restarts, so allow outbound connections to the analyzer on any port). Docker Desktop on macOS and Windows reaches LAN instruments through its outbound NAT, so no extra network setup is needed.

To set the address in a shell instead of the client configuration:

Shell

Set UTS_IP for the current session

bash / zsh (Linux, macOS)

export UTS_IP=192.168.1.100

PowerShell (Windows)

$env:UTS_IP = "192.168.1.100"

cmd (Windows)

set UTS_IP=192.168.1.100

Probe scripts take the host as an argument or from UTS_IP: node scripts/probe-basics.mjs 192.168.1.100. node scripts/check-panel-lock.mjs (after npm run build) reports from a screenshot whether the analyzer's front panel is locked (remote mode) and so whether Esc must be pressed.

Project site

The project site is at https://reid-n0rc.github.io/uni-t-uts-mcp/ (source in site/). Its "Built for real hardware" section explains, benefit first, how the server copes with the analyzer's timing quirks. The site has an optional synthwave soundtrack, generated live in your browser with the Web Audio API (no audio files, no downloads, no external requests). It starts automatically where your browser allows it, otherwise on your first click, tap or key press (a small prompt says so); scrolling does not count, because browsers do not treat it as a user gesture. The Soundtrack button at the bottom left is the first thing in the tab order and mutes it; the choice is remembered in your browser and a muted visitor never gets autoplay. The tempo is about 128 BPM; to try another, add ?bpm=128 (or #bpm=128) to the address: values from 60 to 180 work, anything else is ignored, and it changes nothing but the tempo. The music pauses while the tab is hidden, and the hero spectrum reacts to it. A marker flag rides the highest point of the animated spectrum, and the marker.exe window next to it (with a short leader line) shows that point's frequency and level; with reduced motion on, the marker stays on a fixed peak. The code is site/soundtrack.cjs and site/hero-marker.cjs (the marker maths: peak finder, frequency and level mapping, window placement), both inlined into the page at build time. Its tool list is generated from the server's own tool definitions and docs/tools-reference.md, so it stays current. Preview it locally with npm run site and open _site/index.html; Link previews (Open Graph and Twitter card) use site/og.png (1200x630); site/social-preview.png (1280x640) is the same picture for the repository's Settings > Social preview, which GitHub only lets the maintainer upload by hand. Both are rendered from site/og/og.html by npm run og-image (headless Chrome, with the tool count read from the registered tools after npm run build; pass --chrome <path> or set CHROME_PATH if Chrome is elsewhere), and the generated PNGs are committed so deploys need no browser. It is deployed by .github/workflows/pages.yml on every change to main that touches the site or the tools.

Wiki

The project wiki (getting started, every tool, instrument behavior, architecture, troubleshooting, roadmap) is generated from this repository and published automatically after every change to main, so do not edit it in the GitHub wiki editor. The Tools page comes from docs/tools-reference.md, Instrument Behavior from docs/verified-hardware.md, Home from package.json and the tool list, and Roadmap from the issue tracker; the other pages are hand-written in docs/wiki/ and change through pull requests. node scripts/sync-wiki.mjs --check builds the pages and checks every link (CI runs it); node scripts/sync-wiki.mjs --out <dir> writes them to a directory. The project site is at https://reid-n0rc.github.io/uni-t-uts-mcp/.

Documentation

Have an analyzer? The manual testing guide is a checklist for every tool group on raw and VXI-11, with a reporting template. Manual and reference links: docs/references.md.

Security

Report vulnerabilities privately; see SECURITY.md.

License

MIT

Available Tools

85 tools
ad_markerA
Idempotent

Set an AD marker's mode, trace, reference marker (delta mode) and/or position, then return its new state. AD module must be active. Commands apply in the order mode, trace, reference, x. AD has six markers per demod type (not SA's ten) and AD-specific traces (rf_spectrum, demod, demod_average, demod_max, demod_min, af_spectrum); x's unit is Hz for the spectrum traces and seconds for the demodulation-waveform traces. A position set on a marker that is off has no effect: set mode normal (or use ad_marker_search) first. Live-verified (2026-11-12) against a real signal.

Inputs: marker (required), x, mode, trace, +2 more.

ad_markers_all_offA
Idempotent

Turn every AD marker off (:CALCulate:AM|FM:MARKer:AOFF for the current demod type) and confirm it by reading each of the six markers' mode. AD module must be active. Live-verified (2026-11-12).

Inputs: instrument.

configure_measurementA
Idempotent

Enter a measurement (channel_power, time_power, obw, acpr, toi, cn or harmonics) and set its parameters; the instrument stays in the measurement until exit_measurement. preset=true (default) is :CONFigure:, false is :CONFigure::NDEFault. Either way the instrument changes the span, RBW and sweep time (for example span 3 MHz); when entered from spectrum analyzer mode the previous frequency, bandwidth and sweep settings are saved and exit_measurement puts them back, and so is the tracking generator output (entering a measurement switches it off). While a measurement is active most spectrum analyzer queries (detector, trace type) get no reply and the tracking generator cannot be changed.

Inputs: measurement (required), xdb, preset, average, +15 more.

connectA

Connect to a UNI-T UTS series spectrum analyzer over auto (default: VXI-11 when the instrument offers it, else raw SCPI/TCP), VXI-11 or raw SCPI/TCP. Returns the instrument identification and the transport in use. Use host "auto" (or UTS_IP=auto) to find the analyzer on the local network when exactly one answers. Using the analyzer puts it in remote mode and locks its front panel until Esc is pressed on the analyzer.

Inputs: host, name, port, transport.

delete_emi_limit_lineA
DestructiveIdempotent

Delete the points of one EMI limit line (line) or of all EMI limit lines (all: true). EMI module must be active (select_instrument_module). Type, trace and margin settings are left as they are. The result confirms the line is empty (for all, line 1 is checked); the analyzer finishes a delete a moment after it is sent, so the tool waits for it.

Inputs: all, line, instrument.

delete_limit_lineA
DestructiveIdempotent

Delete the points of one limit line (line) or of all limit lines (all: true). Type, trace and margin settings are left as they are. The result confirms the line is empty (for all, line 1 is checked); the analyzer finishes a delete a moment after it is sent, so the tool waits for it.

Inputs: all, line, instrument.

disconnectA

Disconnect from the spectrum analyzer (the instrument named by name, default: the default one). The name stays registered so it can be connected again.

Inputs: name.

discover_instrumentsA
Read-only

Find UNI-T / VXI-11 spectrum analyzers on the local network without knowing their IP address: broadcasts a portmapper query on each local IPv4 interface and identifies every responder with *IDN? (read-only; the serial number is not shown). Returns host, model, firmware and whether VXI-11 and raw port 5025 answer.

Inputs: timeout_ms.

emi_markers_all_offA
Idempotent

Turn every EMI marker off (:CALCulate:FSCan:MARKer:AOFF) and confirm it by reading each marker's mode.

Inputs: instrument.

emi_runA

Start an EMI scan sequence and wait for it, with a time limit. Sends :INITiate2:CONTinuous OFF first (cannot read its prior state first: :INITiate2:CONTinuous? gets no reply in EMI, live-verified), then either :INITiate:FSCan:CLEar:IMMediate (clear_list true: clears the signal list and starts) or :INITiate:IMMediate. There is no documented 'finished' query; completion is inferred from the instrument answering again, since a scan-only sequence was live-verified to leave it silent to everything (including the error queue) for 25 s or more while running, then stop by itself. Reading the resulting signal list is not possible through documented commands (use emi_signal_list actions or the screenshot tool over VXI-11).

Inputs: timeout_s, clear_list, instrument.

emi_signal_listA

Act on the EMI module's signal table (peak table): add the current marker's frequency or measurement to the list, replace or append a row from a meter reading, delete or mark/unmark a signal, set which meter a marker couples to, or zoom the list view. The manual documents NO command to read the table's contents and none of these actions has a read-back, so the result only confirms the command was accepted (no instrument error); to see the actual list, use the screenshot tool over VXI-11.

Inputs: action (required), meter, marker, signal, +1 more.

emi_stopA

Stop a running EMI scan sequence (:INITiate:STOP). Live-verified 2026-11-12: accepted without an instrument error in EMI mode (unlike SA, where this command gives -113). No independent confirmation that it actually halted anything was taken (no documented read-back); the result only reports whether the instrument raised an error.

Inputs: instrument.

enter_analog_demodA

Switch to the analog demodulation (AD) module and read it back. From spectrum analyzer mode, saves the frequency, bandwidth, sweep time and continuous-sweep settings first, for exit_analog_demod to restore; re-entering AD while already there keeps whatever was saved the first time. Warns (not an error) if the module did not change: on this firmware an unlicensed module is refused silently with no SCPI error, which this tool cannot distinguish from a link glitch. Leaves the instrument in AD on purpose; call exit_analog_demod when done. Does not select or preset an AM/FM demodulation type.

Inputs: instrument.

exit_analog_demodA

Leave the AD module and return to spectrum analyzer mode (:INSTrument:SELect SA). Unless restore_settings=false, the frequency, bandwidth, sweep time and continuous-sweep settings saved by enter_analog_demod are put back and verified by read-back (the same resend-once-then-fail pattern exit_measurement uses). Always sends the switch, even if this server never called enter_analog_demod (e.g. after select_instrument_module); a clear warning says so when there is nothing saved to restore, rather than guessing at settings this server never saw.

Inputs: instrument, restore_settings.

exit_measurementA
Idempotent

Leave the measurement and return to spectrum analyzer mode (:CONFigure:SANalyzer). The measurement preset leaves the span, RBW and sweep time changed, so unless restore_settings=false the frequency, bandwidth, sweep time and continuous-sweep settings saved by configure_measurement are put back and verified, and so is the tracking generator output, level and offset when it was on (a measurement entered elsewhere has nothing saved: a warning says so). Does nothing when already in spectrum analyzer mode.

Inputs: instrument, restore_settings.

get_acquisitionA
Read-only

Get the acquisition mode: continuous (true) or single sweep (false), plus the sweep time (s) and its auto flag. Note: over the raw transport the instrument ignores all commands while a single sweep is running; over VXI-11 it queues them.

Inputs: instrument.

get_ad_markerA
Read-only

Read one AD marker: mode (off, normal, delta, fixed), trace, and its position (x) and value (y) together, with their units (which depend on the trace and current demod type). AD module must be active. A delta marker's x/y are relative to its reference marker. An off marker has x and y null. Live-verified (2026-11-12).

Inputs: marker, instrument.

get_ad_settingsA
Read-only

Get a read-only snapshot of the AD (analog demodulation) module's frequency, bandwidth and demod-timing settings: current demodulation type (AM/FM, via :CONFigure?), center frequency and step, RF span and resolution bandwidth, demodulation bandwidth, AF spectrum start/stop and bandwidth, demod window sweep time, demod time and averaging, and input impedance. AD module must be active (enter_analog_demod/select_instrument_module). Filters, audio and display/marker settings are not included here (separate tool groups). A silent or malformed reply to any query is an error naming that command; no partial snapshot is ever returned. :CONFigure? and most of these getters are not yet live-verified on this firmware (docs/verified-hardware.md); treat results as plausible, not confirmed.

Inputs: instrument.

get_amplitudeA
Read-only

Get the analyzer's amplitude settings: reference level (in the current power unit), power unit, scale per division (dB), Y scale type, reference level offset (dB), input attenuation (dB) and whether it is automatic, preamp state and input impedance (ohms).

Inputs: instrument.

get_bandwidthA
Read-only

Get resolution and video bandwidth (Hz) with their auto flags, the VBW/RBW ratio and the filter shape (gaussian or flattop).

Inputs: instrument.

get_demod_resultA
Read-only

Get the AD (analog demodulation) module's numeric result window — center frequency, carrier power, carrier frequency error, modulation rate, SINAD, distortion/total Vrms, THD, and peak+/peak-/(pk-pk)/2/RMS for both the current and max-hold rows — without a screenshot. Wraps the undocumented bare :FETCh:AM?/:FETCh:FM? query (suffix 1, the default), confirmed live on this firmware (docs/verified-hardware.md). The AM/FM type is read fresh from :CONFigure? each call. AD module must be active (enter_analog_demod/select_instrument_module). This does not expose the RF spectrum trace, demodulated waveform or AF spectrum views (other FETCh suffixes); those remain screenshot-only. Units beyond what the live example confirmed (Hz, dB) are plausible, not independently verified.

Inputs: instrument.

get_detectorA
Read-only

Get the detector (sample, positive, negative, normal, average) and its auto flag for one trace (1-6) or all six, via :SENSe:DETector:TRACe.

Inputs: trace, instrument.

get_emi_correctionA
Read-only

Read one EMI correction (antenna/cable) factor set: whether it is enabled and its point list (frequency in Hz, gain in dB, added to the measured level at that frequency). EMI module must be active (select_instrument_module).

Inputs: slot, instrument.

get_emi_limit_lineA
Read-only

Read one EMI limit line: whether it is displayed, its type (upper or lower), the trace it is tested against, the margin and its on/off state, and the point list (frequency in Hz, level in dBm, connected). EMI module must be active (select_instrument_module). The analyzer documents no pass/fail read-back, so whether a trace violates the line cannot be read; check the screenshot or compare get_trace_data with the points.

Inputs: line, instrument.

get_emi_markerA
Read-only

Read one EMI marker: mode (off, normal, delta, fixed), trace (1-3) and its frequency (x, Hz) and level (y, dBm by default) together. A delta marker's x and y are relative to its reference marker. An off marker has x and y null.

Inputs: marker, instrument.

get_emi_peak_criteriaA
Read-only

Read the EMI peak search criteria: threshold (dBm) and excursion (dB), each with its automatic flag. In automatic mode the instrument derives the value from the trace.

Inputs: instrument.

get_emi_settingsA
Read-only

Get a read-only snapshot of the EMI module configuration: standard, scan sequence, the 10-band scan table, meter/trace detectors, trace types, search/peak settings, meter frequency and attenuation, and trigger. EMI module must be active (select_instrument_module). By default omits 'scan_table' (10 bands, by far the most expensive group); pass groups including 'scan_table' to include it. A silent or malformed reply to any query is an error naming that command; no partial snapshot is ever returned.

Inputs: groups, instrument.

get_emi_signal_list_sortA
Read-only

Read the EMI module signal list's sort type and order - the only part of the signal table the manual documents as queryable.

Inputs: instrument.

get_frequencyA
Read-only

Get the analyzer's frequency settings: center, span, start, stop, center step (and whether it is automatic) and offset, all in Hz.

Inputs: instrument.

get_frequency_counterA
Read-only

Read the marker frequency counter: whether it is on and its gate time in seconds.

Inputs: instrument.

get_instrument_moduleA
Read-only

Get the active measurement function module: spectrum_analyzer, emi or analog_demod. Read-only, safe in any module. An unexpected reply (not SA/EMI/AD) is an error quoting it rather than a guess.

Inputs: instrument.

get_limit_lineA
Read-only

Read one limit line: whether it is displayed, its type (upper or lower), the trace it is tested against, the margin and its on/off state, and the point list (frequency in Hz, level in dBm, connected). The analyzer documents no pass/fail read-back, so whether a trace violates the line cannot be read; check the screenshot or compare get_trace_data with the points.

Inputs: line, instrument.

get_markerB
Read-only

Read one marker: mode (off, normal, delta, fixed), trace, and its frequency (x, Hz) and level (y, current power unit, dBm by default) together. A delta marker's x and y are relative to its reference marker (reference_marker is included). An off marker has x and y null.

Inputs: marker, instrument.

get_marker_functionA
Read-only

Read a marker's function (off, noise, band_power, band_density) and the band span used by the band functions. The function result is the marker's level: read it with get_marker (y).

Inputs: marker, instrument.

get_marker_ndbA
Read-only

Read a marker's N-dB bandwidth measurement: whether it is on, the N value (dB below the marker) and, when on, the measured bandwidth in Hz.

Inputs: marker, instrument.

get_measurementA
Read-only

Report whether the instrument is in spectrum analyzer mode, or check one measurement. The instrument has no query for the active measurement, so without 'measurement' this asks one query that only spectrum analyzer mode answers (spectrum_analyzer, or an error that a measurement is active). With 'measurement' (channel_power, time_power, obw, acpr, toi, cn or harmonics) it checks that measurement and returns its parameters; an error means it is not active. A check that gets no reply costs a few seconds while the instrument recovers.

Inputs: instrument, measurement.

get_peak_criteriaA
Read-only

Read the peak search criteria: threshold (dBm) and excursion (dB), each with its automatic flag. In automatic mode the instrument derives the value from the trace.

Inputs: instrument.

get_sweepB
Read-only

Get sweep settings: sweep time (s) with auto flag and auto rule, sweep type (sweep/fft) with auto flag, sweep points (the trace length), trigger source (immediate/video) and video trigger level (dBm).

Inputs: instrument.

get_traceA
Read-only

Get the trace configuration: the selected (current) trace, and for each trace 1-6 (or only trace) its type (write, average, max_hold, min_hold), update state (true = live, false = view/hold) and display state, plus the global average count and average type. Trace math cannot be read (the instrument has no query for it).

Inputs: trace, instrument.

get_trace_dataA
Read-only

Read the amplitude values of one trace (1-6, default the selected trace) with the computed frequency axis, the power unit, the trace type and summary statistics (min, max, mean, peak level and peak frequency). The axis is linear from :FREQuency:STARt? to :FREQuency:STOP? over :SENSe:SWEep:POINts? points (zero span has no frequency axis: a time axis from 0 to the sweep time is returned and the result says so). format is ascii (default: about 14 KB, 7 significant digits, no state change, fastest on the unit), real32 (binary, about 4 KB, the same 7 digits) or real64 (binary, about 8 KB, full double precision); for a binary format the instrument's data format is switched for the read and always put back. fresh runs one single sweep first so the data is a complete, current sweep (continuous mode is switched back on afterwards); without it the values are whatever the trace currently holds, which in continuous mode can be mid-sweep. max_points (>= 2) reduces the response by peak-preserving min/max decimation and the result says so with the original count; the statistics always use the full trace. include_axis (default true) adds the per-point axis.

Inputs: fresh, trace, format, instrument, +2 more.

get_tracking_generatorA
Read-only

Get the tracking generator (the manual's 'trace source') state: output on/off, output level in dBm, level offset in dB, reference trace, normalization on/off and its reference level in dB. While a measurement is active it is an error saying so (call exit_measurement); an error naming the query otherwise means the option is probably not installed.

Inputs: instrument.

identifyA
Read-only

Query the analyzer identification (*IDN?): manufacturer, model, serial number and firmware version.

Inputs: name.

list_instrumentsA
Read-only

List the instruments this server knows by name (the default one, those from UTS_INSTRUMENTS and any added with connect name=...): whether each is connected, where, over which transport, and which one is used when no name is given. Read-only; the serial number is not shown.

Inputs: no named parameters.

markers_all_offA
Idempotent

Turn every marker off (:CALCulate:MARKer:AOFF) and confirm it by reading each marker's mode.

Inputs: instrument.

marker_to_instrumentA

Use a marker's frequency or level to set an instrument parameter: center, step (center frequency step; turns automatic step off), start, stop or reference_level. The marker must be on. Returns the new value of the parameter. The instrument refuses a center that would put the span outside its range.

Inputs: marker (required), target (required), instrument.

measureA
Idempotent

One-shot measurement that leaves the instrument as it found it: from spectrum analyzer mode it saves the frequency, bandwidth and sweep settings and the tracking generator output (entering a measurement switches it off), enters the measurement (channel_power, time_power, obw, acpr, toi, cn or harmonics) with the given parameters, READs the result, and ALWAYS (even on errors) exits to spectrum analyzer mode, restores the settings and the generator and verifies. With the requested measurement already active it only reads and puts any parameters you changed back. It refuses when the instrument is not in spectrum analyzer mode and the requested measurement is not the active one (use exit_measurement first). Takes the measurement's averaging time.

Inputs: measurement (required), xdb, preset, average, +16 more.

read_measurementA
Read-only

Read the result of the active measurement. READ (default) runs the measurement and waits for it; fetch=true returns the latest result at once. channel_power gives channel power (dBm) and density (dBm/Hz), time_power gives power (dBm), obw gives occupied bandwidth (Hz), frequency error (Hz), x dB bandwidth (Hz) and total power (dBm), acpr gives main, lower and upper channel power (dBm) and lower/upper relative power (dBc), cn gives carrier and noise power (dBm) and C/N (dB), toi gives the lower and upper third-order products and tones and the intercept, harmonics gives the fundamental, harmonics 2..n (dBc) and distortion (THD). Errors when that measurement is not active; it never changes the mode.

Inputs: measurement (required), fetch, timeout_s, instrument.

restart_traceA

Restart max hold, min hold or averaging by re-sending the trace's current type (:TRACe:TYPE ). Verified on the instrument: this clears the accumulated hold/average and starts over, and so do changing the type or the update state; :INITiate:RESTart and :INITiate:IMMediate do NOT. Without trace every trace that is in average, max_hold or min_hold is restarted; write traces need no restart.

Inputs: trace, instrument.

scpi_commandA
Destructive

Send a raw SCPI command (no reply expected) to the analyzer. Escape hatch for commands without a dedicated tool. Commands that reset the instrument, change network settings, lock the panel or write files are refused unless confirm=true. Queries are refused; use scpi_query.

Inputs: command (required), confirm, instrument.

scpi_queryA
Read-only

Send one raw SCPI query (it must end in '?') to the analyzer and return the reply. Escape hatch for commands without a dedicated tool. Use reply='block' for IEEE 488.2 '#' binary block replies (returned as base64). Unsupported queries get no reply from the instrument and time out.

Inputs: command (required), reply, instrument, timeout_ms.

screenshotA
Read-only

Capture the analyzer's screen and return it as a PNG image. Needs the VXI-11 transport (over raw TCP the instrument truncates large replies at 144,800 bytes, so the tool refuses with instructions). Temporarily selects PNG as the picture format (:SYSTem:PICture:FORMat) and always restores the original format. Takes about 3 seconds.

Inputs: instrument.

select_instrument_moduleA

Switch the active measurement function module (SA/EMI/AD) and read it back. Does not restore the previous module afterwards - the caller chose this switch; call it again with the module you want back when done. Warns (not an error) if the module did not change: on this firmware an unlicensed module is refused silently with no SCPI error, which this tool cannot distinguish from a link glitch. The front-panel lock is unaffected by this call beyond the usual: see docs/verified-hardware.md, 'Front-panel lock'.

Inputs: module (required), instrument.

set_acquisitionA
Idempotent

Switch between continuous sweep (continuous=true, the instrument's normal state) and single sweep mode (continuous=false, :INITiate:CONTINUOUS OFF). In single mode the instrument sweeps only when start_sweep or single_sweep is used.

Inputs: continuous (required), instrument.

set_ad_audioA

Set the AD (analog demodulation) module's speaker and/or system volume (PM p.158-159, p.9). AD module must be active. Turning the speaker ON, or raising the volume while it is already on, requires confirm=true (loud/unexpected tone in a shared lab, docs/research/analog-demodulation.md risk 3). By default restores the speaker and volume to what they were before this call once the requested change is confirmed by read-back; pass keep=true to leave the new state in place instead. The read path (speaker state, volume) is live-verified (2026-11-12); the speaker-on/volume-raise write path was intentionally not exercised live outside a confirmed, supervised session (the audible side effect this tool's own confirm=true gate exists for).

Inputs: keep, confirm, speaker, instrument, +1 more.

set_ad_demod_timingA
Idempotent

Configure the AD module's demodulation window sweep time, demodulation time (or automatic), and averaging state/count. AD module must be active. The AM/FM prefix is read fresh from :CONFigure? each call. Ranges come from the programming manual and are not yet live-verified. Everything requested is re-read afterwards and any instrument-adjusted value is reported in 'warnings'. Leaves the new state (nothing is restored).

Inputs: instrument, demod_time_s, average_count, average_state, +2 more.

set_ad_displayA
Idempotent

Configure one AD display window's Y-axis reference level and/or per-division value, and (window 3 only) the AF spectrum's linear/log spacing. AD module must be active. The unit of reference_level/per_division depends on the window and current demod type (AM/FM, read fresh from :CONFigure? each call) — see each parameter's description. Live-verified (2026-11-12) for window 1 and window 3's spacing setter; window 2's unit and exact clamp-vs-error behavior were not separately exercised. Everything requested is re-read afterwards and any instrument-adjusted value is reported in 'warnings'. Leaves the new state.

Inputs: window (required), af_spacing, instrument, per_division, +1 more.

set_ad_filtersA
Idempotent

Set the AD (analog demodulation) module's audio filters: low-pass and/or high-pass (freely combinable), or band-pass/weighting (PM p.158-160). AD module must be active. The AM/FM prefix is read fresh from :CONFigure? each call. Live-verified (2026-11-12): low_pass_filter and high_pass_filter can be set together in one call (the instrument does not turn either off for the other), but band_pass_filter is mutually exclusive with both — setting it turns off any active low-/high-pass filter and vice versa (refused locally before sending anything if requested together with either). This tool reads all three before and after and reports in 'warnings' whichever family the instrument turned off that was not explicitly requested.

Inputs: instrument, low_pass_filter, band_pass_filter, high_pass_filter.

set_ad_frequencyA
Idempotent

Configure the AD module's center frequency, RF span, resolution bandwidth and demodulation bandwidth (DBW). AD module must be active. The AM/FM prefix is read fresh from :CONFigure? each call. Ranges come from the programming manual and are not yet live-verified: whether the instrument clamps or errors out of range is UNKNOWN. Everything requested is re-read afterwards and any instrument-adjusted value is reported in 'warnings'. Leaves the new state (nothing is restored).

Inputs: rbw_hz, span_hz, rbw_auto, center_hz, +4 more.

set_amplitudeA
Idempotent

Set amplitude parameters. The power unit is applied first, so reference_level is interpreted in the new unit. Manual attenuation_db turns automatic attenuation off. Out-of-range values are clamped by the instrument; the settings are re-read afterwards and anything it changed is reported in 'warnings'.

Inputs: preamp, instrument, power_unit, scale_type, +6 more.

set_bandwidthA
Idempotent

Set RBW, VBW, the VBW/RBW ratio and the filter shape. Manual values turn the matching auto flag off. The instrument snaps/clamps values and couples RBW, VBW and sweep time to the span and auto flags, so everything is re-read afterwards and any change is reported in 'warnings'.

Inputs: rbw_hz, vbw_hz, rbw_auto, vbw_auto, +3 more.

set_detectorA
Idempotent

Set the detector of one trace (1-6): sample, positive, negative, normal or average (turns that trace's automatic detector off), or switch automatic selection on/off.

Inputs: trace (required), auto, detector, instrument.

set_emi_correctionA
Idempotent

Edit an EMI correction (antenna/cable) factor set. EMI module must be active (select_instrument_module). Give slot plus any of: points (replaces the whole point list; 1 to 10 points in ascending frequency order, each with frequency_hz and gain_db), enabled (on/off), or delete (clears this slot's points; not combined with points). Or give all_off (turns every slot off) or delete_all (clears every slot's points) alone, without slot. The slot (or slot 1, for all_off/delete_all) is re-read afterwards; anything the instrument did not take is reported in 'warnings'.

Inputs: slot, delete, points, all_off, +3 more.

set_emi_limit_lineA
Idempotent

Create or edit an EMI limit line. EMI module must be active (select_instrument_module). Give any of: displayed, type (upper/lower), trace, margin_db and margin_enabled, points (replaces the whole point list; 1 to 12 points in ascending frequency order, equal frequencies make a vertical step, each with frequency_hz, amplitude_dbm and optional connected), copy_from (copy another line's points into this one) or build_from_trace (build points from a trace's current data). copy_from/build_from_trace are sent first, then the other settings. The line is re-read afterwards; anything the instrument did not take is reported in 'warnings'.

Inputs: line, type, trace, points, +6 more.

set_emi_markerA
Idempotent

Set an EMI marker's mode, trace, reference marker (delta mode) and/or frequency position. Commands are applied in the order mode, trace, reference, frequency; the marker is re-read afterwards and anything the instrument did not take is reported in 'warnings'. A position set on a marker that is off has no effect: set mode normal (or use emi_marker_search, which turns the marker on) first.

Inputs: marker (required), mode, trace, instrument, +2 more.

set_emi_measurementA
Idempotent

Configure the EMI module's measurement: standard (none/cispr), sweep sequence and re-measure mode, trace/meter/final detectors, meter dwell time, averaging, and search mode/counts. EMI module must be active (select_instrument_module). At most two of quasi_peak/average_continuous/average may be selected together per detector group (the manual documents this as mutually exclusive). Everything requested is re-read afterwards and any instrument-adjusted value is reported in 'warnings'. Leaves the new state (nothing is restored).

Inputs: sequence, standard, remeasure, instrument, +9 more.

set_emi_peak_criteriaA
Idempotent

Set the EMI peak search criteria. Giving threshold_dbm or excursion_db turns that criterion's automatic mode off; threshold_auto / excursion_auto true switches it back to automatic. Values the instrument changed are reported in 'warnings'.

Inputs: instrument, excursion_db, threshold_dbm, excursion_auto, +1 more.

set_emi_scan_tableA
Idempotent

Edit the EMI module's 10-band scan table: per band, enabled, start_hz, stop_hz, rbw_hz/rbw_auto, time_s/time_auto, attenuation_db/attenuation_auto, points (11-40001) and preamp; or load a CISPR band preset (presets: band, cis: A/B/C/D/CD/E). EMI module must be active (select_instrument_module). The whole table is re-read afterwards and anything adjusted by the instrument (including the neighbor-band coupling the manual describes on overlap or crossing) is reported in 'warnings'.

Inputs: bands, presets, instrument.

set_emi_signal_list_sortA
Idempotent

Set the EMI module signal list's sort type and/or order. Read back afterward; anything the instrument did not take is a warnings entry.

Inputs: sort_type, instrument, sort_order.

set_frequencyA
Idempotent

Set frequency parameters (all in Hz). Give center and/or span, OR start and/or stop, OR full_span, OR zero_span; center step and offset can be combined with any of these. Frequency parameters are coupled, so the settings are re-read afterwards; values the instrument changed are reported in 'warnings'.

Inputs: span_hz, stop_hz, start_hz, center_hz, +6 more.

set_frequency_counterA
Idempotent

Turn the marker frequency counter on or off and/or set its gate time (1 us to 500 ms). Values the instrument changed are reported in 'warnings'.

Inputs: enabled, instrument, gate_time_s.

set_limit_lineA
Idempotent

Create or edit a limit line. Give any of: displayed, type (upper/lower), trace, margin_db and margin_enabled, and points (replaces the whole point list; 1 to 10 points in ascending frequency order, equal frequencies make a vertical step, each with frequency_hz, amplitude_dbm and optional connected). The line is re-read afterwards; anything the instrument did not take is reported in 'warnings'.

Inputs: line, type, trace, points, +4 more.

set_markerA
Idempotent

Set a marker's mode, trace, reference marker (delta mode) and/or position. Commands are applied in the order mode, trace, reference, x; the marker is re-read afterwards and anything the instrument did not take is reported in 'warnings'. A position set on a marker that is off has no effect: set mode normal (or use marker_search, which turns the marker on) first.

Inputs: marker (required), mode, x_hz, trace, +2 more.

set_marker_functionA
Idempotent

Set a marker's function: noise (noise level per Hz), band_power (power in the band), band_density (power density in the band) or off. band_span_hz sets the band width for band_power and band_density. Read the result with get_marker. Values the instrument changed are reported in 'warnings'.

Inputs: marker (required), function, instrument, band_span_hz.

set_marker_ndbA
Idempotent

Turn a marker's N-dB bandwidth measurement on or off and/or set N (dB below the marker, -140 to -0.01, e.g. -3 or -6). Returns the state including the measured bandwidth in Hz (null while off).

Inputs: marker (required), ndb, enabled, instrument.

set_peak_criteriaA
Idempotent

Set the peak search criteria. Giving threshold_dbm or excursion_db turns that criterion's automatic mode off (verified on the instrument); threshold_auto / excursion_auto true switches it back to automatic. Values the instrument changed are reported in 'warnings'.

Inputs: instrument, excursion_db, threshold_dbm, excursion_auto, +1 more.

set_sweepA
Idempotent

Set sweep points, sweep time, sweep type, trigger source and video trigger level. Points, type and rule are applied before the sweep time so a manual time is not overridden by the auto coupling. Changing sweep_points changes the trace length. Out-of-range values are clamped silently by the instrument; settings are re-read afterwards and any change is reported in 'warnings'.

Inputs: instrument, sweep_type, sweep_points, sweep_time_s, +5 more.

set_traceA
Idempotent

Set trace configuration: select the current trace, and for one trace set its type (write, average, max_hold, min_hold), update state (live or view/hold) and display state, and set the global average count (1-999) and average type. Everything is re-read afterwards and anything the instrument did not take is reported in 'warnings'. Changing a trace type or the averaging restarts that trace's hold/average. To restart hold or averaging without changing settings use restart_trace.

Inputs: type, trace, update, display, +4 more.

set_trace_mathA
Idempotent

Set trace math for a trace (:CALCulate:MATH): result trace <- operand_a (op) operand_b. Operations: off, power_difference, power_sum, log_difference, log_offset; offset_db (-100..100) applies only to the two log operations. The instrument has no query for the math setting, so it cannot be read back (check the trace data). Enabling math switches the trace on (update and display); turning it off does not switch it off again.

Inputs: trace (required), operation (required), offset_db, operand_a, +2 more.

set_tracking_generatorA
Idempotent

Set the tracking generator (trace source): output on/off, level (dBm), level offset (dB), reference trace, normalization and its reference level. Level and offset are set before the output is switched on. The output is wired to the analyzer input on some benches, so switch it off when done: switching it off also re-asserts automatic RBW/VBW that were on (the instrument otherwise keeps a stale 300 kHz RBW). Values the instrument changed are reported in 'warnings'.

Inputs: enabled, level_dbm, normalize, instrument, +3 more.

single_sweepA

Switch to single sweep mode, run exactly one sweep and wait until it is complete, so the trace is final and can be read. Leaves the instrument in single mode; use set_acquisition continuous=true to resume normal sweeping.

Inputs: timeout_s, instrument.

start_sweepA

Start (:INITiate:IMMediate) or restart (:INITiate:RESTart) a sweep. In single mode, wait=true (default) blocks until the sweep is complete; with wait=false call wait_for_sweep_complete next, because over the raw transport the instrument ignores every command while it sweeps (VXI-11 queues them). In continuous mode the sweep is restarted and not awaited. There is no stop/pause/resume: the instrument rejects :INITiate:STOP/PAUSe/RESume.

Inputs: wait, method, timeout_s, instrument.

wait_for_sweep_completeA

Wait for a sweep started with start_sweep(wait=false) to finish: over the raw transport it stays silent for the remaining sweep time (the instrument ignores input while sweeping) and then polls *OPC? until it answers; over VXI-11 it makes one blocking *OPC? read that returns when the sweep ends.

Inputs: timeout_s, instrument.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 85 tools

    Disambiguation4/5

    Most tools have a clearly distinct resource/action, and module-specific prefixes plus explicit 'EMI/AD module must be active' notes separate the SA, EMI and AD variants. However the parallel marker, limit-line and peak-criteria families (get_marker vs get_emi_marker vs get_ad_marker; set_marker vs ad_marker) create real misselection risk in such a large set.

    Naming Consistency3/5

    All names are snake_case, but conventions are mixed: many get_/set_ verb_noun pairs coexist with action-first names (measure, connect, identify, screenshot), odd forms (marker_to_instrument, emi_signal_list), and ad_marker acting as a setter while get_ad_marker is the reader. The set is readable overall, but not predictably patterned.

    Tool Count2/5

    85 tools is far above the practical 3-15 range and makes the surface hard for an agent to navigate. Although the server covers three instrument modules and many settings, the count is excessive for an agent-facing toolset.

    Completeness4/5

    Coverage is very broad across SA, EMI and AD: settings get/set pairs, measurement lifecycle, markers, limit lines, traces, sweeps, discovery/connect, and raw SCPI escape hatches. Gaps exist where the instrument exposes no read-back (trace math, EMI signal list, limit-line pass/fail) and some AD display state lacks a getter, but core workflows are covered.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for controlling Hantek DSO2D15 and other DSO2000-family oscilloscopes via USB and SCPI, enabling waveform acquisition, measurements, and screen captures.
      1
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      MCP server for controlling SIGLENT oscilloscopes and signal generators via USBTMC, enabling waveform generation, scope configuration, measurement, and evidence reporting for electronics competitions.
      1
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for reading and controlling an OWON SPE6103 programmable DC power supply over USB serial, with safety checks and verified SCPI commands.
      MIT
    • F
      license
      Not graded
      quality
      B
      maintenance
      Enables unified discovery, query, and control of laboratory instruments (power supplies, oscilloscopes, signal generators, multimeters) via VISA/SCPI, with device-specific libraries and an MCP server exposing 19 tools for natural language interaction.
      -