Multi-Backend Setup
A single backend controls a set of instruments — one GPIB bus through an AR488 adapter, a group of LAN instruments through pyvisa-py, or everything visible to NI-VISA. When your equipment spans multiple transports or physical locations, mcpyvisa manages them all from one server. This tutorial shows you how to configure multiple backends and run cross-backend operations.
When you need multiple backends
Section titled “When you need multiple backends”Common scenarios:
- Mixed instrument buses — GPIB instruments on an AR488 adapter and newer USB-TMC or LAN instruments connected directly. Each bus type needs its own backend.
- Separate test benches — one bench for analog measurements, another for RF or power. Each has its own GPIB bus and adapter.
- Mixed transports — a USB-connected AR488 adapter on the bench in front of you, and a WiFi adapter on a rack across the lab.
- Isolation — sensitive measurement equipment on one bus, noisy power supplies on another, to avoid bus contention and ground loops.
- Scale — more than 30 GPIB instruments. Each GPIB bus supports 30 addresses, so a second backend doubles your GPIB capacity. USB-TMC and LAN backends have no such limit.
Each backend operates independently. The server talks to them concurrently, and serializes commands within each backend using per-backend locks.
Configure multiple backends
Section titled “Configure multiple backends”Create or update your configuration file with multiple [[backend]] sections. The double brackets in TOML denote an array — each [[backend]] block defines one backend.
[server]log_level = "INFO"auto_discover = trueauto_identify = true
# AR488 adapter on the local bench (GPIB instruments)[[backend]]name = "bench-a"type = "ar488"transport = "serial"port = "/dev/ttyUSB0"baudrate = 115200auto_discover = trueauto_identify = trueread_timeout_ms = 3000inter_command_delay_ms = 10
# pyvisa-py for LAN and USB-TMC instruments on the rack[[backend]]name = "lan-rack"type = "pyvisa-py"auto_discover = trueauto_identify = trueread_timeout_ms = 5000
# Instrument aliases -- each specifies which backend it lives on[instruments.dmm]resource = "GPIB0::22::INSTR"backend = "bench-a"
[instruments.psu]resource = "GPIB0::5::INSTR"backend = "bench-a"
[instruments.scope]resource = "TCPIP::192.168.1.10::INSTR"backend = "lan-rack"
[instruments.bench-dmm]resource = "USB0::0x0957::0x0607::MY12345::INSTR"backend = "lan-rack"A few things to note:
- Each backend must have a unique
name. This is how you reference them inconnect_backendanddisconnect_backend. - Backend type determines the driver.
ar488uses the pyvisa-ar488 backend,pyvisa-pyuses the pure-Python implementation,systemuses NI-VISA. - Instrument aliases specify their backend. The
backendfield in each[instruments.*]section tells mcpyvisa which backend to route commands through. This means"dmm"and"scope"resolve to different backends automatically. - Timeouts are independent. LAN instruments might need longer timeouts than local USB connections.
Connect backends
Section titled “Connect backends”-
Check server status
Start a Claude Code session and verify the server sees all configured backends:
> Show me the server statusClaude calls
server_status():Server: mcpyvisa v0.2.0Backends: 2 configuredbench-a (ar488, serial /dev/ttyUSB0): disconnectedlan-rack (pyvisa-py): disconnectedInstruments: 4 aliases configureddmm -> GPIB0::22::INSTR (bench-a)psu -> GPIB0::5::INSTR (bench-a)scope -> TCPIP::192.168.1.10::INSTR (lan-rack)bench-dmm -> USB0::0x0957::0x0607::MY12345::INSTR (lan-rack)Both backends are configured but not yet connected. Aliases are listed with their target resource and backend.
-
Connect the first backend
> Connect to bench-aClaude calls
connect_backend("bench-a"):Connected to bench-a (ar488, serial)Firmware: AR488 GPIB controller 0.05.99Discovered 2 instrument(s):GPIB0::5::INSTR — KEITHLEY INSTRUMENTS INC. 2000 (alias: dmm)GPIB0::22::INSTR — Agilent Technologies E3631A (alias: psu) -
Connect the second backend
> Connect to lan-rack tooClaude calls
connect_backend("lan-rack"):Connected to lan-rack (pyvisa-py)Discovered 2 instrument(s):TCPIP::192.168.1.10::INSTR — Tektronix TDS 2024B (alias: scope)USB0::0x0957::0x0607::MY12345::INSTR — Agilent 34461A (alias: bench-dmm) -
View everything at once
> Show me all instrumentsClaude calls
server_status():Server: mcpyvisa v0.2.0Backends: 2 configured, 2 connectedbench-a (ar488, serial): connectedGPIB0::5::INSTR — KEITHLEY INSTRUMENTS INC. 2000 (alias: dmm)GPIB0::22::INSTR — Agilent Technologies E3631A (alias: psu)lan-rack (pyvisa-py): connectedTCPIP::192.168.1.10::INSTR — Tektronix TDS 2024B (alias: scope)USB0::0x0957::0x0607::MY12345::INSTR — Agilent 34461A (alias: bench-dmm)The backend name prefix tells you which bus each instrument is on. Aliases let you forget the details.
Cross-backend operations
Section titled “Cross-backend operations”With multiple backends connected, you can orchestrate workflows that span buses. The alias system routes each command to the correct backend automatically — you do not need to specify which backend an instrument is on when using aliases.
Here is a practical example: read a voltage with the bench DMM while adjusting a power supply on the GPIB bus. Suppose you are characterizing how a device under test responds to supply voltage changes.
-
Set the power supply output
The Agilent E3631A (alias
"psu") on bench-a has three outputs. Set the +6V output to 3.3V:> Set the psu to output 3.3V on the +6V channelClaude calls:
instrument_write("psu", "INST P6V")— select the +6V outputinstrument_write("psu", "VOLT 3.3")— set voltage to 3.3Vinstrument_write("psu", "OUTP ON")— enable the output
Sent to psu: INST P6VSent to psu: VOLT 3.3Sent to psu: OUTP ON -
Read the resulting voltage on the other backend
The Agilent 34461A (alias
"bench-dmm") on lan-rack is probing the device under test via USB-TMC:> Read DC voltage on the bench-dmmClaude calls:
instrument_write("bench-dmm", "CONF:VOLT:DC")instrument_query("bench-dmm", "READ?")
Sent to bench-dmm: CONF:VOLT:DC+3.29120E+003.291V measured at the DUT — reasonable for a 3.3V supply with some drop across the circuit. The power supply was controlled over GPIB (via AR488) and the measurement was taken over USB-TMC (via pyvisa-py), all through the same mcpyvisa server.
-
Sweep and measure
You can ask Claude to automate the full sequence:
> Sweep the psu voltage from 3.0V to 5.0V in 0.5V steps.> At each step, wait 500ms for settling, then read the voltage on> the bench-dmm. Show me a table of set voltage vs measured voltage.Claude will interleave
instrument_writecalls to"psu"withinstrument_querycalls to"bench-dmm", building a table as it goes:| Set (V) | Measured (V) ||---------|-------------|| 3.0 | 2.987 || 3.5 | 3.491 || 4.0 | 3.993 || 4.5 | 4.488 || 5.0 | 4.982 |
Use the bus_health_check prompt
Section titled “Use the bus_health_check prompt”mcpyvisa includes a bus_health_check prompt that audits all backends in a single pass. This is useful for verifying your multi-backend setup is healthy.
> Run a bus health checkClaude activates the bus_health_check prompt and executes a systematic sequence:
- Calls
server_status()to enumerate all configured backends - For each connected backend, calls
discover_instruments()andcheck_srq()(GPIB backends only) - For disconnected backends, attempts
connect_backend() - Calls
serial_poll()on GPIB backends to check for instruments requesting service
The resulting report looks something like:
Infrastructure Health Report==================================
Backends: 2 configured, 2 connected, 0 failed
bench-a (ar488, serial /dev/ttyUSB0): Firmware: AR488 GPIB controller 0.05.99 Instruments: 2 discovered, 2 identified GPIB0::5::INSTR — KEITHLEY INSTRUMENTS INC. 2000 (dmm) — status 0x00 (idle) GPIB0::22::INSTR — Agilent Technologies E3631A (psu) — status 0x00 (idle) SRQ: not asserted
lan-rack (pyvisa-py): Instruments: 2 discovered, 2 identified TCPIP::192.168.1.10::INSTR — Tektronix TDS 2024B (scope) USB0::0x0957::0x0607::MY12345::INSTR — Agilent 34461A (bench-dmm) (SRQ not applicable for this backend type)
Recommendations: - All instruments responding normally. No action needed.Backend-specific configuration
Section titled “Backend-specific configuration”Different instruments and transports need different timing. For AR488 backends, you can adjust settings at runtime without restarting the server using configure_ar488.
-
Increase timeout for a slow instrument
Some instruments — particularly older HP meters or anything doing an internal self-test — take several seconds to respond. If you are getting timeout errors:
> Set the read timeout on bench-a to 10 secondsClaude calls
configure_ar488("bench-a", read_timeout_ms=10000):Configured bench-a: read_timeout_ms=10000This takes effect immediately for all subsequent operations on that backend. Other backends are not affected.
-
Tune EOS settings for a specific AR488 backend
Some instruments expect line endings different from the default CRLF. The
eosparameter controls what the AR488 adapter appends when sending data:Value Line ending 0CR+LF (default) 1CR only 2LF only 3None > Set bench-a to use LF line endingsClaude calls
configure_ar488("bench-a", eos=2):Configured bench-a: eos=2 -
View current server status
To check the state of all backends and instruments:
> Show me the server statusClaude calls
server_status()which returns the full picture: all backends, their connection state, and all discovered instruments with aliases.
Concurrency model
Section titled “Concurrency model”Understanding how mcpyvisa handles concurrent access helps you reason about what is safe to do in multi-backend setups.
Across backends: concurrent. Each backend has its own asyncio lock and its own transport. Operations on bench-a and lan-rack can proceed simultaneously without blocking each other.
Within a backend: serialized. GPIB is a shared bus — only one device can talk at a time. USB-TMC and LAN transports also serialize per-backend to avoid interleaved responses. The per-backend lock ensures that if two tool calls target the same backend, one waits for the other to complete.
Practical implication: If Claude needs to read a voltage on the "dmm" (bench-a) and capture a waveform on the "scope" (lan-rack), those two operations can overlap. But if Claude needs to write a command and then read a response from two instruments on the same backend, those are always sequential.
What is next
Section titled “What is next”- Configuration Reference — full documentation of all config fields and the search path
- Universal Tools Reference — details on connect, disconnect, status, and discover tools
- Prompts Reference — all guided workflows, including
bench-initandtroubleshoot-bus