Skip to main content
Glama
USBTMC MCP Server

USBTMC MCP Server

by NaoNaoMe

USBTMC MCP Server

License: MIT

A Model Context Protocol (MCP) server for controlling multiple USBTMC (USB Test and Measurement Class) devices simultaneously using SCPI commands.

Features

  • Multi-Device Support: Connect and control up to 16 instruments at once.

  • Unified Interface: Use standard SCPI commands via a simplified MCP toolset.

  • Keysight Support: Includes specialized tools to unlock Keysight modular instruments from firmware mode to USBTMC mode.

  • Screenshot Capture: Take screenshots from Keysight/Agilent and Tektronix oscilloscopes.

  • State Management: Automatic tracking of device IDs and connection states.

Related MCP server: instrument-mcp

Requirements

  • Python >= 3.13

  • mcp[cli] 2.x (v0.2.0 and later; use usbtmc-lite-mcp 0.1.x if you are pinned to mcp 1.x)

Windows Additional Setup

This project uses libUSB as a backend for USB communication. On Windows, you need to install a compatible USB driver for your device using Zadig.

  1. Download and run Zadig

  2. Select your target USB device from the dropdown (enable Options → List All Devices if it does not appear)

  3. Select WinUSB as the driver and click Replace Driver

Note: Replacing the driver will remove the device's original functionality (e.g., HID recognition). To restore it, uninstall the driver from Device Manager and reconnect the device.

Installation

Using uv (recommended):

uv pip install usbtmc-lite-mcp

Or via pip:

pip install usbtmc-lite-mcp

Or from source:

git clone https://github.com/NaoNaoMe/usbtmc-lite-mcp.git
cd usbtmc-lite-mcp
uv sync

Configuration

Claude Desktop Config

Add the server to your claude_desktop_config.json:

{
  "mcpServers": {
    "usbtmc-lite-mcp": {
      "command": "uvx",
      "args": [
        "usbtmc-lite-mcp"
      ]
    }
  }
}

Tools Overview

Connection

  • usbtmc_list_devices: Scan the USB bus for available USBTMC instruments.

  • usbtmc_list_connected_devices: List all currently active device connections.

  • usbtmc_connect: Establish a connection to a specific device (returns a device_id).

  • usbtmc_disconnect: Close the connection to a device.

Communication

  • usbtmc_query: Send a SCPI query (e.g., *IDN?) and receive the response.

  • usbtmc_send: Send a SCPI command.

  • usbtmc_receive: Manually reads the response.

  • usbtmc_clear: Clear device buffers and reset communication state.

Keysight / Tektronix Utilities

  • usbtmc_unlock_keysight_devices: Switch Keysight modular instruments to USBTMC mode.

  • usbtmc_screenshot_keysight_display: Capture a screenshot from a Keysight/Agilent oscilloscope.

  • usbtmc_screenshot_tektronix_display: Capture a screenshot from a Tektronix oscilloscope.

Example Workflow

  1. List Devices: Call usbtmc_list_devices to find your instrument's serial number.

  2. Connect: Call usbtmc_connect with the serial_number. It will return a device_id (e.g., 0).

  3. Identify: Call usbtmc_query with device_id: 0 and command: "*IDN?".

  4. Configure: Call usbtmc_send to set parameters.

  5. Disconnect: Call usbtmc_disconnect when finished.

License

This project is licensed under the MIT License — see the LICENSE file for details.

Available Tools

11 tools
usbtmc_clearA
Idempotent

Clear the device input/output buffers and reset communication state.

Use this to recover from communication errors or stuck states.

Args: params (DeviceIdInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect()

Returns: dict: Result containing: - success (bool): Whether the clear operation was successful - device_id (int): The target device_id - message (str): Success or error message

Inputs: params (required). Returns: object

usbtmc_connectA

Connect to a USBTMC device and receive a device_id for subsequent operations.

The device_id is used to identify the connection in all subsequent operations. If multiple devices match the criteria, the connection will fail - provide more specific criteria to uniquely identify the target device.

Args: params (ConnectInput): Connection parameters containing: - manufacturer (str, optional): Device manufacturer name to match - product (str, optional): Device product name to match - serial_number (str, optional): Unique device serial number (most specific)

Returns: dict: Result containing on success: - device_id (int): Unique identifier for this connection (use for all subsequent operations) - manufacturer (str): Device manufacturer name - product (str): Device product/model name - serial_number (str): Device serial number - message (str): Success message

On error:
    - error (str): Error message describing the failure

Note: Maximum 16 simultaneous connections are supported.

Inputs: params (required). Returns: object

usbtmc_disconnectA
Idempotent

Disconnect from a specific USBTMC device.

Args: params (DeviceIdInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect()

Returns: dict: Result containing: - success (bool): Whether the disconnection was successful - device_id (int): The disconnected device_id - product (str): Product name of the disconnected device - message (str): Success or error message

Inputs: params (required). Returns: object

usbtmc_list_connected_devicesA
Read-onlyIdempotent

List all currently connected (active) USBTMC devices.

Returns: dict: Result containing: - count (int): Number of connected devices - devices (list[dict]): List of connected device info, each containing: - device_id (int): Unique identifier for the connection - manufacturer (str): Device manufacturer name - product (str): Device product/model name - serial_number (str): Device serial number

Example: >>> result = usbtmc_list_connected_devices() >>> result { "count": 1, "devices": [ { "device_id": 0, "manufacturer": "Keysight Technologies", "product": "DSO-X 3024A", "serial_number": "MY12345678" } ] }

Inputs: no named parameters. Returns: object

usbtmc_list_devicesA
Read-onlyIdempotent

List all available USBTMC devices connected via USB.

This is typically the first step in the workflow:

  1. usbtmc_list_devices() - Discover available devices

  2. usbtmc_connect() - Connect to a device and get device_id

  3. Use device_id for operations (send/query/etc.)

  4. usbtmc_disconnect() - Close connection when done

Returns: dict: Result containing: - count (int): Number of devices found - devices (list[dict]): List of device info dictionaries, each containing: - manufacturer (str): Device manufacturer name - product (str): Device product/model name - serial_number (str): Unique device serial number

Example: >>> result = usbtmc_list_devices() >>> result { "count": 1, "devices": [ { "manufacturer": "Keysight Technologies", "product": "DSO-X 3024A", "serial_number": "MY12345678" } ] }

Inputs: no named parameters. Returns: object

usbtmc_queryA

Send a SCPI command and immediately receive the response.

Use for QUERY commands (with '?') that request information from the device. For SET commands (without '?'), use usbtmc_send() instead.

This is a convenience function combining send and receive operations.

Args: params (QueryInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect() - command (str): SCPI command string to send (usually ends with '?') - wait_time (float): Time to wait between send and receive (default: 0.1s) - max_bytes (int): Maximum bytes to read (default: 1024)

Returns: dict: Result containing: - success (bool): Whether the query was successful - device_id (int): The target device_id - command (str): The command that was sent - response (str or None): Response data, or None if no data/timeout - message (str): Success or error message

Note: Wait time recommendations: - Simple queries (*IDN?, status): 0.1s (default) - Querying existing measurements: 0.1s - After changing settings: 0.5-2.0s

Inputs: params (required). Returns: object

usbtmc_receiveA
Read-only

Receive data from a specific USBTMC device.

Args: params (ReceiveInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect() - max_bytes (int): Maximum bytes to read (default: 1024)

Returns: dict: Result containing: - success (bool): Whether data was received - device_id (int): The target device_id - data (str or None): Received data string, or None if no data/timeout - message (str): Success or error message

Inputs: params (required). Returns: object

usbtmc_screenshot_keysight_displayA
Read-only

Capture screenshot from a Keysight/Agilent oscilloscope.

Args: params (DeviceIdInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect()

Returns: Image

Inputs: params (required).

usbtmc_screenshot_tektronix_displayA
Read-only

Capture screenshot from a Tektronix oscilloscope.

Args: params (DeviceIdInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect()

Returns: Image

Inputs: params (required).

usbtmc_sendA

Send a SCPI command to a specific USBTMC device.

Use for SET commands (without '?') that configure device settings. For QUERY commands (with '?'), use usbtmc_query() instead.

This function only sends data; use usbtmc_receive() to read responses, or use usbtmc_query() for send+receive in one operation.

Args: params (SendInput): Input containing: - device_id (int): The unique identifier returned by usbtmc_connect() - command (str): SCPI command string to send

Returns: dict: Result containing: - success (bool): Whether the send was successful - device_id (int): The target device_id - command (str): The command that was sent - message (str): Success or error message

Inputs: params (required). Returns: object

usbtmc_unlock_keysight_devicesA
Idempotent

Switch all Keysight devices from firmware update mode to USBTMC mode.

Some Keysight USB modular instruments (e.g., U2700 series) power on in firmware update mode and require a vendor-specific command to switch to normal USBTMC operation.

After calling this function, devices will re-enumerate on the USB bus. Wait a moment, then call usbtmc_list_devices() to discover them.

Returns: dict: Result containing: - unlocked_count (int): Number of successfully unlocked devices - total_found (int): Total devices found in firmware mode - message (str): Success or informational message - errors (list[str], optional): List of error messages if any device failed

Inputs: no named parameters. Returns: object

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A4.3/5.0

    Scored across 11 tools

    Disambiguation5/5

    Each tool targets a distinct operation: discovery, connection, communication, recovery, vendor unlock, and vendor-specific screenshots. The only potential confusion between list_devices and list_connected_devices is resolved by clear descriptions.

    Naming Consistency5/5

    All tools follow a usbtmc_<verb>_<noun> pattern in lowercase snake_case, with consistent verb-first ordering and vendor qualifiers where needed.

    Tool Count5/5

    11 tools is well-scoped for a USBTMC server, covering the full workflow without excessive fragmentation.

    Completeness5/5

    The tool set covers the complete lifecycle from discovery to disconnection, including send/receive/query for SCPI communication, recovery via clear, and vendor-specific features for Keysight and Tektronix.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      B
      maintenance
      An MCP server for controlling lab instruments (oscilloscopes, signal generators, etc.) via standardized interfaces like USBTMC, RS-232, and LAN.
      100
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Connects test and measurement instruments (oscilloscope, logic analyzer, multimeter, power supply) to AI via MCP, enabling natural language control and automated analysis.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables MCP clients to connect to and control Siglent oscilloscopes and power supplies over SCPI/TCP using typed tool calls with input validation, safety controls, and built-in observability.
      1
      Apache 2.0
    • 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.
      -