openaxpp300s-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openaxpp300s-mcpset the output to 5 V with a 1 A current limit and turn it on"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openaxpp300s
English | 简体中文
An open Python package, command-line interface and MCP server for the AX PP300S buck-boost bench power supply (0 to 30 V, 0 to 10.1 A, 300 W), driven over the supply's USB serial port. It is written so that an AI agent (Claude Code, or any MCP client) can set voltage and current, switch the output, read back what the terminals deliver, log for hours and run timed sequences by itself, without the vendor PC app. Every command prints one JSON object per line, and every error has a stable code, a message, an exit code and, for most errors, a hint.
The protocol was taken from the vendor documents, from a disassembly of the supply's firmware (V1.4.4) and from
measurements on the real supply; see docs/PROTOCOL.md.
This project is not affiliated with AxinDIY, the maker of the supply. "AX PP300S" is their product name.
Status and tested hardware
Version 0.1.1 (beta). Verified on the real supply on 2026-11-07, in three sessions: an AX PP300S with firmware V1.4.4, a Windows 11 PC, a CH340 USB serial chip. In the second and third sessions the supply ran from a 65 W USB-PD charger (about 19.8 V) on its Type-C power input, with a Fluke 289 and an electronic load as references. Before the third session the user calibrated the supply's current on the front panel against the (recently checked) Fluke 289.
Verified on the hardware:
port discovery,
status,selftest;setof VSET, ISET, OVP, OCP, DELAY, REV, OPP and OTP (each one is acknowledged by the supply);onandoff, also into a load (CV and CC);VSET accuracy from 0.5 V to 30 V against a Fluke 289 with no load, including boost to 20, 24 and 30 V from the 20 V input (see Accuracy);
the CC limit (ISET) against the Fluke 289 at about 3 V, from 0.05 A to 5 A after the user's current calibration (0.1 A to 1 A before it), and the current in CV under load (0.5 A) (see Accuracy);
lowering VSET and OVP together with the output on (no load), and lowering ISET and OCP together while 1 A flowed into a load (no trip in either case; the setpoint is sent first, the protection after the output has come down);
DELAY and REV behaviour,
watch,sequence,rawqueries and the refusals (OVP headroom, an undocumented or out-of-rangerawframe);the MCP server against the real supply: ports, status, selftest, set (including a refused set), output, watch, log_start / job_status / job_stop, sequence_start;
the Chinese screen and its parameter lists: writing and selecting lists,
oninto the selected list's voltage, a list change with the output on, the refusal of a list whose OVP is too low, the cut-off current and the cut-off time, and that Digital-screen registers (VSET, DELAY) have no effect there;display colours (
color set,color reset);CV/CC priority (
--priority);link timing (see Timing).
No protection tripped in the second or third session. CC was verified up to 5 A and about 17.5 W (the supply went from 32.7 C to 36.0 C during the run up to 5 A).
Not yet verified on the hardware:
OCP, OPP and OTP trips (only OVP tripped, twice, on the first day);
the on-device settings menu and its effects;
currents above 5 A and powers above about 20 W;
the DC5525 power input (the second and third sessions used the Type-C power input);
CC accuracy at other output voltages (the CC table below was measured at about 3 V);
the EEPROM writes themselves (see Does a status query really write the EEPROM?).
Linux and macOS: the code has no Windows-only paths in the serial layer, but only Windows was tried. The test suite runs against the simulator (see Simulator); no test opens a real port.
Related MCP server: Rigol DP832 MCP Server
Install
Requirements: Python 3.10 or newer, the supply, a USB cable. The only dependency is pyserial.
From PyPI:
pip install openaxpp300sOr from a checkout (for development): pip install -e . (add ".[test]" for the tests). Either way the install
provides the commands openaxpp300s and openaxpp300s-mcp; python -m openaxpp300s ... is the same as
openaxpp300s .... Releases: a tag vX.Y.Z runs .github/workflows/release.yml (tests, build, GitHub release,
PyPI by trusted publishing).
Connecting the supply
Use the supply's serial Type-C port (the one for data), not the power-input port. The supply appears as a CH340 USB serial device (VID:PID 1A86:7523) and gets a COM port number on Windows (COMx). Install the WCH CH340 driver if Windows does not do it by itself.
The supply must be switched on and showing its normal screen (not the white-screen bootloader).
Close the vendor PC app, a serial terminal and FlyMcu first: only one program can hold the port.
Opening the port does not reset the supply and does not change its output.
Port discovery:
openaxpp300s ports --probelists the serial ports and asks each USB one (Bluetooth ports are skipped) for a status reply; the port that answers
is remembered for later commands. Without --port, the port is taken from $OPENAXPP300S_PORT, else the one that answered last, else the
first USB serial port that answers like a PP300S. To choose explicitly: --port COMx (for example --port COM14).
Quick start
openaxpp300s ports --probe
openaxpp300s selftest
openaxpp300s limits --max-voltage 12 --max-current 3 --note "test board"
openaxpp300s set -V 5 -I 1 --ovp 6 --ocp 2
openaxpp300s on
openaxpp300s status
openaxpp300s offSet the bench limits first (see Bench limits). Add --sim to any command to try it against the
virtual supply, without hardware.
A real --sim run of set:
$ openaxpp300s --sim set -V 5 -I 1 --ovp 6 --ocp 2
{"ok":true,"cmd":"set","port":"SIM","sent":[
{"key":"ovp","name":"OVP","value":6.0,"unit":"V","raw":600,"id":"0x02","ack":"01","latency_ms":1.9},
{"key":"ocp","name":"OCP","value":2.0,"unit":"A","raw":200,"id":"0x03","ack":"01","latency_ms":5.0},
{"key":"voltage","name":"VSET","value":5.0,"unit":"V","raw":500,"id":"0x00","ack":"01","latency_ms":5.2},
{"key":"current","name":"ISET","value":1.0,"unit":"A","raw":100,"id":"0x01","ack":"01","latency_ms":5.9}],
"output_on_before":false,"status":{...}}(Line breaks added here; the tool prints one line.) The protections that stay above the output go first, then the
setpoints. on and status:
$ openaxpp300s --sim on
{"ok":true,"cmd":"on","port":"SIM","sent":[{"key":"output","name":"ON/OFF","value":true,"unit":"","raw":1,
"id":"0x08","ack":"01","latency_ms":2.2}],"settled":true,"on_after_s":1.12,"status":{"vout_v":5.0,"iout_a":0.0,
"pout_w":0.0,"vin_v":19.8,"temp_c":28.5,"output_on":true,"mode":"CV","cc_flag":0,"output_flag":1,...}}--text prints a short human-readable form instead of JSON:
$ openaxpp300s --sim --text status
SIM output OFF OFF
out 0.000 V 0.000 A 0.00 W
in 19.80 V temp 28.5 C (reply 47.3 ms)CLI reference
Global options, before or after the subcommand:
Option | Meaning |
| serial port (default: |
| use the virtual supply (also |
| human-readable output instead of JSON |
| print every frame sent and received on stderr |
| seconds to wait for another command using the port (default 5) |
| seconds to wait for each answer (default 0.3) |
| resends of a frame without an answer (default 2) |
| print the version (before the subcommand only) |
Commands:
Command | What it does |
| list serial ports; |
| measured output (V, A, W), input voltage, temperature, CV/CC, output state, plus the values this tool sent last and the bench limits; a note when the output is on but this tool did not switch it on (see below) |
| send settings in a safe order (options below) |
| switch the output on (honours DELAY and REV) and wait until the voltage is up (see On, settling and the Chinese screen); with DELAY or REV (as sent last) over 20 s it returns without waiting, unless |
| switch the output off and wait until it is down |
| the five parameter lists 0..4 of the Chinese screen (see below) |
| display colours of the Digital screen (firmware 1.4.4 or newer; saved in the supply's EEPROM) |
| status lines every |
| log the status to CSV or JSONL with Ah and Wh until |
| timed voltage/current steps (CSV like the vendor template: |
| stop running |
| list the running ones |
| show or change the bench limits |
| the register table: ids, ranges, screens |
| send one frame (decimal or |
| read-only checks of the link and the supply (status replies, latency, plausible values, a bad-checksum frame ignored); never changes a setting; exit code 1 when a check fails |
set options:
Option | Range and step |
| VSET, 0 to 30.00 V, 10 mV steps |
| ISET, 0.01 to 10.10 A, 10 mA steps |
| over-voltage protection, 0.5 to 30.50 V |
| over-current protection, 0.1 to 10.50 A |
| DELAY, 0 to 9999 s: after |
| REV, 0 to 9999 s: after |
| over-power protection, 10 to 310 W in 10 W steps |
| over-temperature protection, 60 to 100 C in 10 C steps |
| CV first or CC first (firmware 1.4.2 or newer; factory default is CC first; see CV first or CC first) |
| do not wait for the output to follow a new VSET |
With the output on, set waits until the output follows a new VSET (up to 3 s, else NOT_APPLIED). A new OVP or OCP
that is not above what the terminals show now (plus a small margin) is refused while the output is on, unless the same
call lowers VSET (or ISET) below it: then the tool sends the setpoint first, waits for the output to come down, and
only then sends the protection. With the output off it waits for the terminals to discharge first.
list select N makes list N of the Chinese screen the active one; list set N writes list N: --voltage,
--current, --ovp, --ocp, --cut-current A (the output goes off after the current stays below it for about 6 s
by the firmware, 5.5 to 6 s measured, 5 s by the manual; 0 = off), --cut-time (the output goes off when the
accumulated on-time reaches it: 1h30m, 45m, 50s, H:M:S, or off = 99:60:60; 0:0:0 is refused) and --select
(also make it the active list, sent after the values). VSET, ISET, OVP, OCP, DELAY and REV act on the Digital and Waveform screens only, the
list registers on the Chinese screen only; OPP, OTP and the CV/CC priority act on every screen. The supply
acknowledges and stores every frame on any screen, so a register for another screen simply has no effect. This is
verified on the hardware: on the Chinese screen a Digital VSET (and DELAY) is ignored, and with the output on a
set -V ends with NOT_APPLIED after 3 s.
Notes on the Chinese screen (measured on the hardware unless marked):
A list value written over serial lives in RAM only and is lost at power-off, unless it belongs to the selected list and the front-panel cursor sits on that field. The list selection is saved: with the cursor in its default position on the Chinese screen, every frame saves it. (Firmware disassembly; power-off was not tried.) Write the values first and select last (
--selectdoes this).Changing the values of the selected list with the output on moves the output at once (2.0 V to 2.4 V followed immediately).
list select Nis refused before anything is sent when the OVP of list N (as sent last) is not above the voltage at the terminals now (plus a small margin), because the output would trip; raise that list's OVP first.The cut-offs are silent: the output just switches off and the supply does not beep, unlike a protection trip. With
--cut-current 0.1and no current flowing, the output switched off after about 5.5 to 6 s. On the serial link it looks like a plain "output off"; when this tool had switched the output on,statusadds a note that lists a cut-off among the possible causes.The cut-off time compares the accumulated on-time since power-up (or since the last time cut-off, or since the statistics were cleared), not the time since the last
on. With a cut-off time of 10 s, the firstonafter setting it was cut at once, because the counter already held the on-time accumulated since power-up; after a time cut-off the counter restarts, and the nextonstayed on for 9 to 10 s.
On, settling and the Chinese screen
on waits until the output voltage is up. It counts the output as settled when a CV reading is at the Digital VSET
or at the VSET of the selected list (each as sent last), so on the Chinese screen on accepts the selected list's
voltage (measured: 1.9975 V for a list of 2.0 V). If the reading is at neither, but is stable in CV 1 s after the soft
start, on returns with a note saying so. If the output flag is still off when the wait ends, the note names a
Chinese-screen cut-off among the possible reasons (cut-offs are silent, and the on-time counts since power-up). Into a
CC load on settled in CC after about 1.7 s.
status adds a note when the output is on but this tool did not switch it on: someone pressed the output key on
the front panel, or another program switched it. The settings in force may then differ from last_sent. (The note
was added after this happened on the hardware: the user pressed the output key three times, and the meter showed the
output on without any on frame from the tool.)
CV first or CC first
--priority cc (the factory default) limits the switch-on current overshoot; --priority cv lets the current
overshoot ISET for a moment. Measured switching on into a 3 V constant-voltage load with VSET 5 V and ISET 0.5 A, from
the supply's read-back polled at 20 Hz: CV first peaked at 0.811 A and 4.263 V, CC first at 0.541 A and 3.733 V (about
60 % over ISET against about 8 %). With CV first, an OCP close to ISET could trip during that overshoot (OCP needs
100 ms). A priority sent over serial is lost at power-off unless the settings menu is exited afterwards (firmware).
Testing the current limit with an electronic load
To test CC (ISET) with an electronic load, put the load in constant-voltage mode at a voltage below VSET, or use
a real resistor. Do not use constant-resistance mode: when the supply has to limit the current, the load's CR loop
and the supply's CC loop fight, and the current jumps between about 0 and 1.2 A every 0.5 to 2 s while the supply sits
in CV most of the time (the multimeter saw it too). Even so, the charge that log recorded over 10 s in that state
(10 Ohm, VSET 12 V, ISET 1 A) was 0.00152 Ah, within 4 % of the meter (mean current times time: 0.00158 Ah). In CV
mode the CC limit is stable and linear.
sequence --dry-run checks the steps against ranges, bench limits and OVP headroom without sending any setting:
$ openaxpp300s --sim sequence --steps "5,1,2;9,1,2" --dry-run
{"ok":false,"cmd":"sequence","error":{"code":"UNSAFE_OPERATION","message":"step 2: VSET 9 V needs OVP >= 9.2 V,
but the OVP sent last is 6 V (4 s ago): the output would trip","hint":"set an OVP above the highest step first:
openaxpp300s set --ovp 9.21"}}Watching and logging
watch prints one JSON line per sample and a summary at the end:
{"type":"sample","t":1794040307.969,"vout_v":0.0,"iout_a":0.0,"pout_w":0.0,"vin_v":19.8,"temp_c":28.5,"mode":"OFF","output_on":false,"latency_ms":13.9}
{"ok":true,"cmd":"watch","event":"done","stopped_by":"count","elapsed_s":0.18,"last":{...},"samples":2,"ah":0.0,
"wh":0.0,"on_s":0.0,"modes":{"OFF":2},"stats":{"vout_v":{"min":0.0,"max":0.0,"mean":0.0},...}}log writes a file (default data/log_<time>.csv, or .jsonl) with the CSV columns pc_time, local_time, vout_v, iout_a, pout_w, vin_v, temp_c, mode, output_on, ah, wh, step. It reconnects for up to --reconnect-for (default
5 min; watch: 10 s) when the supply stops answering. watch, log and sequence can run in the background;
running lists them and stop ends them. By the firmware, every status query makes the supply rewrite one EEPROM field (unless the
DATA box is selected), so do not poll faster than you need (see Safety).
Output format
Every command prints JSON, one object per line, on stdout:
success:
{"ok":true,"cmd":"...", ...};failure:
{"ok":false,"cmd":"...","error":{"code":"...","message":"...","hint":"..."}}(nohintwhen there is none), also on stdout, and a non-zero exit code;watchprints sample lines ("type":"sample");logandsequenceprint event lines ("event":"started","step","link_lost", ...); all three end with a summary line carrying"event":"done".
Units are SI: V, A, W, s, C. Timestamps t are Unix time in seconds.
Errors and exit codes
Code | Exit | Meaning and hint |
| 2 | bad option or value, or a value outside the supply's range; the hint gives the range |
| 3 | no PP300S answered on any USB serial port, or the named port does not exist; plug the supply in by its serial Type-C port, switch it on, close the vendor app, or give |
| 4 | the port is held by another program (close the vendor PC app, a serial terminal or FlyMcu and retry), or another openaxpp300s command kept it longer than |
| 5 | the supply acknowledged but the read-back shows no effect; typically the supply is on the wrong screen, or a charged capacitor or battery holds the output |
| 6 | no answer: supply off, in its bootloader, or the wrong port; try |
| 6 | an answer with a bad header, tail or checksum; another program may be talking to the supply |
| 6 | serial I/O error (cable unplugged, driver error); the command was retried after reopening the port |
| 7 | refused for safety, for example: over the bench limits (or the output rose above the voltage limit and was switched off again), an OVP closer to VSET than the headroom rule allows, an OVP or OCP not above what the terminals show now, an OPP or OTP within 5 W or 5 C of the present power or temperature, or an undocumented register in |
(other) | 1 | any other failure ( |
A watch, log or sequence stopped on request (stop, Ctrl+C) ends with exit code 0 and the summary it had. Any
other command interrupted with Ctrl+C exits with code 130.
Bench limits
openaxpp300s limits --max-voltage 12 --max-current 3 --note "what is connected" stores a maximum voltage (0 to
30 V) and a maximum current (0 to 10.1 A) in state/limits.json. They apply to every command and every MCP call,
except raw --unsafe:
voltage-like values (VSET, OVP, list VSET and OVP) and current-like values (ISET, OCP, list ISET and OCP) above them are refused with
UNSAFE_OPERATION;onis refused when the VSET sent last is above the voltage limit; with a voltage limit set, a list selection is refused when that list's voltage is unknown to the tool;while
onfollows the output (not with--no-wait), and for 1 s after a list selection with the output on, the output is switched off again at once if the measured voltage exceeds the voltage limit by more than 2 % + 50 mV (the front panel may have set anything);sequences are checked step by step before the first step starts, and every sample of a running sequence is checked against the voltage limit.
$ openaxpp300s --sim limits --max-voltage 12 --max-current 3 --note "test board"
{"ok":true,"cmd":"limits","changed":true,"limits":{"max_voltage":12.0,"max_current":3.0,"note":"test board",
"updated":"2026-11-07 03:31:28"},"file":".../state/limits.json"}(file is the full path; shortened here.)
limits --clear removes them. With no limits set, only the supply's own ranges apply. Set the limits to match what
is connected before you let an agent drive the supply.
Safety
The supply drives real power. Read this before connecting a load.
Headroom rule. The tool refuses an OVP lower than
VSET + max(0.2 V, 1.5 %), whether given in the same call or as sent last, andonrefuses to switch on when the VSET and OVP sent last break that rule. An OCP lower thanISET + max(0.05 A, 2 %)is sent with a warning (it trips as soon as a load pulls the output into CC); keep it above that. The reason for the OVP rule is measured: an OVP of 3.00 V with VSET 3.00 V tripped the output as the voltage stepped up from 2 V, and an OVP of 2.00 V with VSET 3.00 V tripped as the output rose. A setpoint step overshoots a little (1.0068 V for 1.00 V once).Never trip a protection. A tripped protection switches the output off and sounds the alarm. The alarm and the trip flag are cleared only by a front-panel key press; the supply cannot report an alarm, and a trip looks on the serial link like a plain "output off" (the on/off flag goes to 0). After a trip, a remote
onstill switches the output on again, but the alarm keeps sounding until someone presses a key. Checkstatusafter every change.The supply cannot report its settings. The link carries the measured output and one on/off flag, not the setpoints, the screen, the cursor or the alarm. The tool remembers what it sent (
last_sentinstatus), and the front panel may have changed things since. Thesetcommand refuses an OVP or OCP that is not above what the terminals show now (plus a small margin), unless the same call lowers the setpoint (see CLI reference).Know what is connected. The voltage that appears on
onis whatever is in force on the supply, which on the Chinese screen is the selected parameter list. Checkvout_vafter switching on.Cut-offs are silent. On the Chinese screen the cut-off current and cut-off time switch the output off without the alarm. A silent "output off" can therefore be a cut-off, not a trip and not a program; the cut-off time counts the on-time accumulated since power-up (see CLI reference).
Keep the settings menu closed while a command runs. Entering the on-device settings menu switches the output off once. While it is open the measurements on the link are frozen, OPP and OTP are not checked, and a remote
oncan switch the output on with regulation frozen. Do not use the tool while the menu is open. (Found in the firmware disassembly; not tried on the hardware.)EEPROM wear and the DATA box. The supply saves the front-panel field under its cursor to its EEPROM on every valid frame it receives, status queries included (found in the firmware disassembly; the writes themselves were not yet observed on the hardware; see Does a status query really write the EEPROM?). With the cursor on V-SET (the power-up default) that is a write to the VSET bytes about 10 times per second when polled at the vendor app's rate of 100 ms: about one million writes in 28 hours, near the typical rating of a 24Cxx part (about 1e6 cycles; the actual part and its rating are not known). The EEPROM has fixed addresses and no wear levelling. Tip: move the front-panel cursor to the DATA box (the last box of the setting bar, after REV) on the Digital or Waveform screen; with it selected, frames save nothing (firmware). Turning the knob while DATA is selected clears the Ah, Wh and time statistics (vendor manual), so leave the knob alone.
watchandlogdefault to one query per second; do not go below what you need.Settings persistence after power-off (from the firmware disassembly). Values sent over serial are only partly kept. VSET, ISET, OVP, OCP, DELAY and REV are written to the EEPROM only if their field is the one under the cursor when a frame arrives (VSET by default); otherwise they are gone at power-off. OPP, OTP and CC-first are kept only if the front-panel settings menu is exited afterwards. The output state is never kept; the output is off after power-up. Display colours are always kept.
Closing the port is safe, the output stays as it is. An interrupted command does not switch the output off by itself, except a
sequence, which switches it off at the end, onstopor on Ctrl+C unless started with--end keep(and always after a bench-limit orNOT_APPLIEDerror). Switch the output off yourself when you leave.Hardware coverage is limited (see Status). Do not assume that a trip, an over-power or an over-temperature case behaves as written here until it has been tested on your supply.
MCP server
openaxpp300s-mcp is an MCP server (stdio, standard library only). Every tool runs the CLI in a child process, so
the same checks, bench limits and error codes apply. It has no raw tool, and the bench limits can only be changed
with the CLI. Add it to Claude Code:
claude mcp add -s user openaxpp300s -- openaxpp300s-mcpIf the Python Scripts folder is not on PATH, give the full path of the executable, for example
<Python>\Scripts\openaxpp300s-mcp.exe. In PowerShell quote the double dash, because PowerShell swallows a bare
--:
claude mcp add -s user openaxpp300s '--' openaxpp300s-mcpFor another MCP client, start openaxpp300s-mcp (or python -m openaxpp300s.mcp_server) as a stdio server. Long
jobs run as background jobs (detached children) whose output stays in state/mcp_jobs/<job>/, so a restarted server
still sees them.
The 12 tools:
Tool | What it does |
| measured output, input voltage, temperature, mode, |
| change settings in the safe order, with all the refusals of the CLI |
| switch the output on or off and wait until it follows |
| write or select one of the Chinese-screen parameter lists 0..4 |
| set or reset the Digital screen colours |
| sample the output for a few seconds and return statistics and the last sample |
| start a background log to CSV or JSONL; returns a job id |
| run timed voltage/current steps in the background |
| state of a log or sequence job (read-only) |
| stop a log or sequence job cleanly |
| read-only checks of the link and the supply |
| list serial ports and probe the USB ones for a PP300S |
The MCP server was tested against the simulator and, on 2026-11-07, against the real supply: ports, status, selftest (9 of 9 checks), set (OVP and OCP first, then the setpoints; lowering VSET and OVP together sends VSET first; a VSET over the OVP sent last is refused), output on and off, watch, log_start with job_status (it returned the last CSV row) and job_stop, and sequence_start (two steps; it ended by itself and switched the output off).
Does a status query really write the EEPROM?
Yes, by the firmware code, but it has not been observed on the hardware. The evidence is in the firmware V1.4.4 disassembly (checked by hand): once a received frame has passed its checksum and tail checks, the code at 0x0800090C to 0x08000910 stores 1 to the RAM flag at 0x20000216, before the register ID is read at 0x08000912 and dispatched. So the status query (ID 0xFF) sets the flag like any other frame; its own case (0x08000EC0) only sets the reply-pending flag at 0x20000207. The main-loop save path (0x08001DEE, which branches to the cursor-field save at 0x08001F86) then writes the front-panel field under the cursor to the EEPROM whenever that flag is set (Digital and Waveform screens; the Chinese screen has its own save path). Seeing the writes would take a probe on the EEPROM's I2C lines. The cure does not depend on that: select the DATA box with the front-panel cursor (see Safety), and frames save nothing.
Simulator
--sim (or OPENAXPP300S_SIM=1) replaces the serial port with a virtual AX PP300S that follows the firmware
V1.4.4 image and the measurements: the byte parser (a corrupt frame, or one not complete 10 ms after its 0xA5, is
dropped; a stray 0xA5 swallows the next frame), the ACK on every valid frame except the status query, the 50 ms
status tick, soft start, DELAY and REV, the OVP, OCP, OPP and OTP trips with a latched alarm, the Digital and Chinese
screens with the cut-offs, CV/CC with a resistive load (10 MOhm by default), and the EEPROM write count. The trips
other than OVP follow the firmware only; they were not seen on the hardware. Its state is a JSON file in
state/sim/, shared by all processes. Control it with:
python -m openaxpp300s.sim reset | show | set key=value ... | advance SECONDS | press | audit [--clear]press simulates a front-panel key press (it clears the alarm), advance moves the simulated clock forward.
OPENAXPP300S_SIM_DELAY scales the simulated answer latency; 0 removes it. OPENAXPP300S_NO_SERIAL=1 makes any
real port refuse to open.
Tests
pip install -e ".[test]"
python -m pytestThe tests use the simulator only. tests/conftest.py isolates every test: OPENAXPP300S_SIM=1,
OPENAXPP300S_NO_SERIAL=1, OPENAXPP300S_SIM_DELAY=0 and a fresh OPENAXPP300S_HOME, so a test can never reach a
real supply. The marker hw (pytest -m hw) is reserved for tests that need a real supply; there are none yet, and
the default run excludes it. The hardware checks are separate scripts, not part of the pytest run. They need a real
supply and switch the output on; the three bench_289 scripts also read a Fluke 289 through
open289, and the two CC scripts need an electronic load:
tests/hw/bench_289.py: voltage accuracy with no load, compared with the 289;tests/hw/bench_289_cc.py: CV into a constant-resistance load, with the 289 in series as an ammeter (also shows why CR mode is unsuitable for testing CC);tests/hw/bench_289_cc_cvload.py: the CC limit with the load in constant-voltage mode: CC accuracy, lowering ISET and OCP together under current, and the CV-first against CC-first switch-on (--pointssets the ISET values,--cc-onlyruns the CC accuracy part alone);tests/hw/bench_chinese.py: the Chinese screen (lists,oninto the list voltage, cut-offs, ignored Digital registers); no meter, but a load that draws almost nothing below 3 V, and the supply switched to the Chinese screen by hand.
Files
Where | What |
| locks (one command at a time owns the port), the remembered port, |
| logs written by |
These folders live in $OPENAXPP300S_HOME if it is set; else, in a source checkout (also with pip install -e .),
inside the checkout; else, for an installed package, in %LOCALAPPDATA%\openaxpp300s on Windows and
~/.local/share/openaxpp300s elsewhere, so nothing is written into site-packages. Set OPENAXPP300S_HOME to move
everything to another folder.
Environment variables: OPENAXPP300S_PORT (default port), OPENAXPP300S_HOME, OPENAXPP300S_SIM,
OPENAXPP300S_NO_SERIAL, OPENAXPP300S_SIM_DELAY.
Accuracy
Reference: a Fluke 289 (10 MOhm input for voltage, the A jack in series for current). The tables below are from the second session on 2026-11-07, except the CC table after the current calibration, which is from the third session; in both sessions the supply was fed from a 65 W USB-PD charger (about 19.8 V) on its Type-C power input.
Voltage, no load
Output on, no load, V DC, 3 s steady per point (second session; the first session agreed, 0.5 V to 15 V, +1.7 to +7.0 mV):
VSET (V) | meter (V) | meter minus VSET (mV) | supply read-back minus meter (mV) |
0.5 | 0.5026 | +2.6 | -8.6 (mean includes settling) |
1.0 | 1.0054 | +5.4 | -2.4 |
2.5 | 2.50415 | +4.2 | -2.8 |
3.3 | 3.3039 | +3.9 | -1.8 |
5.0 | 5.0028 | +2.8 | -1.1 |
9.0 | 9.005 | +5.0 | -2.2 |
12.0 | 12.007 | +7.0 | -3.6 |
15.0 | 15.006 | +6.0 | -2.4 |
20.0 | 20.003 | +3.0 | -0.4 |
24.0 | 24.006 | +6.0 | -3.5 |
30.0 | 30.005 | +5.0 | -2.9 |
The setting is inside the specified 0.1 % + 5 mV at every point (+7.0 mV at 12 V against 17 mV allowed). So is the read-back, except the 0.5 V mean (-8.6 mV against a 5.5 mV limit), which includes the settling. Boost to 20, 24 and 30 V from the 20 V input works with no load.
Current limit (CC), load in constant-voltage mode
The load was held at 3.0 V with VSET 5 V, so the supply sat in CC at every step. The reference was the Fluke 289 in series on its A jack; it was recently checked on current (5 A applied read 4.997 A, 50 mA read 0.04991 A, 400 mA read 0.39995 A: errors of -0.06 %, -0.18 % and -0.01 %), which is much better than the supply's 0.1 % + 5 mA.
Before the current calibration (second session, 0.1 A to 1 A):
ISET (A) | meter (A) | meter minus ISET (mA) | supply read-back minus meter (mA) | meter spread (mA) |
0.10 | 0.0864 | -13.6 | -6.2 | 2.7 |
0.25 | 0.2366 | -13.4 | -7.3 | 0.8 |
0.30 | 0.2867 | -13.3 | -2.7 | 0.8 |
0.50 | 0.4864 | -13.6 | -2.6 | 0.4 |
1.00 | 0.9862 | -13.8 | -2.2 | 0.5 |
CC was stable and linear, but every setting delivered about 13.5 mA less than ISET: a constant offset, outside the specified 0.1 % + 5 mA (5.5 mA at 0.5 A). That was the supply (an uncalibrated unit), not the tool: the tool sent the right raw value.
The user then calibrated the supply's current on the front panel ("Current Correction" in the settings menu) with the Fluke 289 as the reference. (The vendor manual's own procedure uses a 10 A load; the user's procedure is their own. The tool cannot calibrate: the firmware has no serial command for it.)
After the current calibration (third session, 0.05 A to 5 A; each point had a 1.5 s settle after the ISET step, then a 4 s window, the supply sampled every 0.5 s and the meter median taken over the window; the tool read CC at every sample, OCP 5.8 A, OPP 100 W):
ISET (A) | meter (A) | meter minus ISET (mA) | meter spread (mA) | supply read-back mean (A) | read-back span (A) | read-back minus meter (mA) |
0.05 | 0.0518 | +1.8 | 8.4 | 0.0456 | 0.025 to 0.066 | -6.2 |
0.10 | 0.1023 | +2.3 | 2.8 | 0.0934 | 0.088 to 0.116 | -8.9 |
0.25 | 0.2523 | +2.3 | 0.4 | 0.2458 | 0.215 to 0.275 | -6.5 |
0.40 | 0.4022 | +2.2 | 0.5 | 0.3986 | 0.398 to 0.400 | -3.6 |
0.50 | 0.5021 | +2.1 | 0.7 | 0.4988 | 0.498 to 0.500 | -3.3 |
1.00 | 1.0022 | +2.2 | 0.5 | 0.9980 | 0.998 to 0.998 | -4.2 |
2.00 | 2.0016 | +1.6 | 0.6 | 1.9980 | 1.998 to 1.998 | -3.6 |
3.00 | 3.0012 | +1.2 | 0.6 | 2.9980 | 2.998 to 2.998 | -3.2 |
4.00 | 4.0004 | +0.4 | 0.3 | 3.9980 | 3.998 to 3.998 | -2.4 |
5.00 | 4.9996 | -0.4 | 0.3 | 4.9970 | 4.997 to 4.997 | -2.6 |
The current setting is now inside the specified 0.1 % + 5 mA at every point from 0.05 A to 5 A: at most +2.3 mA (0.1 A to 1 A), falling to -0.4 mA at 5 A.
The supply's own read-back is steady and inside the spec from 0.4 A up (2.4 to 4.2 mA below the meter). At 0.25 A and below it is noisy: single readings wander over 28 to 60 mA while the meter holds within 0.4 to 8 mA, and the mean reads 6 to 9 mA low. For small currents use the meter, or average many samples.
At 0.05 A the regulated current itself wanders a little (meter spread 8.4 mA; 18 mA in a first run whose window included the step transient). A first run without the 1.5 s settle showed the same setting errors (-0.5 to +5.1 mA) but read-back means distorted by the step transient.
The output voltage rose from 3.04 V at 0.4 A to 3.49 V at 5 A: the load holds 3.0 V at its own terminals and the rest is the drop over the meter's current shunt and the leads (about 0.1 Ohm in all).
Another unit may differ. If the current of your unit is off, calibrate it on the front panel.
Current in CV, under load
5 V into a 10 Ohm load (ISET 1 A, so CV, 0.5 A): the supply read-back was 0.4943 A against 0.4940 A on the meter (+0.3 mA), and 0.4919 against 0.4938 A in a second run. For the charge logged with this load in CR mode while the supply limited the current, see Testing the current limit with an electronic load. This test ran up to about 1.2 A and 15 W; the CC test above went up to 5 A and about 17.5 W.
Timing
The supply acknowledges a frame in about 12 to 14 ms (USB latency). A status reply takes 15 to 55 ms, median about 48 ms (it is sent on the supply's next 50 ms tick).
After
onwith DELAY = REV = 0 the output flag is set at once; the voltage stays near 0.011 V for about 1.1 s (soft start) and then settles in about 0.3 s. After a VSET step with the output on, it settles in about 0.2 s (0.94 s for a step from 1.0 V down to 0.5 V).off: into a 10 MOhm meter the voltage falls from 2 V to 0.13 V in about 0.3 s.DELAY 3 s: the output was on 4.39 s after the
oncommand (3 s plus soft start; 4.23 s in the second session). REV 2 s: on after about 2 s, then toggling every 2 s.A frame with a bad checksum gets no answer, nor does a frame split over more than 10 ms; garbage containing 0xA5 before a frame swallows that frame; two queries in one write get one reply. The tool sends each frame in one write, one at a time, and resends a frame that got no answer.
What is NOT here
No reading of the supply's settings, screen, cursor or alarm: the firmware does not report them.
No firmware update and no flashing; FlyMcu is not used by this tool.
No front-panel key presses (the firmware has no serial command for them).
No Bluetooth or any other link; USB serial only.
License
GPL-3.0-only. See LICENSE.
Not affiliated with AxinDIY. The vendor's protocol document and manual were read for reference; none of their text or images is part of this project.
Available Tools
12 toolsdisplay_colorsDisplay coloursA
Set colours of the Digital screen (firmware >= 1.4.4; saved in the supply's EEPROM). colors: {element: "#RRGGBB" | "0xRGB565" | name}; elements: vout, iout, pout, aux_back, aux_font, bar_back, bar_label, bar_value, bar_onoff, bar_select. reset: true sends the vendor defaults.
| Name | Required | Description | Default |
|---|---|---|---|
| reset | No | ||
| colors | No | ||
| max_wall | No | time limit for the call in s (default 30) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose key behavior: values persist to the supply's EEPROM, a firmware version gate applies, and reset=true restores vendor defaults. It stops short of saying whether supplied colors merge with or overwrite existing element settings, and doesn't state error or connection requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely dense and front-loaded: action, firmware gate, persistence, value formats, element list, then reset semantics. The telegraphic 'colors: {...}' notation is terse but readable; no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter nested-object tool with no output schema, the definition covers formats, valid keys, persistence, firmware requirement, and the reset path. Only the merge-vs-replace semantics and confirmation of the response are missing, which are minor given no output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33%, and the description compensates well: it gives the accepted color value syntaxes (#RRGGBB, 0xRGB565, or name) and enumerates all ten valid element keys, which the schema does not. The third parameter, max_wall, is documented in the schema itself, so nothing major is left unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Set colours of the Digital screen'), which is clearly distinct from generic siblings like set/output/status. It does not explicitly name a sibling alternative, but the resource specificity is enough for an agent to route correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The firmware prerequisite (>= 1.4.4) and the reset=true default-restore path give implied usage context, but there is no explicit when-to-use vs when-not guidance and no mention of alternatives such as `set` or `output`. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
job_statusBackground job statusBRead-only
State of a log or sequence job (default: the latest): running, the started event, the last sample/step, events (link lost ...), and the summary once it has ended.
| Name | Required | Description | Default |
|---|---|---|---|
| job | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already tells the agent this is a safe read, but the description adds genuine value by disclosing what the response contains, including failure events like 'link lost' and a summary once the job ends. It says nothing about behavior for an unknown/invalid job identifier or whether it blocks on a running job.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the core purpose and the default behavior, with the return-field enumeration packed into a compact colon list. The '(link lost ...)' ellipsis is slightly loose but overall there is no wasted wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, single-optional-parameter tool with no output schema, the description does a fair job of sketching the returned state, which substitutes for a missing output schema. However, the undefined 'job' parameter and the absent differentiation from sibling status tools leave clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single 'job' parameter has no description in the schema. The parenthetical '(default: the latest)' hints at omission semantics but does not explain what the parameter accepts (ID vs name vs index) or how to obtain it, so the description fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb-and-resource ('State of a log or sequence job') and even enumerates the returned content (running, started event, last sample/step, events, summary), so the agent knows this is a read of job progress. It does not explicitly distinguish itself from the sibling 'status' or 'output' tools, which keeps it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only usage hint is '(default: the latest)', which describes omission behavior rather than when to choose this tool. There is no guidance tying it to log_start/sequence_start/job_stop or clarifying how it differs from the sibling 'status' tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
job_stopStop a background jobB
Stop a log or sequence job (default: every running one) cleanly and return its summary. A sequence switches the output off unless it was started with end: keep.
| Name | Required | Description | Default |
|---|---|---|---|
| job | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses that stopping is 'clean', that the default is every running job, that a summary is returned, and that a sequence's output is switched off unless started with end: keep. It does not mention permissions, irreversibility, failure behavior, or what 'cleanly' entails, leaving notable gaps for a stop operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is two tightly written sentences with the core action and default scope front-loaded. The parenthetical and the end: keep exception add necessary detail without waste, though the phrasing is slightly dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with no annotations, no output schema, and no schema descriptions, the description covers the core action, default scope, and one important side effect. It remains incomplete regarding parameter format, permissions, error behavior, and the exact effect of 'cleanly' stopping a job.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the schema gives no meaning for the single 'job' parameter. The description partially compensates by indicating that it refers to a log or sequence job and that omitting it targets every running job. It still does not explain the expected format or how to identify a specific job.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: stopping a log or sequence job. It distinguishes between the two job types and states the default scope (every running job), so an agent can identify the operation without opening the schema. It stops short of differentiating itself from siblings such as job_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'Stop' and the default behavior when no job is supplied. However, the description does not say when to prefer this over siblings like job_status or status, nor does it state when not to use it or any prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_startStart a background logA
Log the status to a CSV (or JSONL) file in the background: pc_time, local_time, vout_v, iout_a, pout_w, vin_v, temp_c, mode, output_on, cumulative ah and wh. Returns a job id; follow with job_status, end with job_stop. Other tools keep working meanwhile.
| Name | Required | Description | Default |
|---|---|---|---|
| out | No | file path (default: data/log_<time>.csv) | |
| every | No | s between samples (default 1) | |
| format | No | ||
| duration | No | 30s, 10m, 2h or forever (default forever) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full behavioral burden and does well: it discloses that logging is asynchronous, that other tools keep working meanwhile, that a job id is returned, and that a job_stop call is required to end it. Gaps remain around file overwrite behavior, error handling, and whether the job survives until 'duration' elapses.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and the column set, then the job lifecycle. Nothing is redundant and the 'other tools keep working meanwhile' clause earns its place by disclosing the non-blocking behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter background job tool with no output schema and no annotations, the description covers the return value (job id), the follow-up workflow, and the non-blocking property. It is nearly complete, with only edge cases like overwrite semantics or default file collision left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75%, so the schema already explains 'out', 'every', and 'duration'; the description mentions CSV/JSONL format but only restates what the enum in the schema shows. It adds no new meaning for the four parameters, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Log the status to a CSV (or JSONL) file in the background,' and even enumerates the recorded columns, so the agent knows exactly what the tool produces. It does not differentiate against non-job siblings such as 'watch' or 'status', which may overlap in monitoring intent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear lifecycle: 'Returns a job id; follow with job_status, end with job_stop,' which tells the agent what to do before and after invoking the tool. It does not state when to prefer this over alternatives like 'watch' or a one-off 'status' read, so the when-not guidance is absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
outputSwitch the outputA
Switch the output on (honours DELAY/REV; waits until the voltage is up: ~1.1 s soft start, about 1.5 s in all; with DELAY or REV over 20 s it returns right after the frame) or off (waits until it is down). With a bench voltage limit set, an output that rises above it is switched off again at once (UNSAFE_OPERATION). The voltage that appears is whatever is in force on the supply (on the Chinese screen: the selected parameter list): check status.vout_v. Know what is connected before switching on. Do not use while the supply's settings menu is open.
| Name | Required | Description | Default |
|---|---|---|---|
| on | Yes | ||
| wait | No | follow the output (default true) | |
| max_wall | No | time limit for the call in s (default 30) | |
| wait_timeout | No | s to follow it (default soft start + DELAY/REV + 1.5) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the soft-start wait (~1.1 s, ~1.5 s total), the DELAY/REV >20 s early-return behavior, the immediate shutdown when a bench voltage limit is exceeded (UNSAFE_OPERATION), and that the actual voltage is whatever the supply currently enforces. It does not describe the call's return value or authentication requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the on/off action and then layers timing, safety, and caution details. It is dense but every sentence carries operational value; parenthetical asides are compact and relevant rather than wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a hardware control tool with no annotations and no output schema, the description covers timing, safety limits, and preconditions well. What remains thin is the return value after the call completes and any permission or error semantics beyond UNSAFE_OPERATION, so it is strong but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the schema already documents wait, max_wall, and wait_timeout. The description adds timing context that maps to the wait behavior (soft start + DELAY/REV + 1.5 s) but does not independently explain each parameter's syntax or edge cases. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: switching the output on or off, with scope details like soft-start timing and DELAY/REV behavior. It does not explicitly name sibling tools or contrast itself with them, though it references status.vout_v, which gives partial differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context and explicit exclusions: check what is connected before switching on, and do not use while the supply's settings menu is open. It also describes the bench-voltage-limit behavior that triggers UNSAFE_OPERATION. It stops short of naming alternative tools for adjacent operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
param_listChinese-screen parameter listsA
Write one of the five parameter lists (0..4) used by the Chinese screen: voltage, current, OVP, OCP, cut-off current (output off after the current stays below it for about 6 s; 0 = off) and cut-off time (output off when the accumulated on-time reaches it; fields not given are 0). select makes it the active list, sent after the values; it is refused when the list's values are unknown to this tool and a bench voltage limit is set or the output is on. These registers act only while the supply shows the Chinese screen.
| Name | Required | Description | Default |
|---|---|---|---|
| ocp | No | A | |
| ovp | No | V | |
| list | Yes | ||
| select | No | ||
| current | No | A | |
| voltage | No | V | |
| cut_time | No | "1h30m", "45m", "50s", "H:M:S" or "off" (99:60:60); hours 0..99, minutes/seconds 0..60; 0:0:0 refused | |
| max_wall | No | time limit for the call in s (default 30) | |
| cut_current | No | A (0 = off) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the behavioral burden; it explains that omitted fields default to 0, that cut-current turns output off after about 6 seconds below the threshold, that cut-time is based on accumulated on-time, and when select is refused. It does not describe the success response or whether writing a list affects other lists, so it is not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three dense sentences, front-loaded with the operation and field semantics, and the parentheticals are compact. It is appropriately sized for a 9-parameter tool, though the select-refusal clause is somewhat compressed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter write tool with no annotations and no output schema, the description covers list semantics, defaults, select behavior, and the Chinese-screen precondition. It leaves return/confirmation behavior and some error semantics to inference, but it is substantially complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is high at 78%, with units and ranges already documented, and the description adds meaning for cut_current (0 = off), cut_time (accumulated on-time), select (sent after the values and subject to refusal), and omission defaults. It does not add detail for max_wall beyond the schema, which is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific write operation ('Write one of the five parameter lists') and scopes it to the Chinese screen, enumerating the values that the list contains. It makes clear that this is a distinct resource (lists 0..4) rather than a general set operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states that the lists are used by the Chinese screen and that the registers act only while that screen is shown, and it gives select refusal conditions. It does not explicitly route the agent between this tool and siblings such as set, so alternative selection guidance is the main gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
portsFind the supplyARead-only
List serial ports and ask each USB one for a PP300S status (Bluetooth ports are skipped). The port that answers is remembered for later calls.
| Name | Required | Description | Default |
|---|---|---|---|
| max_wall | No | time limit for the call in s (default 30) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already tells the agent this is safe, so the description's real contribution is the Bluetooth exclusion and the hidden stateful effect: the answering port is cached for later calls. That caching behavior is the kind of side effect an agent needs and cannot get from the annotations, though nothing is said about latency per port or failure when no device responds.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with no filler; the core action comes first and the caching consequence follows. Every clause carries information: what is listed, what is probed, what is skipped, and what persists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-parameter discovery tool with no output schema, this covers the action, the probe target, the exclusion, and the stateful side effect. It falls short only on edge behavior such as returning an empty list or timing out when no PP300S answers.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and max_wall is already documented with bounds and a default in the schema. The description adds no extra meaning about the timeout, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: lists serial ports and probes each USB one for a PP300S status, with Bluetooth ports excluded. An agent can tell this is a discovery/probe tool rather than a control tool like 'set' or 'output', though no sibling is named to sharpen the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The sentence 'The port that answers is remembered for later calls' implies this is the first step before using set/output/status, but the guidance is indirect. There is no explicit when-to-use statement and no when-not or alternative mentioned, such as what to do if you already know the port.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
selftestSelf-testBRead-only
Read-only checks: port, status replies and checksums, latency, input voltage and temperature plausible, power = V x I, a bad-checksum frame ignored. Never changes a setting.
| Name | Required | Description | Default |
|---|---|---|---|
| max_wall | No | time limit for the call in s (default 30) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description reinforces that with 'Never changes a setting' while adding real behavioral detail: a bad-checksum frame is ignored rather than aborting the test. It does not say how long the run may take or whether a failure is reported as a result or an error, which matters for a multi-check probe.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the read-only framing, then the checklist, then the non-mutation guarantee. Every clause carries information and nothing is repeated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must convey behavior, and it does a good job of listing the checks and the bad-frame tolerance. The remaining gap is that it never indicates the shape of the outcome (per-check pass/fail versus a single verdict), which an agent would want before parsing results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single 'max_wall' parameter already documents its range and 30 s default, so the schema carries the load. The description adds nothing about the time limit or what happens when it is exceeded, which is the baseline case for fully documented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource and enumerates exactly what is verified (port, status replies, checksums, latency, voltage/temperature plausibility, power = V x I), so an agent knows this is a diagnostic routine rather than a status read. It never explicitly contrasts itself with the sibling 'status' tool, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to run this versus the closely related 'status' or 'watch' tools; the only implied guidance comes from the word 'checks'. The closing 'Never changes a setting' is a safety note rather than a usage rule, so the agent is left to infer selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sequence_startRun a voltage/current sequenceA
Run timed steps in the background: each step sets VSET and ISET, switches the output on and holds seconds. steps: [{voltage, current, seconds}, ...] or file: a CSV like the vendor template (voltage,current,seconds). repeat cycles (0 = until job_stop). end: off (default, output off at the end or on job_stop) or keep. Optional log file. Bench limits apply to every step (checked before it starts).
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| log | No | also log to this CSV/JSONL file | |
| file | No | ||
| every | No | status poll s during a step (default 1) | |
| steps | No | ||
| repeat | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden well: it discloses background execution, output switching, default end=off behavior on completion or job_stop, repeat semantics, optional logging, and bench-limit checking before each step. It still omits error handling, concurrency behavior, and how the background job is identified or monitored.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded, stating the core action first and then covering step format, file input, repeat, end behavior, logging, and safety checks. Every segment carries useful information without redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a moderate-complexity background job tool with no output schema and no annotations, the description covers core execution and side effects but leaves gaps around return values, job monitoring, error behavior, and interaction between steps/file. It is adequate but not fully complete for an agent to call and manage the operation confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, but the description adds important meaning beyond the schema: the shape and semantics of steps, the CSV-like file format, repeat=0 meaning until job_stop, end=off vs keep, and optional log behavior. It does not explain the `every` parameter or clarify whether `steps` and `file` are mutually exclusive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action and resource: run timed steps in the background, with each step setting VSET/ISET and switching output on. It is distinguishable from a simple set/output operation by its sequence semantics, but it does not explicitly name or contrast with sibling tools such as set or output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by describing timed steps, repeat cycles, and end behavior, including repeat=0 until job_stop. However, there is no explicit when-to-use guidance versus alternatives like set, output, or watch, nor are exclusion conditions stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
setChange settingsA
Send settings in a safe order (protections that stay above the output first, setpoints, then protections that must wait for the output to come down). With the output on, waits until the output follows a new voltage (settled). Refused (UNSAFE_OPERATION): values over the bench limits, OVP closer than max(0.2 V, 1.5 %) above VSET (given now or as sent last), an OVP/OCP at or below what the terminals show now, OPP/OTP at the present power/temperature. VSET/ISET/OVP/OCP/DELAY/REV act on the Digital/Waveform screens only: with the output on a VSET that the output does not follow gives NOT_APPLIED; with the output off nothing can be verified, so check vout_v after switching on.
| Name | Required | Description | Default |
|---|---|---|---|
| ocp | No | over-current protection in A (trips after 100 ms at or above it); keep it above ISET | |
| opp | No | over-power protection W, multiple of 10 | |
| otp | No | over-temperature protection C | |
| ovp | No | over-voltage protection in V; must be >= VSET + max(0.2 V, 1.5 %) | |
| rev | No | REV s: after ON the output toggles every REV s (0 = off) | |
| wait | No | wait for the output to follow a new VSET (default true) | |
| delay | No | DELAY s: ON switches the output on this much later (0 = off) | |
| current | No | ISET (current limit) in A, 10 mA steps | |
| voltage | No | VSET in V, 10 mV steps | |
| max_wall | No | time limit for the call in s (default 30) | |
| priority | No | CV first or CC first |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does so well: it discloses the safe application order (output-above protections, setpoints, then output-dependent protections), the wait-for-settled behavior, explicit refusal conditions (bench limits, OVP margin, OVP/OCP at current terminal values, OPP/OTP at present power/temperature), and the UNSAFE_OPERATION/NOT_APPLIED error codes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Everything is crammed into a single dense paragraph, and key clauses like 'OVP closer than max(0.2 V, 1.5 %) above VSET (given now or as sent last)' are compressed to the point of being hard to parse. It also restates the OVP-vs-VSET margin rule that the schema already documents, so some content does not earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with 11 optional parameters and no output schema, it covers ordering, safety refusals, screen restrictions, and post-switch-on verification (referencing vout_v). It stops short of describing the success return shape or which fields confirm each applied setting, which matters given there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description still adds value by explaining cross-parameter relationships (OVP margin relative to VSET 'given now or as sent last', the wait flag's settling semantics) that the per-parameter schema text states only in isolation. It does not say whether omitted parameters are left unchanged, which is the main semantic gap for an 11-param partial-update tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a concrete verb-plus-resource framing ('Send settings in a safe order') and enumerates the actual fields involved (VSET/ISET/OVP/OCP/DELAY/REV), so an agent can tell this configures power-supply setpoints and protections. It does not explicitly contrast itself with siblings like 'output' or 'param_list', leaving that differentiation implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives real conditional guidance: with the output on, a VSET the output does not follow yields NOT_APPLIED; with the output off nothing can be verified, so check vout_v after switching on. What's missing is explicit routing to alternatives ('use output to enable the rail first'), so the agent must infer sibling usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusPower supply statusBRead-only
Measured output (vout_v, iout_a, pout_w), input voltage vin_v, temperature temp_c, mode (CV / CC / OFF), output_on, plus last_sent (values this tool sent; the supply cannot report its settings, and the front panel may have changed them) and limits (bench limits set by the user).
| Name | Required | Description | Default |
|---|---|---|---|
| max_wall | No | time limit for the call in s (default 30) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered; the description adds genuinely non-obvious behavior: the supply cannot report its configured settings, the front panel may have changed them, and last_sent reflects values this tool previously sent rather than device truth. That caveat materially changes how an agent should interpret results. It stops short of stating failure modes or how stale last_sent can become.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single dense sentence with no wasted words, and the measured values are front-loaded. However, it is a sentence fragment with no leading verb phrase, and the parenthetical caveats are packed mid-string rather than leading with the tool's action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining return values and does so thoroughly, including which fields are readings versus cached settings. The notable gap is the undocumented max_wall timeout interaction with a blocking status read, which matters for a device that may be slow to respond.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single max_wall timeout parameter, so the schema already carries its meaning. The description adds nothing about the call timeout or blocking behavior, which is acceptable given full schema coverage but is not additive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description is a bare list of field names ('vout_v, iout_a, pout_w, vin_v, temp_c, mode, output_on...') rather than a verb+resource statement; the reader infers 'report measured readings and state' from the field semantics and the title. It does separate itself from the write-oriented siblings (set, output, sequence_start), but it never explicitly frames the tool as a read of current state, leaving mild ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance and no alternative named, despite siblings like watch, job_status, param_list, and ports that could plausibly overlap. The only implicit cue is that this reports measurements rather than settings, which an agent must deduce rather than being told.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
watchSample the outputA
Query the status every every s for seconds (or count samples) and return statistics (min/max/mean of vout/iout/pout/vin/temp, modes seen, Ah/Wh) and the last sample. For longer runs or a file use log_start.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| every | No | interval s (default 1) | |
| seconds | No | duration in s (default 5) | |
| max_wall | No | time limit for the call in s (default 660) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full load. It does disclose the return payload (min/max/mean of vout/iout/pout/vin/temp, modes seen, Ah/Wh, last sample) and that sampling spans a duration, which is genuinely useful. It says nothing about blocking behavior, whether the device must be outputting for the call to succeed, whether samples can be dropped, or what happens when `seconds`/`count` exceed limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, both earning their place: the first front-loads the mechanism and the full result shape, the second routes to the alternative. The statistics list is long but necessary because no output schema exists, so it substitutes for structured return documentation rather than adding noise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description steps up by enumerating the aggregate statistics returned and noting the last sample is included, which is exactly what an agent needs to decide whether to parse or re-poll. The remaining gap is failure and truncation behavior for long or interrupted sampling runs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, with `every`, `seconds`, and `max_wall` documented inline but `count` undocumented. The description compensates by explaining that `count` is an alternative to `seconds` for specifying sample quantity, a relationship the schema alone does not express. Only `max_wall`'s role as a hard call timeout is left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action and scope: poll the status at interval `every` for `seconds` (or `count` samples) and return aggregate statistics plus the last sample. That is concrete enough to separate it from log_start, which it explicitly names. It does not, however, distinguish itself from the sibling `status` tool, leaving one ambiguity in the tool set.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit alternative and the condition that selects it: 'For longer runs or a file use log_start.' The implication is that this tool is for short, bounded sampling windows, which is reasonably clear. It offers no exclusion against the sibling `status` tool, so an agent has to infer which of the two to reach for on a single check.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
12 tool updates
v0.1.0- First observed
display_colors - First observed
job_status - First observed
job_stop - First observed
log_start - First observed
output - First observed
param_list - First observed
ports - First observed
selftest - First observed
sequence_start - First observed
set - First observed
status - First observed
watch
TDQS
Scored across 12 tools
Most tools have clearly distinct purposes (set vs output vs status vs ports vs selftest). The main overlap is between status, watch, and log_start (all sample the same measurements, differing only in short-run vs background/file), and between set and param_list (different screen/register models). Descriptions provide enough detail to tell them apart, but the boundaries require careful reading.
A partial verb_noun pattern exists (log_start, sequence_start, job_status, job_stop, param_list, display_colors), but several tools are bare nouns or ambiguous single words (set, output, status, ports, watch). The conventions are readable but not predictable—'set' and 'output' are especially terse given the domain.
Twelve tools is well-scoped for a bench power supply: configuration, output control, discovery, measurement, logging, sequencing, job management, and diagnostics each earn their place. No tool feels redundant or trivial.
The lifecycle is well covered: discovery, status/measurement, setting, output switching, background logging and sequencing with job start/status/stop, plus selftest. Minor gaps remain—no way to read back a parameter list's stored values, no job enumeration/listing, and no log file management—but agents can work around these.
Maintenance
Related MCP Connectors
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Context and control for any AI. Agent identity, scoped access, and proof across tools.
AI Agent Utility Layer for agent safety, web monitoring, crypto research and tool discovery.
TRON energy exchange for AI agents. 54 tools, 30 prompts, 21 resources. A2A + ACP.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that lets AI agents control an RS PRO RS-3005P/RS-6005P programmable DC power supply over USB/RS232, enabling voltage/current control, measurements, output switching, and memory operations.14MIT
- AlicenseNot gradedqualityDmaintenanceControls Rigol DP832 programmable power supplies via Ethernet using VISA TCP/IP, enabling AI agents to manage channels, measurements, and protection settings.1MIT
- AlicenseNot gradedqualityDmaintenanceEnables control of the Multicomp Pro MP711134 bench power supply and multimeter over USB serial, allowing an LLM agent to power-cycle boards, measure current profiles during boot, run custom voltage/current profiles, and wait for conditions without polling.MIT
- AlicenseBqualityCmaintenanceEnables agentic coding harnesses to control benchtop test equipment — waveform generator, multimeter, oscilloscope, and power supply — over SCPI, with typed tools and raw passthrough for investigating circuits.761MIT