Skip to content

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 (see get_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 (see get_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 (see get_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 (see get_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_error entry exists only when print_error != 0, and is listed first.
  • If a device_error is present, the FIRST device_hms entry is returned as reported and every later device_hms entry is relabelled severity="Historical", is_critical=False. If none is present, EVERY device_hms entry is relabelled Historical. Codes are never compared, and device_error entries 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_error before 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_hms codes 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 (see get_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_name is 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 (see get_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 (see get_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 (see get_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 (see get_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 (see get_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 (see get_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"}.