Repository navigation
Getting Started
- Node.js 22 or newer (CI tests Node 22 and 24 on Linux, macOS and Windows), or Docker.
- A UNI-T UTS series analyzer on your network, reachable from the machine that runs the server. Raw SCPI is served on TCP port 5025 (verified on the UTS3036B; other models are expected to behave the same but are untested).
- An MCP client such as Claude Code or Claude Desktop.
The server is pure Node (no native modules, no VISA).
- Connect the analyzer to your network and note its IP address (shown in the instrument's LAN/system settings).
- Check that port 5025 is reachable from your computer:
- macOS / Linux:
nc -z -w 2 192.168.1.100 5025 - Windows (PowerShell):
Test-NetConnection 192.168.1.100 -Port 5025
- macOS / Linux:
- Replace
192.168.1.100in this page with your analyzer's address. Never commit real addresses or serial numbers to a repository.
Release v1.1.0 is out. Pick one of these; each registers the server under the name uni-t-uts. UTS_IP is optional: without it, tell the assistant "connect to the analyzer at 192.168.1.100" and it uses the connect tool.
Using Cursor, VS Code, Windsurf or another client? See Add to Client.
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.0On 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.tgzDownload uni-t-uts-mcp-1.1.0.mcpb from the v1.1.0 release and double-click it; Claude Desktop asks for the analyzer address (optional), port and transport. Installing it in Claude Desktop itself has not been verified yet; the JSON configuration below always works.
Add an mcpServers entry to the client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: ~/.cursor/mcp.json; some VS Code-style clients use 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 tarball URL (replace the last argument).
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.100npm 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 the absolute path of your clone. Use --from npm, --from tarball, --from github or --from docker to print the other forms.
The server connects automatically at startup when UTS_IP is set (a failed auto-connect is only logged; you can still call the connect tool).
| Variable | Description |
|---|---|
UTS_IP |
Analyzer hostname or IP. Enables auto-connect and is the default host for the connect tool |
UTS_PORT |
TCP port of the raw transport, default 5025
|
UTS_TRANSPORT |
auto (default: VXI-11 if the analyzer offers it, otherwise raw), raw or vxi11. Default for the connect tool's transport parameter; setting only UTS_PORT means raw |
UTS_VXI11_DEVICE |
VXI-11 logical device name, default inst0
|
UTS_INSTRUMENTS |
Optional, for several analyzers at once: name=host[:port],name2=host2[:port2] or JSON ({"name":"host:port"}). UTS_IP is the instrument named default; these add more, all connected at startup. connect, disconnect and identify take a name; list_instruments shows them ; every other tool takes an optional instrument argument |
UTS_BUSY_TIMEOUT_S |
How many seconds a tool call waits for another call to finish before failing with Instrument busy, default 120
|
To set the address in a shell instead of the client configuration: export UTS_IP=192.168.1.100 (bash, zsh), $env:UTS_IP = "192.168.1.100" (PowerShell) or set UTS_IP=192.168.1.100 (cmd).
The default transport is auto: VXI-11 when the analyzer offers it, otherwise raw SCPI over TCP port 5025 (UTS_TRANSPORT=raw or vxi11 forces one). VXI-11 uses TCP port 111 (the portmapper) and a port the portmapper reports, which changes between instrument restarts, so a host firewall must allow outbound connections to the analyzer. Over VXI-11 the analyzer queues commands sent during a sweep instead of dropping them, and single_sweep waits with one blocking *OPC?. VXI-11 was verified against the real UTS3036B (issue #75): every tool gives the same values as over raw, nothing is dropped during a sweep, and the screen image is not truncated. Details: Architecture and the programming guide.
Ask your assistant to:
-
Identify the analyzer (
identify). You should get a line likeUNI-TREND,UTS3036B,<serial>,V1.04.0040. -
Read the current settings (
get_frequency,get_amplitude,get_bandwidth,get_sweep,get_acquisition,get_trace). -
Change something small (for example
set_frequencywith a new center and span) and check the returned state and anywarnings.
To try the tools without an AI client, use the MCP Inspector from a clone of the repository:
UTS_IP=192.168.1.100 npm run inspector # macOS / Linux
$env:UTS_IP = "192.168.1.100"; npm run inspector # Windows PowerShellIf something does not work, see Troubleshooting.
- The front panel locks while you use it. Once the server sends commands, the analyzer is in remote mode and its touch screen and buttons stop responding. Press Esc on the analyzer to return it to local mode (verified on a UTS3036B over raw TCP; the remote ways back to local do not work on that firmware).
- The analyzer ignores every command while a single sweep is running on the raw socket, so long manual sweep times make other tools time out. The server copes with this for its own sweeps. See Instrument Behavior.
-
Parallel tool calls are safe. The server runs tool calls one at a time per instrument, in the order they arrive, so results and errors are never mixed up. A long operation such as
single_sweepmakes other calls wait, and a call that waits longer thanUTS_BUSY_TIMEOUT_Sseconds fails withInstrument busywithout having sent anything. -
Several analyzers at once. Name them in
UTS_INSTRUMENTS(for examplesa1=192.168.1.100:5025,sa2=analyzer2.local) or add them withconnectand aname, then passinstrumentto any tool. Calls to different analyzers run in parallel, calls to the same analyzer are queued, and an error on one never affects another.list_instrumentsshows them. - Some commands are blocked unless explicitly confirmed (reset, network settings, panel lock, file writes). See Safety and Security.
- The
screenshottool works over VXI-11 only; see the Roadmap.
MIT licensed. Verified on a UNI-T UTS3036B (firmware V1.04.0040); other models are untested. This wiki is generated from the repository's docs/ folder, which is authoritative: change it there, not here.