Getting Started
This tutorial walks you through installing mcpyvisa, configuring a backend, and discovering the instruments it can reach. By the end, you will have a working MCP server that an LLM can use to talk to your test equipment.
What you will need
Section titled “What you will need”Before starting, make sure you have:
- A supported instrument connection — any of the following:
- An AR488 adapter (ESP32 with AR488 firmware) connected via USB or WiFi to GPIB instruments
- A USB-TMC instrument connected directly to your computer
- A LAN/VXI-11 instrument on your network
- NI-VISA or Keysight IO Libraries installed for system VISA resources
- Python 3.11+ with uv installed
- Claude Code (or another MCP-compatible client)
Install mcpyvisa
Section titled “Install mcpyvisa”-
Quickest: run directly from PyPI
If you just want to use mcpyvisa without cloning the source,
uvxwill fetch and run it in an isolated environment:Terminal window uvx mcpyvisaThis downloads mcpyvisa, installs its dependencies, and starts the MCP server. Press
Ctrl+Cto stop it. You will configure it properly in the next step. -
Alternative: install from source
If you want to modify mcpyvisa or run from a local checkout:
Terminal window git clone https://git.supported.systems/warehack.ing/mcgpib.gitcd mcgpibuv syncuv run mcpyvisa
Configure your backend
Section titled “Configure your backend”mcpyvisa reads its configuration from a TOML file. It searches these locations in order:
- The path in the
$MCPYVISA_CONFIGenvironment variable ./mcpyvisa.tomlin the current directory~/.config/mcpyvisa/config.tomlin your home directory
Create a configuration file for your setup. The examples below show the most common backend types.
Create ~/.config/mcpyvisa/config.toml:
[server]log_level = "INFO"auto_discover = trueauto_identify = true
[[backend]]name = "bench-a"type = "ar488"transport = "serial"port = "/dev/ttyUSB0"baudrate = 115200auto_discover = trueauto_identify = trueread_timeout_ms = 3000inter_command_delay_ms = 10
[instruments.dmm]resource = "GPIB0::22::INSTR"backend = "bench-a"
[instruments.psu]resource = "GPIB0::5::INSTR"backend = "bench-a"Each field:
| Field | Purpose |
|---|---|
name | A unique identifier you choose for this backend. Used in connect_backend and disconnect_backend. |
type | "ar488" for AR488/Prologix GPIB adapters. |
transport | "serial" for USB connections. |
port | The serial port path. On Linux this is typically /dev/ttyUSB0 or /dev/ttyACM0. On macOS, look for /dev/cu.usbserial-*. |
baudrate | Must match the AR488 firmware setting. The default is 115200. |
auto_discover | When true, mcpyvisa discovers instruments on the bus immediately after connecting. |
auto_identify | When true, sends *IDN? to each discovered listener during discovery. |
read_timeout_ms | How long to wait for an instrument response before timing out (milliseconds). |
inter_command_delay_ms | Pause between consecutive commands. Prevents ESP32 voltage dips under rapid bus activity. |
The [instruments.*] sections define aliases. Instead of typing GPIB0::22::INSTR in every tool call, you can just say "dmm".
Create ~/.config/mcpyvisa/config.toml:
[server]log_level = "INFO"auto_discover = trueauto_identify = true
[[backend]]name = "bench-a"type = "ar488"transport = "tcp"host = "192.168.1.50"tcp_port = 23auto_discover = trueauto_identify = trueread_timeout_ms = 5000inter_command_delay_ms = 20
[instruments.dmm]resource = "GPIB0::22::INSTR"backend = "bench-a"The WiFi-specific fields:
| Field | Purpose |
|---|---|
host | IP address of the ESP32 on your network. Configure this on the adapter first with the ++wifi command over serial. |
tcp_port | TCP port the adapter listens on. The AR488 WiFi default is 23. |
Note the longer timeouts — WiFi adds latency compared to USB, so read_timeout_ms = 5000 and inter_command_delay_ms = 20 give the adapter more breathing room.
Create ~/.config/mcpyvisa/config.toml:
[server]log_level = "INFO"auto_discover = trueauto_identify = true
[[backend]]name = "lan-rack"type = "pyvisa-py"auto_discover = trueauto_identify = trueread_timeout_ms = 5000
[instruments.scope]resource = "TCPIP::192.168.1.10::INSTR"backend = "lan-rack"
[instruments.bench-dmm]resource = "USB0::0x0957::0x0607::MY12345::INSTR"backend = "lan-rack"The pyvisa-py backend uses the pure-Python VISA implementation. It supports USB-TMC instruments (via usb resource strings) and LAN instruments (via TCPIP resource strings) without requiring NI-VISA or any proprietary drivers.
Create ~/.config/mcpyvisa/config.toml:
[server]log_level = "INFO"auto_discover = trueauto_identify = true
[[backend]]name = "ni"type = "system"auto_discover = trueauto_identify = true
[instruments.dmm]resource = "GPIB0::22::INSTR"backend = "ni"The system backend uses whatever VISA library is installed on the system — NI-VISA, Keysight IO Libraries, or any other IVI-compliant implementation. It can reach any resource that visa.ResourceManager() can open.
Add to Claude Code
Section titled “Add to Claude Code”Register mcpyvisa as an MCP server so Claude Code can discover and call its tools.
claude mcp add mcpyvisa -- uvx mcpyvisaclaude mcp add mcpyvisa -- uv run --directory /path/to/mcgpib mcpyvisaReplace /path/to/mcgpib with the actual path to your cloned repository.
If your config file is not in one of the default search paths, point mcpyvisa to it with the environment variable:
MCPYVISA_CONFIG=/path/to/mcpyvisa.toml claude mcp add mcpyvisa -- uvx mcpyvisaConnect and discover
Section titled “Connect and discover”With mcpyvisa registered, start a Claude Code session and walk through the connection. Here is what a typical first conversation looks like.
-
Connect to the backend
Ask Claude to connect, or call the tool directly:
> Connect to my backend "bench-a"Claude calls
connect_backend("bench-a"). The server initializes the pyvisa ResourceManager for that backend, opens the transport, and reads the adapter firmware version (for AR488 backends). Ifauto_discoveris enabled, it also discovers instruments reachable through the backend.You should see a response like:
Connected to bench-a (ar488, serial)Firmware: AR488 GPIB controller 0.05.99Discovered 3 instrument(s):GPIB0::1::INSTR — HEWLETT-PACKARD 34401AGPIB0::5::INSTR — KEITHLEY INSTRUMENTS INC. 2000 (alias: dmm)GPIB0::22::INSTR — Agilent Technologies E3631A (alias: psu)Instruments that match a configured alias show their alias name in parentheses.
-
Discover instruments manually (optional)
If
auto_discoverwas disabled in your config, or if you have added instruments since connecting, discover explicitly:> Discover instruments on bench-aClaude calls
discover_instruments("bench-a"). For AR488 backends, this sends++findlstnto poll every GPIB address from 1 to 30, then sends*IDN?to each listener. For other backends, it queries the ResourceManager for available resources.Discovered 3 instrument(s) on bench-a:GPIB0::1::INSTR — HEWLETT-PACKARD 34401A (S/N: 3146A02377)GPIB0::5::INSTR — KEITHLEY INSTRUMENTS INC. 2000 (S/N: 1234567)GPIB0::22::INSTR — Agilent Technologies E3631A (S/N: MY12345678) -
Identify a specific instrument
To get detailed identification for a single instrument, use its alias or VISA resource string:
> Identify the instrument "dmm"Claude calls
instrument_identify("dmm"):dmm (GPIB0::5::INSTR on bench-a):Manufacturer: KEITHLEY INSTRUMENTS INC.Model: 2000Serial: 1234567Firmware: A04 /A02Raw: KEITHLEY INSTRUMENTS INC.,2000,1234567,A04 /A02You can also use the full VISA resource string:
instrument_identify("GPIB0::5::INSTR").
Your backend is connected and your instruments are discovered. You are ready to start taking measurements.
What is next
Section titled “What is next”- First Measurement — send SCPI commands to a multimeter and read a DC voltage
- Multi-Backend Setup — configure AR488, USB-TMC, and LAN backends for cross-bus workflows
- Configuration Reference — full documentation of every config field
- Tool Reference — complete list of all 22 tools with parameters and examples