Printer State
11 tools, defined in tools/state.py.
| Tool | Title | Access |
|---|---|---|
get_ams_status |
Get AMS Status | read-only |
get_capabilities |
Get Printer Capabilities | read-only |
get_fan_speeds |
Get Fan Speeds | read-only |
get_hms_errors |
Get HMS Errors | read-only |
get_job_info |
Get Print Job Info | read-only |
get_print_progress |
Get Print Progress | read-only |
get_printer_info |
Get Printer Info | read-only |
get_printer_state |
Get Printer State | read-only |
get_spool_info |
Get Spool Info | read-only |
get_temperatures |
Get Temperatures | read-only |
get_wifi_signal |
Get Wi-Fi Signal | read-only |
get_ams_status
Get AMS Status · read-only
Return the status of all AMS units.
WHEN to use: check AMS health, such as humidity, heater and drying state, or the global AMS status, and how many AMS units are connected.
Sibling disambiguation: get_ams_status and get_ams_units return the identical
{ams_status, ams_count, units} payload from the same printer state; they differ only
in name, and get_ams_units carries the field reference for the units list. A unit
reports slot presence (tray_exists, one boolean per slot: four, or one on an AMS HT)
and its dryer (dryer, null on a unit that cannot dry), not per-slot filament: use
get_spool_info for filament type, color, and remaining percentage.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"ams_status": str, "ams_count": int, "units": [dict]}. Each unit includes
temperature, humidity, heater state, drying state, and tray-existence flags; ams_status
is the global AMS status string and ams_count the number of connected AMS units. Error
shape: {"error": "Printer '<name>' not connected"}.
Notes
humidity_index scale: 1=WET (alert, filament needs drying), 5=DRY (good, no action needed). Higher numbers mean DRIER — the scale is counterintuitive. Only values of 1 or 2 indicate a moisture problem. Value 5 = completely dry. Value 0 = sensor reading unavailable (do not treat as wet).
Values are the last telemetry received; they go stale, with no error, while the MQTT session is paused (pause_mqtt_session) or the connection has dropped.
get_capabilities
Get Printer Capabilities · read-only
Return the hardware capabilities dict for the printer.
WHEN to use: check what the printer supports (AMS, dual extruder, camera, chamber temperature control, detector and auto-recovery support) before choosing a tool or option.
Sibling disambiguation: get_capabilities returns the feature flags discovered for this
printer. get_printer_info returns the model, serial number, and firmware version, and
get_detector_settings returns the current detector settings rather than what is
supported.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
The serialized capabilities dict of boolean flags, for example has_ams,
has_dual_extruder, has_camera, has_lidar, has_air_filtration, has_chamber_temp, and the
has_*_support flags. Capabilities are discovered during the initial MQTT handshake and
telemetry analysis. Error shape: {"error": "Printer '<name>' not connected"}.
get_fan_speeds
Get Fan Speeds · read-only
Return the current fan speeds as percentages for all fans on the printer.
WHEN to use: check the part-cooling, aux, exhaust, or heatbreak fan speed. For the enhanced-cooling fan this reports the last value commanded through this server's current session, not a measured run state.
Sibling disambiguation: get_fan_speeds returns fan percentages only. get_climate
returns temperatures and chamber door state, and get_temperatures returns temperatures
only. set_fan_speed is the tool that changes a fan.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"part_cooling_pct", "aux_pct", "exhaust_pct", "heatbreak_pct",
"enhanced_cooling_pct"}, each a percentage. Fans reported: part_cooling, aux
(recirculation), exhaust (chamber), heatbreak, enhanced_cooling (Toolhead Enhanced
Cooling Fan, H2-series extension-tool only). Error shape:
{"error": "Printer '<name>' not connected"}.
Notes
enhanced_cooling_pct is NOT a measured speed — the printer publishes no run-state telemetry for this fan. It is the last target commanded through THIS server's current session (sticky): it persists unchanged across telemetry updates, reads 0 after a session start or restart and on printers with no extension-tool module, is zeroed when the extension tool leaves the MOUNTED state, and never reflects a command sent by another client. The other fan values are the last telemetry received and go stale, with no error, while the MQTT session is paused or the connection has dropped.
get_hms_errors
Get HMS Errors · read-only
Return the printer's HMS (Health Management System) errors, labelled active or Historical.
WHEN to use: decide whether the printer has a live hardware fault before submitting a job, or explain a failed or paused print.
Sibling disambiguation: get_hms_errors returns only the HMS error list and the raw
print_error code, with the active/historical rule already applied. get_printer_state
also carries the same hms_errors inside its full payload. get_pending_alerts
returns pending state-change alerts rather than the current error list.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"hms_errors": [dict], "print_error": int}. Each hms_errors entry is
{"code": str (e.g. "HMS_0300-0400-0002-000C"), "msg": str (human-readable
description), "module": str, "severity": str, "is_critical": bool, "type":
"device_hms" | "device_error" | "command_error", "url": str}; the code is a string,
not a number. A command_error is a command the printer refused in its reply (bpm
adds it; e.g. a filament load while the AMS dries, HMS_0500-C04F) and also carries
command, ams_id and timestamp; it is never relabelled and stays until that
command is sent again or accepted, so it can outlive its cause. A device_error
entry also carries actions: the buttons Bambu Studio shows for that print_error on
this printer, [{"id", "name", "label", "command"}]; command is resume,
done or abort (send with send_ams_control_command, RESUME with
resume_print=False), clean_print_error, assistant or close, and empty
for a button this server cannot send. The
list holds both the active entry and the Historical-labelled ones (see Notes), and is
empty only when the printer reports no HMS entries and print_error is 0. Filter on
severity != "Historical" (or is_critical) to see only the active fault.
print_error is the printer's numeric print error code (0 when none). Error shape:
{"error": "Printer '<name>' not connected"}.
Notes
Active vs. historical rule (applied by THIS SERVER, not reported by the printer):
- A
device_errorentry exists only when print_error != 0, and is listed first. - If a
device_erroris present, the FIRSTdevice_hmsentry is returned as reported and every laterdevice_hmsentry is relabelled severity="Historical", is_critical=False. If none is present, EVERYdevice_hmsentry is relabelled Historical. Codes are never compared, anddevice_errorentries are never relabelled. - "Historical" is a positional label, not a printer-reported cleared state. With
print_error == 0, every entry the printer sends is relabelled Historical. Do not read
it as proof the hardware is healthy: check print_error and the non-Historical
entries, and consider
clear_print_errorbefore submitting a new job. - gcode_state="FAILED" means the last job failed; it says nothing about whether the printer will accept a new one.
device_hmscodes follow HMS_XXXX-XXXX-XXXX-XXXX. The first segment carries the module byte (0x03=Mainboard, 0x05/0x12=AMS, 0x07=Toolhead, 0x0B=Webcam, 0x10=HMS) in its high byte and the severity mask in its low byte; the other segments are module-specific identifiers. Entries derived from print_error (type "device_error") have two segments: HMS_XXXX-XXXX.- Values are the last telemetry received; they go stale, with no error, while the MQTT session is paused (pause_mqtt_session) or the connection has dropped.
get_job_info
Get Print Job Info · read-only
Return the ActiveJobInfo for the current (or last) print job as a dict.
WHEN to use: you need the job's identity and detail (subtask name, gcode file, plate, stage code, layer counts, elapsed/remaining minutes), for example to locate its project file or to decode why a job is paused.
Sibling disambiguation: get_job_info returns the full ActiveJobInfo record, including
the job's identity fields. get_print_progress returns a compact progress summary and is
the one that carries gcode_state. get_printer_state bundles every state field in
one large response.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
The whole serialized ActiveJobInfo dict, uncompressed: subtask_name, gcode_file,
plate_num (-1 when unknown), plate_type, stage_id, stage_name, current_layer,
total_layers, print_percentage, elapsed_minutes, remaining_minutes, wall_start_time,
print_type, project_file_command, project_info_fetch_attempted, and project_info. While
a job runs, project_info.metadata carries thumbnail and topimg as full base64
PNG data URIs, so the payload can be very large; for project data prefer
get_current_job_project_info(include_images=False). Error shape:
{"error": "Printer '<name>' not connected"}.
Notes
Field semantics:
- stage_id: integer stage code.
stage_nameis the decoded label (bpm parseStage); read it rather than decoding the code yourself. 0 and -1 decode to ""; 1=Auto bed leveling, 2=Heatbed preheating, 3=Sweeping XY mech mode, 4=Changing filament, 5=M400 pause, 6=Filament runout pause, 7=Heating hotend, 8=Calibrating extrusion, 9=Scanning bed surface, 10=Inspecting first layer, 11=Identifying build plate, 12=Calibrating Micro Lidar, 13=Homing toolhead, 14=Cleaning nozzle tip, 15=Temp check, 16=Paused by user, 17=Front cover falling, 18=Lidar calibration (alt), 19=Calibrating flow, 20=Nozzle temp malfunction, 21=Bed temp malfunction, 22=Filament unloading, 23=Skip step pause, 24=Filament loading; 25-58 and 70-77 name further calibration, check, pause and AMS filament-change steps; 100=Printing; 255=Completed. An unlisted code decodes as "Stage [N]".
Empty result interpretation:
- Every field is empty or zeroed (subtask_name="", gcode_file="", print_percentage=0, stage_id=0; a -1 stage_id, when it appears, is the printer's own stg_cur) until this session's first status report. A just-connected, restarted or re-created session therefore reads empty even if the printer has run jobs; "no job since the printer's last power cycle" is one possible explanation, not a guarantee.
gcode_state is NOT a field of ActiveJobInfo and is not returned by this tool. Read gcode_state from get_print_progress() or get_printer_state() instead.
Shortcuts for agent efficiency:
- Current plate number: parse gcode_file path — pattern is /data/Metadata/plate_N.gcode where N is the plate number. Example: "/data/Metadata/plate_3.gcode" → plate 3. No extra tool call needed.
- Find the project file on the SD card: use get_3mf_entry_by_name(name, subtask_name
- ".gcode.3mf") to look it up by filename instead of scanning list_sdcard_files(). That call runs a LIVE FTPS listing of the SD card (it contacts the printer; it does not read a cache). On a miss, try subtask_name + ".3mf", the form bpm falls back to.
Values are the last telemetry received; they go stale, with no error, while the MQTT session is paused (pause_mqtt_session) or the connection has dropped.
get_print_progress
Get Print Progress · read-only
Return print progress: percentage complete, current/total layers, and time remaining.
WHEN to use: poll how far along a print is and whether the printer is idle, running, paused, or finished, without pulling the whole job record.
Sibling disambiguation: get_print_progress is the compact progress summary and the one
that returns gcode_state. get_job_info returns the full ActiveJobInfo (gcode file,
plate number, stage_id) but no gcode_state. get_printer_state bundles all state in one
large response.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"gcode_state", "print_percentage", "current_layer", "total_layers",
"elapsed_minutes", "remaining_minutes", "stage_name", "subtask_name",
"skipped_objects"}. Elapsed and remaining time are in minutes. When the printer is
connected but has no job record, the job-derived fields read 0 (or "" for stage_name and
subtask_name). Error shape: {"error": "Printer '<name>' not connected"}.
Notes
Field semantics:
- gcode_state: string — "IDLE", "PREPARE", "RUNNING", "PAUSE", "FINISH", "FAILED", "SLICING", "INIT". "FAILED" means the *last* job ended in failure; it says nothing about whether the printer will accept a new one. Check get_hms_errors() (print_error and non-Historical entries) and, if a fault error is lingering, clear_print_error(), before submitting a job.
- stage: this tool returns the decoded stage as the string
stage_name, not as a code. See get_job_info() for the code table (100=Printing, 255=Completed). - skipped_objects: list of identify_id integers skipped in the current print job (objects skipped via skip_objects()). Empty list when no objects have been skipped or no print is active.
Values are the last telemetry received; they go stale, with no error, while the MQTT session is paused (pause_mqtt_session) or the connection has dropped.
get_printer_info
Get Printer Info · read-only
Return the printer model, serial number, and firmware version.
WHEN to use: identify which printer this is (model and serial) and which firmware it runs.
Sibling disambiguation: get_printer_info returns identity plus firmware in one call.
get_firmware_version returns the firmware versions alone, and get_capabilities
returns what the hardware supports rather than which unit it is.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"model": str, "serial": str, "firmware_version": str, "ams_firmware_version": str}.
model is the printer model enum name, or "UNKNOWN" when the model is not set.
firmware_version and ams_firmware_version are strings and read "" until the printer's
version/module handshake reply arrives; ams_firmware_version stays "" when no module
reports an AMS version. Neither is ever None. Error shape:
{"error": "Printer '<name>' not connected"}.
get_printer_state
Get Printer State · read-only
Return the full live BambuState for the named printer as a dict.
WHEN to use: you need many state fields at once (extruders, AMS units, spools, climate, HMS errors, print progress) and one bundled response is cheaper than several calls.
Sibling disambiguation: get_printer_state bundles all printer state into one large
response. For routine queries prefer the targeted tools, which are smaller and faster:
get_temperatures (nozzle, bed, and chamber temperatures), get_spool_info (active
spool and all AMS spools), get_job_info (current print job details),
get_nozzle_info (nozzle diameter, type, and tray state), get_print_progress
(print percentage, layer, and time remaining), get_ams_units (AMS unit and slot
details), get_hms_errors (active and historical HMS errors), get_fan_speeds (all
fan speeds as percentages), and get_climate (temperatures and chamber door state).
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
The serialized BambuState dict, with enum fields as their names, hms_errors passed
through the active/historical rule, extension_tool.mounted (bool, whether the
enhanced cooling fan is mounted) added, and recent_update (bool) added. Any payload
over 300 characters is returned as a gzip+base64 envelope instead:
{"compressed": True, "encoding": "gzip+base64", "original_size_bytes": int,
"compressed_size_bytes": int, "data": str}. Error shape: {"error": "Printer '<name>'
not connected"}.
Notes
recent_update: bool. True when BPM's watchdog considers the MQTT report stream live; False when the watchdog found no message for watchdog_timeout seconds (or none yet), asked the printer to re-announce its version/push info, and is waiting for that reply. Ordinary report messages only reset the watchdog's staleness clock while this is True; it flips back to True only when a fresh info/module reply arrives. An idle (non-printing) printer with a healthy report stream still reads recent_update=True. This field flags a stalled telemetry connection, not printer activity.
Decompress an envelope with:
import gzip, json, base64
data = json.loads(gzip.decompress(base64.b64decode(r["data"])))
If the compressed envelope itself exceeds the MCP response limit, fall back to
GET /api/printer?printer=<name>. That route returns a DIFFERENT, larger document (a
serialization of the whole BambuPrinter object, not this BambuState dict) and answers
HTTP 304 ("no data yet") while recent_update is False.
Incidental side effect: building the response records its size in ~/.bambu-mcp/response_size_tracker.json when it sets a new high-water mark, and may then rewrite MAX_MCP_OUTPUT_TOKENS in ~/.copilot/mcp-config.json. It does not touch the printer.
get_spool_info
Get Spool Info · read-only
Return the active spool and a list of all spools associated with the printer.
WHEN to use: find out which filament is loaded and in use, or list every spool with its type, color, remaining percentage, nozzle temperature range, and drying parameters.
Sibling disambiguation: get_spool_info is filament-centric (one dict per spool, plus
the active one). get_ams_units and get_ams_status return the same unit payload
(temperature, humidity, heater and drying state, tray-existence flags), not filament.
get_external_spool returns the external holder trays alone: 254, and also 255 on a
dual-nozzle printer.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"active_spool": dict | None, "spools": [dict]}. The active spool is the one in the
active AMS unit (ams_id equal to the state's active_ams_id) whose slot_id or id equals
the state's active_tray_id; the id is tried so a single-extruder printer's absolute tray
id reaches units after the first, and the external holders 254 and 255 are matched by
slot_id alone. It is None when nothing matches or no tray is active. The list has an
entry for every AMS slot the printer reports, empty ones included, plus the external
holder entries, so its length is not the number of physical spools; an entry with an empty type holds no filament. Per-spool keys:
id (0-23 for AMS trays, 254/255 for external holders), slot_id (slot within
the unit, or the holder id; -1 on a placeholder), ams_id (firmware unit id; -1 for
external), name, type, sub_brands, color, tray_info_idx, k, bed_temp,
nozzle_temp_min/max, drying_temp, drying_time, remaining_percent, state, total_length,
tray_weight, plus the added color_name and display_name. Error shape:
{"error": "Printer '<name>' not connected"}.
Notes
Field semantics:
- active_ams_id, active_tray_id: BambuState values used to select active_spool; this
tool does not return them (read them from
get_printer_state). - active_ams_id: internal chip_id of the AMS unit. 0 = first AMS unit (AMS 2 Pro); 128 = AMS HT unit (Bambu's internal ID for AMS HT). NOT the same as the 0-based unit_id used by get_ams_units() / load_filament().
- active_tray_id: -1 when no tray is active. On a single-extruder printer it is the printer's raw tray_now value (255 mapped to -1), an absolute tray id: AMS unit n slot s is 4n+s. On a dual-extruder printer it is the low byte of the active extruder's report, the slot inside the active unit: the debug log shows the H2D's AMS HT as 32768 (unit 128, slot 0), which reads as active_ams_id 128 with active_tray_id 0. That is why a spool is chosen by unit first (see Returns). 254 and 255 are the external spool holders (254 = the only holder on a single-nozzle printer, the LEFT holder on a dual-nozzle one; 255 = the RIGHT holder).
- Verification limit: the log shows tray_now only as 0, 1 and 255, so no absolute id above 3 (a second AMS unit, or an AMS HT as spool id 16) has been observed on a single-extruder printer; that path follows bpm's code and the spool numbering and is UNVERIFIED on hardware (loading filament to see one would be a printer write).
- Each spool dict: type (str), remaining_percent (0–100, or -1 when the tray reports no 'remain' value; always -1 for a reported external holder, 0 on the placeholder for an absent one), nozzle_temp_min/max (°C), drying_temp (°C), drying_time (hours).
- color: a CSS3 colour NAME when the spool's RGB matches one exactly (e.g. "red", "black", "white"), otherwise an 8-digit "#RRGGBBAA" string that includes alpha. It is not always a hex string, so handle both forms. An empty external holder reports tray_color "00000000", which resolves to "black".
- name (if present): Bambu Lab vendor-specific brand label (e.g. "Bambu PLA Basic"). Not present on third-party spools and not a reliable identifier. The true identity of a spool is color + tray_info_idx (base profile catalog code, e.g. "GFA00"). When name is absent, the vendor name can be derived from tray_info_idx: GFA00="Bambu PLA Basic", GFA01="Bambu PLA Matte", GFB00="Bambu ABS", GFB01="Bambu ASA".
- display_name: synthesized human-readable label always present in each spool dict. Rule: "{catalog or type} ({color_name})".
- color_name: nearest CSS3 color name for the spool color (e.g. "darkorange"). Derived from the color field with the alpha channel stripped; when color is already a name, color_name equals it. Use color_name for human-readable descriptions.
Values are the last telemetry received; they go stale, with no error, while the MQTT session is paused (pause_mqtt_session) or the connection has dropped.
get_temperatures
Get Temperatures · read-only
Return current and target temperatures for all nozzles, the bed, and chamber.
WHEN to use: check whether the nozzle(s), bed, or chamber have reached their target temperatures, for example before starting a print or while it heats.
Sibling disambiguation: get_temperatures returns temperatures only, in a fixed
nozzles/bed/chamber shape. get_climate returns temperatures and chamber door state.
get_fan_speeds returns fan percentages. get_printer_state bundles everything in one
large response.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"nozzles": [{"id", "temp", "target"}], "bed": {"temp", "target"},
"chamber": {"temp", "target"}}. For single-extruder printers the nozzles list has one
entry; for dual-extruder (H2D) printers it has two. Error shape:
{"error": "Printer '<name>' not connected"}.
Notes
Values are the last telemetry this server received, not a fresh read. They go stale,
with no error returned, while the MQTT session is paused (pause_mqtt_session) or
the connection has dropped. Check get_session_status /
get_printer_connection_status, or recent_update in get_printer_state, when
freshness matters.
get_wifi_signal
Get Wi-Fi Signal · read-only
Return the Wi-Fi signal strength for the printer in dBm.
WHEN to use: diagnose flaky telemetry or dropped MQTT messages by checking how strong the printer's Wi-Fi link is.
Sibling disambiguation: get_wifi_signal returns only the signal strength. The same
value is the wifi_signal_strength field of get_printer_state.
get_session_status and get_printer_connection_status report the MQTT session and
connection state, not radio signal.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).
Returns
{"wifi_signal": str}, the signal strength as the printer reports it. A stronger
(less negative) value indicates a better signal. Error shape:
{"error": "Printer '<name>' not connected"}.