List JouleScope devices
list_devicesList connected JouleScope devices, including JS220 serial numbers and firmware versions, to identify and check device status.
Instructions
List connected JouleScope devices, including JS220 serial and firmware details when available.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/joulescope_mcp/service.py:142-165 (handler)The core logic of list_devices: iterates connected devices, retrieves serial number, hardware/firmware/fpga versions, and returns driver_version + devices list.
def list_devices(self) -> dict[str, Any]: with self._driver_session() as driver: devices = [] for device_path in list(driver.device_paths()): item: dict[str, Any] = { "path": device_path, "model": "js220" if "/js220/" in device_path else "unknown", "serial_number": device_path.rstrip("/").split("/")[-1], "available": True, } try: driver.open(device_path, mode="restore") if "/js220/" in device_path: item["hardware_version"] = _version_to_str(driver.query(f"{device_path}/c/hw/version")) item["firmware_version"] = _version_to_str(driver.query(f"{device_path}/c/fw/version")) item["fpga_version"] = _version_to_str(driver.query(f"{device_path}/s/fpga/version")) except Exception as exc: item["available"] = False item["error"] = str(exc) finally: with suppress(Exception): driver.close(device_path) devices.append(item) return {"driver_version": self.driver_version, "devices": devices} - src/joulescope_mcp/server.py:38-48 (registration)The MCP tool registration for 'list_devices' using the @mcp.tool decorator. Delegates to service.list_devices().
@mcp.tool( title="List JouleScope devices", description="List connected JouleScope devices, including JS220 serial and firmware details when available.", annotations=read_only, structured_output=True, ) def list_devices() -> dict[str, Any]: try: return service.list_devices() except JoulescopeMcpError as exc: raise _tool_error(exc) from exc - src/joulescope_mcp/service.py:54-62 (helper)Helper used by list_devices to convert integer-encoded version numbers (e.g., firmware version) into dot-separated strings.
def _version_to_str(version: Any) -> str: if isinstance(version, str): return version if not isinstance(version, int): return str(version) v_patch = version & 0xFFFF v_minor = (version >> 16) & 0xFF v_major = (version >> 24) & 0xFF return f"{v_major}.{v_minor}.{v_patch}" - The return type dict[str, Any] and the structured output shape (driver_version string + devices array with path/model/serial_number/available/versions) effectively serve as the schema.
def list_devices(self) -> dict[str, Any]: with self._driver_session() as driver: devices = [] for device_path in list(driver.device_paths()): item: dict[str, Any] = { "path": device_path, "model": "js220" if "/js220/" in device_path else "unknown", "serial_number": device_path.rstrip("/").split("/")[-1], "available": True, } try: driver.open(device_path, mode="restore") if "/js220/" in device_path: item["hardware_version"] = _version_to_str(driver.query(f"{device_path}/c/hw/version")) item["firmware_version"] = _version_to_str(driver.query(f"{device_path}/c/fw/version")) item["fpga_version"] = _version_to_str(driver.query(f"{device_path}/s/fpga/version")) except Exception as exc: item["available"] = False item["error"] = str(exc) finally: with suppress(Exception): driver.close(device_path) devices.append(item) return {"driver_version": self.driver_version, "devices": devices}