Thorlabs Optical Power Meter
LocalAbout Thorlabs Optical Power Meter
An MCP server for Thorlabs optical power meters, using SCPI over USBTMC/VISA to read power, log changes, and adjust meter settings. It supports laser measurement workflows and has been tested with a wire-level simulator, not real hardware.
Key features
- 01Read optical power and sensor temperature
- 02Log power series and stability metrics
- 03Set wavelength correction, averaging, and range
- 04Dark-zero the sensor
- 05Inspect meter and sensor information
Use cases
- 01Measure laser power at a selected wavelength
- 02Track laser warm-up drift and stability
- 03Configure wavelength and range before measuring
- 04Check whether a thermal sensor is still warming up
MCP support
Provides MCP clients with reading, configuration, and zeroing tools for Thorlabs optical power meters, sending SCPI commands over USBTMC/VISA.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
uvx labmcp-thorlabs-pmLABMCP_ADDRESSInstrument address, e.g. serial:///dev/ttyUSB0 or tcp://192.168.1.50:5025LABMCP_SIMULATESet to 1 to use the built-in simulator (no hardware)LABMCP_READ_ONLYSet to 1 to disable all state-changing toolsLABMCP_LIMITSSafety limit overrides, e.g. max_temperature_c=80Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.
Tools
11Saved tool list · updated 2w ago
This tool takes no parameters.
Details
From the project READMEThorlabs Optical Power Meter — MCP Server
Let an AI agent read laser power, log stability and warm-up drift, set the wavelength correction, averaging and range, and dark-zero the sensor on Thorlabs optical power meters through their documented SCPI command set over USB (USBTMC / VISA).
| Package | labmcp-thorlabs-pm |
| Instruments | PM100D, PM100A, PM100USB, PM400 consoles with C-series photodiode and thermal sensors. PM101 and PM5020 use the same documented commands but are unverified (see Notes) |
| Interfaces | USB (USBTMC, via VISA) |
| Protocol | SCPI: PM100D Operation Manual 17654-D02 §6.4, PM100USB Operation Manual 19570-D02 §6.3, PM400 Operating Manual v1.1 §5.5, and Thorlabs' per-model SCPI command references |
| Status | 🧪 simulated: tested against a wire-level SCPI simulator, not yet verified on hardware. Report a hardware test |
Try it without hardware
uvx labmcp-thorlabs-pm --simulate --check
uvx labmcp-thorlabs-pm --simulate --option sim_sensor=S302C --check # thermal sensor head
The simulator is a PM100D with an S120C photodiode (or S302C thermopile) looking at a 1.234 mW, 632.8 nm HeNe laser. Setting the wrong wavelength on the photodiode gives a proportionally wrong reading, as on the real bench.
Connect your power meter
- Driver. Thorlabs meters enumerate as USB Test & Measurement Class (USBTMC) devices, vendor ID
0x1313.- Windows: the Thorlabs driver (TLPM / Thorlabs VISA) is not visible to PyVISA. Install the free NI-VISA runtime, then switch the meter to the NI-VISA driver with the Thorlabs Driver Switcher (installed with the Thorlabs Optical Power Monitor software), and start the server with
?backend=@ivi(see below). This is the route Thorlabs documents for PyVISA. - Linux: pyvisa-py talks USBTMC directly (installed with this package). Give your user access to the device, e.g.
/etc/udev/rules.d/99-thorlabs-pm.rules:
thenSUBSYSTEM=="usb", ATTR{idVendor}=="1313", MODE="0666"sudo udevadm control --reload-rulesand re-plug the meter. NI-VISA also works (?backend=@ivi). - macOS: pyvisa-py + libusb (
brew install libusb); NI-VISA is an alternative.
- Windows: the Thorlabs driver (TLPM / Thorlabs VISA) is not visible to PyVISA. Install the free NI-VISA runtime, then switch the meter to the NI-VISA driver with the Thorlabs Driver Switcher (installed with the Thorlabs Optical Power Monitor software), and start the server with
- Find the resource string:
uvx labmcp ports(orpython -m pyvisa info). It looks likeUSB0::0x1313::0x8078::P0012345::INSTR(the product ID depends on the model: PM100D0x8078, PM100USB0x8072). - Test the connection:
For the second input of a PM5020 adduvx labmcp-thorlabs-pm --address USB0::0x1313::0x8078::P0012345::INSTR --check uvx labmcp-thorlabs-pm --address "visa://USB0::0x1313::0x8078::P0012345::INSTR?backend=@ivi" --check # NI-VISA--option channel=2.
Add to your MCP client
Claude Code
claude mcp add power-meter -- uvx labmcp-thorlabs-pm --address USB0::0x1313::0x8078::P0012345::INSTR
Claude Desktop / Cursor / Windsurf (claude_desktop_config.json, .cursor/mcp.json, …)
{
"mcpServers": {
"power-meter": {
"command": "uvx",
"args": ["labmcp-thorlabs-pm", "--address", "USB0::0x1313::0x8078::P0012345::INSTR"]
}
}
}
Add --read-only to allow readings but block wavelength, averaging, range and zero changes. For other clients, generate the snippet with uvx labmcp config thorlabs-pm --address <resource> --client vscode (also cursor, codex, claude-code).
Tools
| Tool | Kind | Description |
|---|---|---|
get_command_log | 👁 read | Return the most recent raw commands sent to / replies received from the instrument (newest last). Useful for debugging and for recording what was done. |
get_connection_info | 👁 read | Report which instrument is connected (identity, address, simulated or real), whether the server is read-only, and the active safety limits. Call this first. |
get_device_info | 👁 read | Identify the meter console and the attached sensor head (model, serial, type, wavelength range, power ranges), and report the present wavelength, averaging, range and zero value. |
log_power_series | 👁 read | Log a series of power readings to characterise laser stability, warm-up or drift. Returns mean, stdev, min/max, RMS and peak-to-peak stability (%) and drift (%/min), plus the readings (downsampled to max_points; use save_path, a new .csv file, to keep all of them). |
read_power | 👁 read | Read the optical power once (in W, plus dBm and a formatted string). The reading uses the configured correction wavelength and averaging; set the wavelength first. |
read_sensor_temperature | 👁 read | Read the sensor head temperature in °C (thermal sensors and other heads with a built-in temperature sensor only). |
reconnect | 🛑 safety | Close and re-open the connection to the instrument (e.g. after it was power cycled or a cable was re-plugged). |
set_averaging | 🎛 control | Set how many samples the meter averages for each reading. More averaging lowers noise but slows each reading (PM100 series: ~3 ms per sample; PM400/PM101/PM5020: 1 ms). |
set_range | 🎛 control | Select auto-ranging, or a fixed power range that fits range_w (the meter picks the most sensitive range that can hold that power). A fixed range reports over-range if exceeded. |
set_wavelength | 🎛 control | Set the correction wavelength (nm) the meter uses to convert sensor signal to power. Must be within the sensor's calibrated range (see get_device_info); sent as a whole number of nm. |
zero_sensor | 🎛 control | Dark-zero the sensor (removes dark current / thermal offset). BEFORE calling, ask the user to block the beam and cover the sensor aperture completely, and wait for them to confirm: zeroing with light on the sensor corrupts all later readings. Takes a few seconds. |
get_connection_info, get_command_log and reconnect are built into every LabMCP server.
A power meter only measures, so this server has no hazard tools. Your laser is the hazard: wear the right eyewear and never exceed the sensor's rated power or power density.
Safety limits
| Limit | Default | Meaning |
|---|---|---|
max_series_duration_s | 600 s | Longest power-logging series an agent may start, estimated as count × max(interval, reading time), where a reading takes averaging × 3 ms plus ~10 ms |
Override at launch: --limit max_series_duration_s=3600. One call can log at most 3640 s (the tool's timeout minus a margin): longer estimates are refused, and a series that runs slower than estimated stops early and returns what it measured (completed: false). save_path must end in .csv and must not exist yet (an existing file is never overwritten); it is checked before logging starts.
Example prompts
- "Set the meter to 1064 nm and tell me the power after the objective."
- "Log the laser power every 2 s for 10 minutes and report the RMS and peak-to-peak stability. Save the data to ~/data/laser_warmup.csv."
- "I've capped the sensor. Zero it, then I'll remove the cap and you read the power."
- "Measure the transmission of this ND filter: read the power without it, then again after I insert it, and give me the optical density."
- "Is the thermal sensor head still warming up? Read its temperature every minute until it's stable."
Notes
- Wavelength matters. Photodiode responsivity varies by a factor of several across the sensor's range, so a wrong wavelength setting gives a wrong power. The server sends whole nanometres (the PM400/PM101/PM5020 references specify an integer), so 632.8 nm is set as 633 nm. That changes the responsivity by far less than the sensor's calibration uncertainty.
- Units.
MEAS:POW?answers in the meter's configured unit (W or dBm). The driver readsSENS:POW:UNIT?first and always returns watts, so a front-panel unit change can't mislead the agent. - Out of range. The meter answers INFINITY / 9.9E37 when the signal exceeds a manually selected range. The server reports this as an error that suggests auto-ranging.
- Zeroing (
SENS:CORR:COLL:ZERO) runs in the background. The server polls…:ZERO:STAT?, checks the error queue, and returns the zero value (…:ZERO:MAGN?). Zero values are lost when the meter reboots. - Energy (pyroelectric) sensors are recognised but not supported: single-pulse energy measurement needs a trigger/fetch workflow that this server doesn't implement yet.
- Averaging is
SENS:AVER:COUN. One sample takes ~3 ms on the PM100 series and 1 ms on the PM400/PM101/PM5020. The reply timeout scales with the averaging count. - PM101 and PM5020: Thorlabs' command references for these list exactly the commands used here. The PM5020 adds a channel suffix (
SENS2,MEAS2,SYST:SENS2:IDN?), selected with--option channel=2. Neither has been tested yet, and PM5020 LAN/serial connections have not been tried. The PM100D's Windows TLPM DLL driver is not used; this server speaks SCPI only. - The simulator's error replies for out-of-range values (
-222,"Data out of range") use the standard SCPI code. The Thorlabs documents only list-113,"Undefined header"explicitly.
Hardware verification
| Model | Firmware | Interface | Verified by | Date |
|---|---|---|---|---|
| none yet: be the first |
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.