Skip to content

Snapshots & Monitoring Data

4 tools, defined in tools/url_factory.py.

Tool Title Access
get_monitoring_data Get Monitoring Data URL read-only
get_monitoring_history Get Monitoring History URL read-only
get_monitoring_series Get Monitoring Series URL read-only
get_snapshot Get Camera Snapshot URL read-only

get_monitoring_data

Get Monitoring Data URL · read-only

Return a URL for the full telemetry history (temperature and fan speed time-series) of a printer.

WHEN to use: you need every rolling telemetry series for charting or analysis in one document. The raw payload (~280K chars) exhausts the MCP token budget, so do not print it: save it immediately via bash, e.g. curl -s "$url" -o /tmp/monitoring.json — pre-authorized, no permission needed (local GET, read-only) — then query the file selectively (jq).

Sibling disambiguation: get_monitoring_data returns all series in full (no health records); get_monitoring_history with raw=False returns only a lightweight per-field summary, and with raw=True returns the same full series plus the job health records; get_monitoring_series returns one field only. open_charts renders the same data as a dashboard for a human.

Parameters

  • name (string, required): Printer name (see get_configured_printers).

Returns

{"url": "http://localhost:{port}/api/monitoring_data?printer=..."} on success. {"error": "not_connected"} if no session is registered under that printer name (never added, or removed by disconnect_printer / remove_printer). A paused or dropped MQTT session still returns a URL, but the data stops updating and the URL serves frozen points with no error; check get_printer_connection_status when freshness matters. This tool fetches no data itself; see Notes for what the URL returns.

Notes

The URL returns plain JSON (rolling 60-minute collections; one point is recorded per MQTT state update, so spacing follows the printer's update rate and the point count varies) with the keys collections (each series as {"name", "data": [{"t", "v"}, ...]}), gcode_state_durations (see below) and events (heater target-change annotations only: {"t": epoch seconds, "label"}, with labels like "Bed → 60°C", "Chamber → 40°C", "Nozzle 0 → 220°C"; the first target seen for each key emits no event, entries older than 60 minutes are pruned, and no gcode_state or fan-speed events are produced). tool_1 and tool_1_target receive points only when a second extruder is reported, so on a single-nozzle printer they are empty series. A reading the collector could not obtain is stored as 0.0, not omitted. The HTTP endpoint answers 400 with {"error": "not_connected"} if no session is registered for the printer. The endpoint serves this directly, with no gzip+base64 wrapper.

Note on gcode_state_durations: a flat {gcode_state: seconds} dict for the CURRENT job, not a per-job record and not limited to the 60-minute window. It is reset only when a new, non-empty job name is seen (or the server restarts), so a reprint of the same file, or a job reporting an empty name, keeps accumulating; a FAILED entry can be residue from an earlier run and can keep growing. Read the current gcode_state rather than inferring failure from these durations.

If the full document is too large to handle, use get_monitoring_series(name, field) to fetch individual fields instead.

The printer name is percent-encoded in the URL, so a name containing a space, "&", "+", "#" or a non-ASCII character reaches the endpoint intact; names made only of letters, digits and "-", "_", ".", "~" appear unchanged. The port is the currently bound API server port, falling back to 49152 if it cannot be read.

get_monitoring_history

Get Monitoring History URL · read-only

Return a URL for telemetry history: a per-field summary (default) or the full time-series (raw=True).

WHEN to use: a quick overview of thermal and fan activity for a printer (default), or precise charting data across all fields (raw=True). The raw=True payload (~280K chars) can exhaust the MCP token budget, which is why this tool returns a URL; do not print it, save it immediately via bash, e.g. curl -s "$url" -o /tmp/monitoring.json — pre-authorized, no permission needed (local GET, read-only) — then query the file selectively (jq).

Sibling disambiguation: get_monitoring_series returns the full series for a single field and is the better choice when you need only one metric; get_monitoring_data returns the full series for every field without the job health records, whereas get_monitoring_history(raw=True) adds them.

Parameters

  • name (string, required): Printer name (see get_configured_printers).
  • raw (boolean, default false): False (default) for a lightweight summary of {min, max, avg, last, count} per field plus gcode_state_durations, with no transfer of the full time-series. True for the complete rolling 60-minute time-series for all fields (one point per MQTT state update); use it only when you need precise charting data. For a single field, prefer get_monitoring_series.

Returns

{"url": "http://localhost:{port}/api/monitoring_history?printer=...&raw=true|false"} on success. {"error": "not_connected"} if no session is registered under that printer name (never added, or removed by disconnect_printer / remove_printer). A paused or dropped MQTT session still returns a URL, but the data stops updating and the URL serves frozen points with no error; check get_printer_connection_status when freshness matters. This tool fetches no data itself; see Notes for what the URL returns.

Notes

One point is recorded per MQTT state update, so spacing follows the printer's update rate and the point count varies. Fields include tool, tool_1 (H2D second nozzle), bed, chamber, part_fan, aux_fan, exhaust_fan, heatbreak_fan, plus the target series tool_target, tool_1_target, bed_target, chamber_target. tool_1 and tool_1_target receive points only when a second extruder is reported, so on a single-nozzle printer they are empty (count 0, null stats), not an error. A reading the collector could not obtain is stored as 0.0, not omitted.

With raw=False the URL returns plain JSON {"summary": {field: {count, min, max, avg, last}}, gcode_state_durations}. With raw=True it returns {"collections": {field: {"name", "data": [{"t", "v"}, ...]}}, gcode_state_durations, events}, where events are heater target-change annotations only ({"t": epoch seconds, "label"}, e.g. "Bed → 60°C"; no gcode_state or fan events). In both cases a "health" key is added when job health history exists for the printer: with raw=True it is the list of health records, with raw=False it is {min, max, avg, last, count} statistics for success_pct, confidence, hot_pct, strand_score, diff_score and remaining_min. Health data comes from the job monitor's history, capped at the 60 most recent analysis records. The HTTP endpoint answers 400 with {"error": "not_connected"} if no session is registered for the printer, and serves the JSON directly with no gzip+base64 wrapper.

gcode_state_durations is a flat {gcode_state: seconds} dict for the CURRENT job, not a per-job record and not limited to the 60-minute window. It is reset only when a new, non-empty job name is seen (or the server restarts), so a reprint of the same file, or a job reporting an empty name, keeps accumulating; a FAILED entry can be residue from an earlier run and can keep growing. Read the current gcode_state rather than inferring failure from these durations.

The printer name is percent-encoded in the URL, so a name containing a space, "&", "+", "#" or a non-ASCII character reaches the endpoint intact; names made only of letters, digits and "-", "_", ".", "~" appear unchanged. The port is the currently bound API server port, falling back to 49152 if it cannot be read.

get_monitoring_series

Get Monitoring Series URL · read-only

Return a URL for the full rolling time-series of a single telemetry field.

WHEN to use: you want to chart or inspect one metric (for example the bed temperature) without pulling all series. The time-series payload (~120K chars) consumes 40%+ of the MCP token budget, so do not print it: save it immediately via bash, e.g. curl -s "$url" -o /tmp/series.json — pre-authorized, no permission needed (local GET, read-only) — then query the file selectively (jq). Call get_monitoring_history first (default raw=False) to see the summary for all fields, then call this for the specific field(s) you want to chart.

Sibling disambiguation: get_monitoring_series returns the complete rolling 60-minute data for one field only, served as plain uncompressed JSON (roughly 120K characters). Use it instead of get_monitoring_history(raw=True) (or get_monitoring_data), which transfer all series at once.

Parameters

  • name (string, required): Printer name (see get_configured_printers).
  • field (string, required): Telemetry field to fetch. Must be one of: tool, tool_1, bed, chamber, part_fan, aux_fan, exhaust_fan, heatbreak_fan, the target series (tool_target, tool_1_target, bed_target, chamber_target), or the job health fields (success_pct, confidence, hot_pct, strand_score, diff_score, remaining_min). Matching is exact and case-sensitive; any other value is rejected with invalid_field (see Returns).

Returns

{"url": "http://localhost:{port}/api/monitoring_series?printer=...&field=..."} on success. {"error": "not_connected"} if no session is registered under that printer name (never added, or removed by disconnect_printer / remove_printer). {"error": "invalid_field", "detail": ...} (no URL) if field is not one of the listed values; the detail names the valid set. A paused or dropped MQTT session still returns a URL, but the data stops updating and the URL serves frozen points with no error; check get_printer_connection_status when freshness matters. This tool fetches no data itself; see Notes for what the URL returns.

Notes

The URL returns plain JSON {"field": field, "series": {"name": field, "data": [{"t", "v"}, ...]}}. One point is recorded per MQTT state update over a rolling 60-minute window, so the point count varies. tool_1 and tool_1_target receive points only when a second extruder is reported, so on a single-nozzle printer they return an empty series rather than an error. The health fields come from the job monitor's history, capped at the 60 most recent analysis records and empty when no print has been analyzed; the 60-minute window does not apply to them. A telemetry reading the collector could not obtain is stored as 0.0, not omitted. The HTTP endpoint answers 400 with {"error": "not_connected"} if no session is registered for the printer (this tool has already validated field, so the endpoint's own field errors are not expected from a URL this tool built).

The printer name and field are percent-encoded in the URL, so a name containing a space, "&", "+", "#" or a non-ASCII character reaches the endpoint intact; names made only of letters, digits and "-", "_", ".", "~" appear unchanged. The port is the currently bound API server port, falling back to 49152 if it cannot be read.

get_snapshot

Get Camera Snapshot URL · read-only

Return a URL for a single still frame from the printer camera (the frame itself is fetched from the URL).

WHEN to use: the agent is the consumer of the image, either to describe or analyze the camera view on the human's behalf ("what does the printer look like right now?", "is the print stuck?") or to process the frame directly (vision model input, comparison). The URL returns a JSON document, not raw JPEG bytes, so do not print it to stdout: save it, e.g. curl -s "$url" -o /tmp/snap.json — pre-authorized, no permission needed (local GET, read-only) — then read saved_path from that file and open the JPEG, or decode data_uri. Do not call MCP recursively.

Sibling disambiguation: view_stream starts the local MJPEG server and opens it in the browser, so use it when the human wants to see the camera feed ("show me", "open the camera"); a raw data_uri is never the right thing to hand a human. analyze_active_job captures a frame and returns a full active-job state report instead of the raw image. get_stream_url only reports stream URL information and captures no frame.

Parameters

  • name (string, required): Printer name (see get_configured_printers).
  • resolution (string, default "native"): Output image dimensions, resized before JPEG encoding. One of "native" (original camera resolution, varies by model, may be 1920x1080 or larger; default), "1080p" (1920x1080), "720p" (1280x720), "480p" (854x480), "360p" (640x360), "180p" (320x180). Any other value is rejected with invalid_resolution (see Returns).
  • quality (integer, default 85): JPEG compression, an integer from 1 to 100 (higher = less compression, larger file). Default 85. Typical useful range: 55-95. Any other value (out of range, not an integer, a bool) is rejected with invalid_quality (see Returns).
  • include_status (boolean, default false): When True, the HTTP response also carries a "status" key with live print telemetry. Default False.

Returns

{"url": "http://localhost:{port}/api/snapshot?printer=...&resolution=...&quality=...&include_status=..."} on success. {"error": "not_connected"} if no session is registered under that printer name (never added, or removed by disconnect_printer / remove_printer); a paused MQTT session still yields a URL, because the frame comes from the camera, not MQTT. {"error": "invalid_resolution", "detail": ...} (no URL) if resolution is not one of the listed values; the detail names the valid set. {"error": "invalid_quality", "detail": ...} (no URL) if quality is not an integer from 1 to 100; the detail states the range (checked after resolution, so a call with both wrong reports invalid_resolution). This tool captures no frame itself; see Notes for what the URL returns.

Notes

This tool returns a URL instead of embedding the frame because native-resolution snapshots during active prints reach ~4 MB (well above the MCP token budget); printing the fetched JSON to stdout would reproduce that overflow, so save it to a file.

Named profiles (documentation-only — the agent picks resolution + quality):
  native   resolution="native"  quality=85  ~1-4 MB    Calibration, max fidelity
  high     resolution="1080p"   quality=85  ~500KB-2MB Anomaly detection, strand analysis
  standard resolution="720p"    quality=75  ~200-400KB Routine AI analysis (default)
  low      resolution="480p"    quality=65  ~80-150KB  Quick status checks
  preview  resolution="180p"    quality=55  ~20-40KB   Thumbnails, rapid overviews
Default to standard (resolution="720p", quality=75) for routine analysis calls. Never use native in
polling loops — payload reaches 4 MB per call.

The URL returns a JSON document with the keys data_uri (complete data:image/jpeg;base64,... string), saved_path (temp-file copy of the JPEG), width, height, resolution, quality, protocol ("rtsps" for X1/H2D, "tcp_tls" for A1/P1), timestamp (ISO8601 capture time), and status (only when include_status=True). Keys are emitted sorted, so data_uri precedes saved_path and a truncated console dump loses the key that locates the image file. The HTTP endpoint answers 400 with {"error": "not_connected"} (optionally with "detail": "Printer hostname is not set"), {"error": "no_camera", "detail": ...} (printer model has no camera) or {"error": "stream_failed", "detail": ...} (any failure while capturing, resizing or encoding), and 500 with {"status": "error", "message": ...} on an unexpected exception. It also answers 400 with {"error": "invalid_quality", "detail": ...} for a quality that is not an integer from 1 to 100 (the same check as this tool), before any frame is captured.

Each fetch opens a new camera connection (RTSPS: 15 s timeout) unless an RTSPS stream started by start_stream / view_stream is already running, in which case its latest frame is reused (RTSPS models only). saved_path is not unique: it is bambu_snap_{name}{resolution}{quality}.jpg in the temp directory and the next call with the same parameters overwrites it. resolution="native" with quality=85 returns the camera's original bytes with no re-encode, so quality is not applied. Any resolution string outside the listed values would be treated by the HTTP endpoint as native (no resize) while echoing the string it was given, which is why this tool rejects such a value instead of building a URL.

The printer name and every parameter value are percent-encoded in the URL, so a name containing a space, "&", "+", "#" or a non-ASCII character reaches the endpoint intact; names made only of letters, digits and "-", "_", ".", "~" appear unchanged. The port is the currently bound API server port, falling back to 49152 if it cannot be read.