Files
19 tools, defined in tools/files.py.
| Tool | Title | Access |
|---|---|---|
create_folder |
Create SD Card Folder | write |
delete_file |
Delete SD Card File | write, destructive |
download_file |
Download SD Card File | write, destructive |
get_3mf_entry_by_id |
Find 3MF Entry By Path | read-only |
get_3mf_entry_by_name |
Find 3MF Entry By Name | read-only |
get_all_project_info |
Get All Plate Info | read-only |
get_current_job_project_info |
Get Current Job Project Info | read-only |
get_file_info |
Get SD Card File Info | read-only |
get_plate_thumbnail |
Get Plate Thumbnail | read-only |
get_plate_topview |
Get Plate Top View | read-only |
get_project_info |
Get Project Plate Info | read-only |
list_sdcard_files |
List SD Card Files | read-only |
open_plate_layout |
Open Plate Layout Image | read-only |
open_plate_viewer |
Open Plate Viewer | read-only |
preview_ams_mapping |
Preview AMS Mapping | read-only |
print_file |
Start Print From SD Card | write, destructive |
refresh_sdcard |
Refresh SD Card Listing | read-only |
rename_sdcard_file |
Rename SD Card File | write |
upload_file |
Upload File To SD Card | write, destructive |
create_folder
Create SD Card Folder · write · needs user_permission=True
Create a directory on the printer's SD card.
WHEN to use: make a new folder on the printer's SD card, for example to organise uploads.
WRITE GUARD: creates a new directory on the printer's SD card over FTPS (an FTPS mkdir).
With user_permission False the tool changes nothing and returns the {"error": ...}
refusal naming that consequence.
Sibling disambiguation: create_folder makes an empty directory; upload_file puts a
file on the card, and delete_file (with a trailing /) removes a directory.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).path(string, required): Full path of the directory to create on the SD card.user_permission(boolean, defaultfalse): Must be True to execute. Default False.
Returns
{"success": True, "path": <path>, "contents": <refreshed SD card tree>} on
success; contents is the printer library's SD card listing taken after the
creation. It is null when that listing failed; the folder itself was created either
way, so the tool still returns success. Errors are {"error": str}:
the _permission_denied refusal when user_permission is False,
"Printer '<name>' not connected", or "Error creating folder: <exception>".
delete_file
Delete SD Card File · write, destructive · needs user_permission=True
Delete a file or folder from the printer's SD card.
WHEN to use: remove a file, or a whole folder, from the printer's SD card, for example to free space or clear out old jobs.
WRITE GUARD: permanently deletes the file from the printer's SD card; a path ending in
/ deletes the folder and everything inside it, recursively. With user_permission
False the tool changes nothing and returns the {"error": ...} refusal naming that
consequence.
Sibling disambiguation: delete_file removes the data from the card;
rename_sdcard_file only moves or renames a file, keeping its contents. create_folder
is the opposite operation for directories.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).remote_path(string, required): Full path on the SD card. A path ending in/is treated as a folder (delete_sdcard_folder, recursive); any other path is treated as a file (delete_sdcard_file).user_permission(boolean, defaultfalse): Must be True to execute. Default False.
Returns
{"success": True, "remote_path": <remote_path>, "contents": <SD card tree>} on
success; contents is the printer library's cached SD card tree with the deleted
entry removed (null if the cache is empty: never populated, or cleared by a listing the
library reported as failed). Errors are {"error": str}:
the _permission_denied refusal when user_permission is False,
"Printer '<name>' not connected", or "Error deleting file: <exception>".
download_file
Download SD Card File · write, destructive · needs user_permission=True
Download a file from the printer's SD card to the local filesystem.
WHEN to use: copy a file off the printer's SD card onto this host, for example to inspect or back up a .3mf.
WRITE GUARD: writes the downloaded file to local_path on this host, creating it or
truncating and overwriting whatever file is already there. The file is created or
truncated BEFORE the transfer begins, so a failed download (missing remote file, dropped
connection) leaves local_path emptied or partly written even though the tool returns
an error. local_path is not constrained to any directory on this tool. With
user_permission False the tool changes nothing and returns the {"error": ...}
refusal naming that consequence.
Sibling disambiguation: download_file copies from the printer to this host;
upload_file copies the other way, from this host to the printer's SD card.
list_sdcard_files and get_file_info only read the card's listing and do not
transfer any file.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).remote_path(string, required): Full path of the file on the printer's SD card.local_path(string, required): Destination path on this host.user_permission(boolean, defaultfalse): Must be True to execute. Default False.
Returns
{"success": True, "remote_path": <remote_path>, "local_path": <local_path>} on
success. Errors are {"error": str}: the _permission_denied refusal when
user_permission is False, "Printer '<name>' not connected", or
"Error downloading file: <exception>".
get_3mf_entry_by_id
Find 3MF Entry By Path · read-only
Search the SD card 3MF file tree for the entry with a given full path.
WHEN to use: you already have a full SD card path (for example from
list_sdcard_files) and need that entry's size and timestamp, or need to confirm it
is a .3mf on the card.
Sibling disambiguation: get_3mf_entry_by_id matches on the full SD card path;
get_3mf_entry_by_name matches on the filename alone. get_file_info does an
exact-path lookup over the full tree rather than the .3mf-only tree.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).target_id(string, required): Full SD card path as returned bylist_sdcard_files, for example"/cache/my_project.gcode.3mf"or"/model/part.3mf". Directory entries have a trailing slash:"/cache/". Matching is case-sensitive and exact.
Returns
{"entry": <node>} on success, where the node has id (full SD card path),
name, size (bytes), timestamp (epoch) and children (directories
only). Errors are {"error": str}: "Printer '<name>' not connected",
"Failed to retrieve SD card contents", "Not found: <target_id>" when no entry
matches, or "Error searching SD card: <exception>".
Notes
The search is a depth-first walk of the tree returned by get_sdcard_3mf_files(),
which runs a live FTPS listing and refreshes the printer library's cache before
filtering. That tree holds only directories and files whose path ends in .3mf.
get_3mf_entry_by_name
Find 3MF Entry By Name · read-only
Search the SD card 3MF file tree for the entry with a given filename.
WHEN to use: you know a .3mf filename but not its full SD card path, and need the path
(the id field) or the file's size and timestamp.
Sibling disambiguation: get_3mf_entry_by_name matches on the filename;
get_3mf_entry_by_id matches on the full SD card path. list_sdcard_files returns
the whole tree of every file, not just .3mf files.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).target_name(string, required): Filename only, not a full path, for example"my_project.gcode.3mf"or"part.3mf". Matching is case-sensitive and exact: no wildcards or partial matches.
Returns
{"entry": <node>} on success, where the node has id (full SD card path),
name, size (bytes), timestamp (epoch) and children (directories
only). Errors are {"error": str}: "Printer '<name>' not connected",
"Failed to retrieve SD card contents", "Not found: <target_name>" when no
entry matches, or "Error searching SD card: <exception>".
Notes
The search is a depth-first walk of the tree returned by get_sdcard_3mf_files(),
which runs a live FTPS listing and refreshes the printer library's cache before
filtering. That tree holds only directories and files whose path ends in .3mf.
The first match wins.
get_all_project_info
Get All Plate Info · read-only
Return 3MF metadata for every plate in a project file, in a single call.
WHEN to use: you need all plates of a multi-plate project at once, for example to survey the file or build a plate picker, instead of one round trip per plate.
Sibling disambiguation: get_all_project_info is the batch counterpart of
get_project_info, which returns one plate per call. Use get_plate_thumbnail or
get_plate_topview to fetch a single plate's image on demand.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.include_images(boolean, defaultfalse): Behaves exactly as inget_project_info. False (default) omits themetadata.topimgandmetadata.thumbnailfields per plate to keep the response small; True includes both data URIs for every plate (large).
Returns
A list of per-plate dicts on success, each shaped exactly like a single
get_project_info response, ordered by plate number. Errors are a dict, not a
list: {"error": "Printer '<name>' not connected"},
{"error": "Could not retrieve project info for '<file_path>'"}, or
{"error": "Error getting all project info: <exception>"}.
Notes
The tool fetches the .3mf's actual plate set. Plate numbers are not assumed to be
contiguous: a .3mf may contain a sparse set of plates (e.g. [1,5,6,7,8,12,15]) if
plates were deleted in the slicer, and only plates that genuinely exist are returned.
The plate set is bounded by the library's max_plates safety ceiling of 30: a plate
numbered above 30 is ignored and does not appear in the result. The .3mf may be
downloaded over FTPS once and its metadata cache written. Each plate's metadata
carries filament_extruders, physical_extruder_map and external_spool_trays
exactly as get_project_info describes them.
get_current_job_project_info
Get Current Job Project Info · read-only
Return 3MF project properties for the currently active print job.
WHEN to use: intended to find out which plate and parts the running (or just-finished) job
is printing without knowing the file path in advance. CURRENTLY IT ALWAYS RETURNS THE
no_active_job ERROR (see Returns), so use get_job_info plus
get_3mf_entry_by_name and get_project_info instead, or the HTTP route
GET /api/get_current_3mf_props.
Sibling disambiguation: get_current_job_project_info is meant to read the active job's
gcode_file and plate from the printer's live job state and return what get_project_info
returns for them. get_project_info needs you to supply the file path and plate;
get_job_info returns the job's own record (subtask name, gcode file, plate, layer
counts, times), not the project's metadata.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).include_images(boolean, defaultfalse): True embeds the base64 thumbnail and top-view data URIs in the response (large). Default False. Seeget_project_infofor the full field documentation.
Returns
In practice {"error": "no_active_job", "gcode_state": "", "note": "No print is
currently running or paused."} on every call, even mid-print: the tool reads
gcode_state from the job record, which has no such field, so the state is always
empty and the no-job branch is always taken. The other errors are {"error": str}:
"Printer '<name>' not connected" and "Error retrieving current job project info
for '<name>': <exception>". The intended (currently unreachable) success value is the
get_project_info result for the active job's file and plate plus a "gcode_state"
key.
Notes
Code defect for the owner: gcode_state should come from the printer state, the .3mf
should be resolved from the job's subtask_name (<subtask_name>.gcode.3mf) or
its project_info rather than from gcode_file (which is the printer-internal
/data/Metadata/plate_N.gcode path, not an SD card path), and a plate_num of -1
means unknown. When include_images=True the intended response carries raw base64
data URIs which may exceed the CLI inline display limit. The HTTP route
GET http://localhost:{api_port}/api/get_current_3mf_props?printer={name} returns the
active job's cached project info. Call kb_get('bambu-http-files') for full route
docs. Pre-authorized, no human permission needed.
get_file_info
Get SD Card File Info · read-only
Return metadata for a specific file on the printer's SD card.
WHEN to use: check whether one known file or folder exists on the SD card and read its size and timestamp, without pulling the whole tree into your context.
Sibling disambiguation: get_file_info returns the one entry for a path you already
know; list_sdcard_files returns a directory tree. get_3mf_entry_by_id does the
same exact-path lookup but only over the .3mf-only tree.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the file or folder (for example"/cache/part.gcode.3mf"). The first depth-first node whoseidornameequals this value exactly is returned, so a bare filename also matches. A folder'sidends with a trailing slash, so pass"/cache/"or the bare name"cache";"/cache"matches nothing.
Returns
{"file": <entry>} on success, where the entry carries the file attributes
id (full SD card path), name, size and timestamp; a directory entry
also carries children. Errors are {"error": str}:
"Printer '<name>' not connected", "Failed to retrieve SD card contents"
(the library reported the listing as failed, see Notes), "File not found:
<file_path>", or "Error getting file info: <exception>".
Notes
Every call retrieves the full SD card listing live over FTPS (which also repopulates
the printer library's cached tree) and then searches it. A listing that failed (a
timeout, a dropped connection, or a folder that could not be listed) gives the
Failed to retrieve error, so File not found means the file is not on the card.
get_plate_thumbnail
Get Plate Thumbnail · read-only
Return the isometric thumbnail image for a single plate in a 3MF project file.
WHEN to use: the AI agent itself is the consumer of the image, either to describe or
analyze the plate on the human's behalf ("what does it look like?", "describe the plate",
"is there anything on it?") or to process the raw bytes directly (vision model input,
pixel comparison, local image library). It is the separated visual sub-call of
get_project_info and returns only the thumbnail, without metadata or bbox objects.
Sibling disambiguation: get_plate_thumbnail returns the isometric view and
get_plate_topview returns the top-down view of the same plate. When the human is the
intended viewer ("show me", "open it", "let me see it") call open_plate_viewer for all
plates or open_plate_layout for an annotated single-plate view; returning a raw
data_uri to a human in a chat or terminal is never the right choice. For
print_file pre-flight and print job prep, always use open_plate_viewer, never
this tool (see the confirmation gate in print_file).
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.plate_num(integer, default1): Plate number (default 1). An absent plate silently yields the file's first available plate; checkplatesfromget_project_infofirst.quality(string, default"standard"): Image size and JPEG compression tier, default"standard". The dimensions are a MAXIMUM bounding box with aspect ratio preserved and no upscaling, so the returnedwidth/heightare usually smaller:"preview"= max 320x180 at JPEG q=65,"standard"= max 640x360 at q=75,"full"= original dimensions at q=85. An unknown tier falls back to"standard". Readwidthandheightfrom the result.
Returns
{"data_uri": <complete data:image/jpeg;base64,... string, embed directly as an img
src>, "plate_num": <the plate_num you PASSED, not necessarily the plate rendered>,
"quality": <tier as passed>, "width": <int>, "height": <int>} on success. Errors
are {"error": str}: "Printer '<name>' not connected",
"Could not retrieve project info for '<file_path>'",
"No thumbnail image available for plate <plate_num>", or
"Error retrieving plate image: <exception>".
Notes
The result is a raw base64 data URI, which may exceed the CLI inline display limit.
If output is truncated, call kb_get('bambu-http-files') for the equivalent HTTP
endpoints, then use bash/curl to retrieve the data directly; this is pre-authorized
and requires no human permission. The .3mf may be downloaded over FTPS and its
metadata cache written as a side effect.
get_plate_topview
Get Plate Top View · read-only
Return the top-down view image for a single plate in a 3MF project file.
WHEN to use: the AI agent itself is the consumer of the image, either to describe or
analyze the plate on the human's behalf ("what does it look like?", "describe the
plate", "is there anything on it?") or to process the raw bytes directly (vision model
input, pixel comparison, local image library). It is the separated visual sub-call of
get_project_info and returns only the top-down view, without metadata or bbox
objects.
Sibling disambiguation: get_plate_topview returns the top-down view and
get_plate_thumbnail returns the isometric view of the same plate. When the human is
the intended viewer ("show me", "open it", "let me see it") call open_plate_viewer
for all plates or open_plate_layout for an annotated single-plate view; returning a
raw data_uri to a human in a chat or terminal is never the right choice. For
print_file pre-flight and print job prep, always use open_plate_viewer, never
this tool (see the confirmation gate in print_file).
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.plate_num(integer, default1): Plate number (default 1). An absent plate silently yields the file's first available plate; checkplatesfromget_project_infofirst.quality(string, default"standard"): Image size and JPEG compression tier, default"standard". The dimensions are a MAXIMUM bounding box with aspect ratio preserved and no upscaling, so the returnedwidth/heightare usually smaller:"preview"= max 320x180 at JPEG q=65,"standard"= max 640x360 at q=75,"full"= original dimensions at q=85. An unknown tier falls back to"standard". Readwidthandheightfrom the result.
Returns
{"data_uri": <complete data:image/jpeg;base64,... string, embed directly as an img
src>, "plate_num": <the plate_num you PASSED, not necessarily the plate rendered>,
"quality": <tier as passed>, "width": <int>, "height": <int>} on success. Errors
are {"error": str}: "Printer '<name>' not connected",
"Could not retrieve project info for '<file_path>'",
"No topimg image available for plate <plate_num>", or
"Error retrieving plate image: <exception>".
Notes
The result is a raw base64 data URI, which may exceed the CLI inline display limit.
If output is truncated, call kb_get('bambu-http-files') for the equivalent HTTP
endpoints, then use bash/curl to retrieve the data directly; this is pre-authorized
and requires no human permission. The .3mf may be downloaded over FTPS and its
metadata cache written as a side effect.
get_project_info
Get Project Plate Info · read-only
Return 3MF metadata and thumbnail info for one plate of a project file on the SD card.
WHEN to use: read a .3mf plate's filaments, AMS mapping placeholder and object bounding
boxes before choosing a plate, building a print summary, or calling print_file.
Sibling disambiguation: get_project_info returns one plate per call;
get_all_project_info returns every plate in the file in one call. The image tools
get_plate_thumbnail and get_plate_topview fetch a single plate's picture, and
get_current_job_project_info resolves the file and plate of the active job for you.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.plate_num(integer, default1): Plate to parse (default 1). If the requested plate does not exist in the .3mf, the library SILENTLY falls back to the file's first available plate: compare the returnedplate_numwith the one you asked for, and readplatesto see which plates exist.include_images(boolean, defaultfalse): False (default) omits themetadata.topimgandmetadata.thumbnailimage fields to keep the response small. True includes both as raw base64 data URIs (large). Use True only when the AI agent needs to process the image bytes directly (vision analysis, comparison) or is describing the image on the human's behalf; a human cannot see raw base64 in a chat or terminal, so to let the human *view* the plates callopen_plate_viewer.
Returns
The serialized project info for the plate: id, name, size, timestamp,
md5, plate_num, plates and metadata (see Notes for the key fields).
Errors are {"error": str}: "Printer '<name>' not connected",
"Could not retrieve project info for '<file_path>'", or
"Error getting project info: <exception>".
Notes
The .3mf file is created by BambuStudio or OrcaSlicer, the slicing applications that
turn .STL/.3MF model files into printable G-code and package everything into a .3mf
project file. The tool parses the requested plate using a local metadata cache. A
cache HIT still performs a live FTPS listing of the whole SD card to validate the cache
(the printer must be reachable) and repopulates the printer library's cached trees;
only the .3mf download is skipped. On a miss the .3mf is downloaded over FTPS and the
cache is written. The same applies to every tool that reads project info.
get_all_project_info and open_plate_viewer pay for that listing once per call,
because the plates after the first are served from the cached listing.
Three metadata keys say which external spool holder each filament prints from
(bpm 1.0.4 and later; a daemon running an older bpm omits them). All are lists indexed
by filament id - 1. filament_extruders is the slicer's 1-based logical extruder
per filament, from slice_info.config; it is empty when the slicer wrote none.
physical_extruder_map is the physical extruder (0 main, 1 deputy) per logical
extruder, from the plate gcode config block; it is empty when absent, and is [1, 0]
on an H2D, so logical extruder 1 is the LEFT one. external_spool_trays is the wire
id of the external holder feeding each filament: 255 main (right), 254 deputy (left),
-1 unused; a single-nozzle printer reports 255 for every used filament although its
telemetry calls its one holder tray 254, so do not match this list to a spool's
slot_id. It is empty when a dual-nozzle plate has no extruder map, and it is
derived on every read, never cached. print_file with use_ams=False uses the
same derivation, so a caller passes no holder.
Multi-level call hierarchy:
Level 1: ``get_project_info(name, file, 1)`` returns ``{plates: [...], ...}`` (index):
the file's real plate numbers, which may be sparse, such as [1,5,6,12].
Level 2: ``get_project_info(name, file, N)`` for one of those numbers returns
per-plate metadata and bbox_objects.
Level 3: ``get_plate_thumbnail(name, file, N)`` returns just the isometric image;
``get_plate_topview(name, file, N)`` returns just the top-down image.
Key fields in the returned dict:
plates: list of all plate numbers in the file. They are not necessarily contiguous or 1-based (e.g. [1,5,6,12] or [10]). Iterate over that list, never overrange(1, len(plates) + 1), and callget_project_infoonce per listed plate to retrieve all plates (or useget_all_project_info).metadata.filament: list of{"id": int (1-based), "type": str, "color": str}for the plate's filaments, the colour being a hex string such as "#RRGGBB". These ids index theams_mappingarray thatprint_fileandpreview_ams_mappinguse.metadata.ams_mapping: a filament-id PLACEHOLDER only, never a real slot assignment; do not pass it toprint_file.metadata.map.bbox_objects: list of{name, ...}dicts for objects on this plate. Filter out entries whose name containswipe_towerto get the human-readable part list.metadata.topimg: present only wheninclude_images=True. Complete base64 data URI (data:image/png;base64,...). Use DIRECTLY as an img src.metadata.thumbnail: present only wheninclude_images=True. Isometric thumbnail data URI. Use DIRECTLY as an img src.- With
include_images=Falsethose two fields are replaced by an omission marker string naming the tool to fetch them.
Coordinate system for bbox fields:
- bbox values are [x_min, y_min, x_max, y_max] in millimetres, absolute bed position.
- Origin (0,0) is the BOTTOM-LEFT of the build plate (slicer convention).
- To map to image pixel coords (origin top-left): flip Y, pixel_y = img_height - (y_mm / bed_h * img_height).
- Apply uniform scale: scale = min(img_w / bed_w, img_h / bed_h); add centring offsets.
- Bed dimensions by model (mm, W x H): H2D/H2S=350x320, X1C/X1/X1E/P1S/P1P/P2S/A1=256x256, A1_MINI=180x180.
- Use
printer.config.printer_model.valueto get the model string for dimension lookup.
Cross-tool link: bbox_objects[].id values are the identify_id integers required by
skip_objects. Filter bbox_objects to exclude entries whose name contains
wipe_tower to get human-readable part names.
When include_images=True the response carries raw base64 data URIs which may
exceed the CLI inline display limit. If output is truncated, use the HTTP fallback:
GET http://localhost:{api_port}/api/get_3mf_props_for_file?printer={name}&file={file_path}&plate={plate_num}.
Call kb_get('bambu-http-files') for full route docs. Pre-authorized, no human
permission needed.
list_sdcard_files
List SD Card Files · read-only
Return the SD card directory listing for the named printer, whole or one subtree.
WHEN to use: see what files and folders are on the printer's SD card, or narrow the
listing to one folder such as /cache/ or /model/ to keep the response small.
Sibling disambiguation: list_sdcard_files returns a directory tree, while
get_file_info returns the single entry for one known path. refresh_sdcard only
re-reads the card into the cache and returns no listing; it matters when you then call
this tool with cached=True. get_3mf_entry_by_name and get_3mf_entry_by_id
search the .3mf-only tree for one entry.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).path(string, default"/"):"/"(default) returns the full top-level tree. A subdirectory returns only that subtree, which is much smaller. The subtree is the first depth-first node whoseidornameequalspathexactly. Directory ids carry a TRAILING SLASH, so use"/cache/"or the bare name"cache";"/cache"matches nothing and returnsPath not found.cached(boolean, defaultfalse): False (default) performs a live FTPS fetch from the printer: guaranteed current, but it needs an active connection and takes a moment. True returns the in-memory cached copy immediately without contacting the printer, for when stale data is acceptable and low latency matters. The cache is populated by the most recent live listing (this tool withcached=False, orrefresh_sdcard). If the cache has never been populated, or the last listing was reported as failed (the library then clears it), the call returns theFailed to retrieve SD card contentserror. A live listing returns the same error when the listing failed (a timeout, a dropped connection, or any folder that could not be listed): a failed listing is never returned as an empty tree. An EMPTYchildrenlist therefore means the card, or that folder, really is empty; a folder the printer refuses to list also reads as empty.
Returns
{"path": <path>, "contents": <node>} on success, where a node is
{"id": <full SD card path>, "name", "size" (bytes), "timestamp", "children"
(directories only)}. A response whose JSON exceeds 300 characters (in practice
almost every real listing) comes back instead as the gzip envelope
{"compressed": True, "encoding": "gzip+base64", "original_size_bytes",
"compressed_size_bytes", "data"}. Errors are {"error": str}:
"Printer '<name>' not connected", "Failed to retrieve SD card contents",
{"error": "Path not found: <path>", "path": <path>}, or
"Error listing SD card: <exception>".
Notes
Use it as a hierarchy: list_sdcard_files(name) for the full top-level tree,
list_sdcard_files(name, "/cache/") for only the /cache subtree,
list_sdcard_files(name, "/model/") for only the /model subtree.
A live listing (cached=False) also repopulates the printer library's cached tree.
To decompress the gzip envelope:
import gzip, json, base64; data = json.loads(gzip.decompress(base64.b64decode(r["data"]))).
If the compressed envelope itself exceeds the MCP response limit, use the HTTP
fallback GET /api/get_sdcard_contents?printer=<name>, or reduce scope by listing a
specific subdirectory (for example path="/cache/").
open_plate_layout
Open Plate Layout Image · read-only
Generate and open an annotated top-down image for a single plate, with each object's bounding box overlaid on the top-view image.
WHEN to use: the human should see where each part sits on one plate's build surface, with a colour legend of part names, for example to confirm object placement before printing.
Sibling disambiguation: open_plate_layout produces one annotated PNG for a single
plate; open_plate_viewer opens an HTML page showing all plates of the file.
get_plate_topview returns the plain top-down image data for the AI agent without
annotation or opening anything.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.plate_num(integer, default1): Plate to render (default 1). An absent plate silently renders another available plate; checkplatesfromget_project_infofirst.
Returns
{"success": True, "path": <PNG path under /tmp>, "plate": <the plate_num you
PASSED, not necessarily the plate rendered>, "objects": <bounding-box object count>,
"unique_parts": <distinct part name count>, "bed_mm": "<W>x<H>"} on success.
objects and unique_parts COUNT wipe-tower entries, and the wipe tower is drawn
on the image and listed in the legend; unlike open_plate_viewer this tool applies
no wipe_tower filter, so subtract entries whose name contains wipe_tower when
reporting a part count. Errors are {"error": str}: "Printer '<name>' not
connected", "Could not retrieve project info for plate <plate_num>",
"No top-down image available for this plate", "No bounding-box objects found for
this plate", or "Error building plate layout: <exception>".
Notes
The PNG is saved to /tmp/plate_layout_<name>_p<plate_num>.png (overwriting any
earlier one) and opened in the default viewer. Reading the project info may download
the .3mf over FTPS and write the local metadata cache.
Bed dimensions are selected by printer model (mm, W x H): H2D/H2S=350x320, X1C/X1/X1E/P1S/P1P/P2S/A1=256x256, A1_MINI=180x180.
Coordinate mapping applied internally:
- Slicer bbox coordinates use a bottom-left origin (mm); the image uses a top-left origin.
- scale = min(img_w / bed_w, img_h / bed_h): uniform scale, no distortion.
- x_off = (img_w - bed_w * scale) / 2; y_off = (img_h - bed_h * scale) / 2: centring.
- pixel_x = x_off + x_mm * scale; pixel_y = img_h - y_off - y_mm * scale: Y flip.
Each unique part name is assigned a distinct colour; a legend with part names and colours is appended below the annotated image.
open_plate_viewer
Open Plate Viewer · read-only
Build and open an HTML viewer of the isometric and top-down images for the plates of a 3MF project file on the printer's SD card.
WHEN to use: the human should see the plates, for example to visually confirm which plate
to print before calling print_file, or to jump to the plate a finished job printed.
Sibling disambiguation: open_plate_viewer shows every plate the file really contains
(isometric, top-down and, when objects are known, a layout image per plate) in a browser
page, headed with each plate's own number even when the numbers are sparse;
open_plate_layout shows one plate as a single annotated top-down PNG. The
get_plate_thumbnail and get_plate_topview tools return raw image data for the AI
agent rather than opening anything for the human.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.target_plate(integer, defaultnull): Optional plate number to scroll straight to on open. If set, the browser opens with the URL fragment#plate-{target_plate}. Useful after a job completes: pass the plate number fromget_job_infoto jump to the printed plate. The anchors are the file's real plate numbers, so a number the file does not contain scrolls nowhere.
Returns
{"success": True, "path": <path of the HTML file written under /tmp>, "plates":
<number of plates shown>} on success. Errors are {"error": str}:
"Printer '<name>' not connected", "Could not retrieve project info for '<file_path>'", or
"Error building plate viewer: <exception>".
Notes
Fetches project info for the plates via the local cache (the .3mf may be downloaded
over FTPS and the cache written on a miss), embeds the base64 images directly in the
HTML, writes it to /tmp/plate_viewer_<name>.html (overwriting any earlier viewer
for that printer), and opens it in the default browser. The plate set is the one
get_all_project_info returns: plate numbers are not assumed to be contiguous or to
start at 1, so a file with plates [1,5,6,12] shows exactly those four, each under its
own number. Only plates that genuinely exist are fetched, and the library's ceiling of
30 applies: a plate numbered above 30 is not shown. The .3mf is downloaded at most
once, and the listing of the SD card is refreshed once for the whole batch.
preview_ams_mapping
Preview AMS Mapping · read-only
Resolve, WITHOUT printing, the ams_mapping that print_file would send for a .3mf plate, from the spools the printer last reported loaded.
WHEN to use: STEP 1 of the print_file confirmation gate. Call it, then show the
result in the summary: each filament to its tray_id with the spool it matched, its colour
distance, and a BPA match label (Excellent Match / Good Match / Type Match / Color Match
Only / Poor Match).
Sibling disambiguation: preview_ams_mapping is read-only and never prints;
print_file runs the same resolution and then starts the physical print.
get_project_info reports the plate's filaments but its ams_mapping is only a
filament-id placeholder, and get_spool_info reports the loaded spools.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file.plate_num(integer, default1): Plate to resolve the mapping for (default 1). An absent plate silently resolves against the file's first available plate; checkplatesfromget_project_infofirst.
Returns
A resolution payload dict: file_path, plate_num (the value you PASSED, not
necessarily the plate resolved), filaments,
resolved_ams_mapping (list indexed by 1-based filament id, -1 for an unused id),
ams_mapping_json (the exact string print_file sends), matches,
unmatched, loaded_spools (the AMS spools that could be printed from) and
external_spools. When "error" is present in the payload print_file would
refuse with the same message; pass ams_mapping explicitly or use use_ams=False.
The payload may then hold only {"error": str}, for a metadata read failure or a plate
with no filament metadata. If the printer is not connected the result is
{"error": "Printer '<name>' not connected"}.
Notes
Read-only in purpose: it changes nothing on the printer, though reading the project
metadata may download the .3mf over FTPS and write the local metadata cache.
"Type Match" means the material matches but the colour is off: print_file WILL
print on it, so surface it to the user. "Color Match Only" means the MATERIAL DOES NOT
MATCH (for example the project wants PLA and only PETG is loaded) and the spool was
accepted purely because its colour is close: print_file WILL print on it too. Call
this out explicitly for any "quality": "poor" match; it is a stronger warning than
a colour mismatch.
print_file
Start Print From SD Card · write, destructive · needs user_permission=True
Send the command to start printing a .3mf file already stored on the printer's SD card.
WHEN to use: only as the last step, after the confirmation gate in Notes (STEP 0 to STEP 3) has been completed in a single turn and the user has given an explicit go-ahead after seeing the complete summary. Never call it on a partial confirmation.
WRITE GUARD: starts a physical print on the named printer, which heats, moves and
extrudes immediately. Once started the job can only be paused (pause_print) or
cancelled (stop_print); it cannot be recalled. With user_permission False the tool
changes nothing and returns the {"error": ...} refusal naming that consequence.
Separately from the guard, the tool is BLOCKED while the printer's LAST REPORTED
gcode_state is RUNNING or PREPARE (an active-print guard that user_permission=True
cannot override). That block reads cached telemetry and does not fire when the state is
empty or unreadable, as it is until the first status report after a session or daemon
restart.
Sibling disambiguation: print_file starts the print; preview_ams_mapping resolves
the same ams_mapping without printing and is the read-only step before it.
get_project_info reads the plate's filaments, and open_plate_viewer shows the
plates to the human.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).file_path(string, required): Full SD card path of the .3mf file to print.plate_num(integer, default1): Plate to print (default 1).bed_type(string, default"auto"): One ofauto,cool_plate,eng_plate,hot_plate,textured_plate(case-insensitive); any other value silently falls back toauto.cool_plate= smooth cold plate (PLA, TPU at low temp);eng_plate= smooth engineering plate (PETG, PA, ABS);hot_plate= smooth high-temp plate (ASA, PC);textured_plate= textured PEI surface (good general-purpose adhesion);auto= let the printer decide based on the sliced settings in the file. Default"auto".use_ams(boolean, defaulttrue): True (default) loads filament from AMS slots, with the mapping resolved as described underams_mapping. False prints using only the external spool holder (single-colour prints without AMS): leaveams_mappingempty, and bpm derives the holder for each filament from the plate's own extruder assignment (right holder for a filament sliced for the right extruder, left holder for the left) and refuses the print with an error when the plate has no extruder map. The holder cannot be chosen.ams_mapping(array of any or string or null, defaultnull): Optional override, default None. When empty (None,""or[]) anduse_amsis True, the mapping is resolved from the spools the printer last reported loaded: each project filament is matched to an AMS spool by exact type then closest colour (bambu-printer-app's print-dialog scoring; exact pairs are assigned first, then best unused, then reuse). A same-material spool of the WRONG colour is accepted ("Type Match"). A WRONG-MATERIAL spool is ALSO accepted if its colour is close enough ("Color Match Only", no material check at all), so callpreview_ams_mappingfirst and show the user every match label, "Color Match Only" especially. The 3mf carries no usable tray ids:get_project_info's ams_mapping is a filament-id placeholder, never a slot assignment. If any filament finds no loaded match, or the plate carries no filament metadata, the print is REFUSED with the unmatched filaments and the loaded spools listed. To override, provide a JSON array string or a list of integers indexed by 1-based filament id (index 0 = filament 1), each element an absolute tray_id, -1 for a filament id the plate does not use. Whenams_mappingis provided,use_amsis automatically set to True. See Notes for the tray_id encoding.timelapse(boolean, defaultfalse): Record a timelapse (default False).bed_leveling(boolean, defaulttrue): Run bed leveling before printing (default True).flow_calibration(boolean, defaultfalse): Run flow calibration before printing (default False).user_permission(boolean, defaultfalse): Must be True to execute. Default False.
Returns
{"success": True, ...} means the print command was PUBLISHED; the printer's
acceptance and the job's start are not confirmed. Follow up with get_print_progress
or get_job_info, and get_hms_errors if nothing starts. The full success shape
is {"success": True, "file_path": <file_path>, "plate_num": <plate_num>,
"bed_type": <resolved bed type name>, "use_ams": <bool>, "ams_mapping": <JSON string
sent, empty when none>, "matches": <list of per-filament match dicts from the
live-spool resolution, empty whenams_mappingwas provided oruse_amsis
False>}. Errors are {"error": str}: the _permission_denied refusal when
user_permission is False, "Printer '<name>' not connected", the active-print
block "Blocked: '<name>' is currently <state>. ...", or
"Error starting print: <exception>". When the live-spool resolution fails, the
return is the resolution payload of preview_ams_mapping (file_path,
plate_num, filaments, resolved_ams_mapping, ams_mapping_json,
matches, unmatched, loaded_spools, external_spools) plus an
"error" message, or only {"error": str} when the project metadata could not be
read.
Notes
Calls printer.print_3mf_file() with the given parameters.
tray_id encoding for ``ams_mapping``: ALWAYS derive from live telemetry (the spool's
ams_id is the hardware chip_id from ``get_ams_units`` / ``get_spool_info``), NEVER
hardcode:
4-slot AMS (ams_id 0..127): tray_id = ams_id * 4 + slot_id -> 0..103
AMS HT / N3S (ams_id >= 128): tray_id = ams_id + slot_id -> 128..
Unused filament id = -1. External spool: not part of this array, use use_ams=False.
NEVER use the 0-based unit_index in place of ams_id, and NEVER apply the 4-slot formula
to an AMS HT (ams_id 128 -> 512 is wrong; 128 is right).
Correct workflow when overriding:
1. Call ``preview_ams_mapping`` to see what the tool would resolve, then
``get_spool_info`` for each spool's ams_id and slot_id.
2. Encode each chosen spool with the formula above.
3. Build the array indexed by 1-based filament id from ``get_project_info``.
Example: if AMS 2 Pro has ams_id=0, slot 1 -> tray_id=1.
if AMS HT has ams_id=128, slot 0 -> tray_id=128.
Always call ``get_project_info`` first to see which filaments the .3mf plate uses.
CONFIRMATION REQUIRED. DO NOT CALL THIS TOOL until all steps below are done IN A SINGLE TURN. This tool starts a physical print that can only be paused or cancelled afterwards, not recalled.
STEP 0, active-print guard: this tool is BLOCKED when the last reported gcode_state is
RUNNING or PREPARE (defense-in-depth, read from cached telemetry). Check
get_print_progress first if unsure.
STEP 1, gather everything first (no user interaction yet): call get_project_info,
preview_ams_mapping, get_ams_units and get_spool_info to collect all data
needed to build the complete summary before asking the user anything.
preview_ams_mapping is the mapping print_file will actually send. To show plate
visuals to the user, call open_plate_viewer(name, file_path); do NOT call
get_plate_thumbnail or get_plate_topview and embed the data_uri in the
response. Humans cannot see raw base64 in a terminal or chat context. Also look up
the stored preference for each sticky field with get_user_pref(name, key), keys
bed_leveling, flow_calibration and timelapse. A null value means nothing is
stored: use the factory default.
Factory defaults: bed_leveling=True, flow_calibration=False, timelapse=False. Label
each field "(your preference)" if the stored value differs from the factory default,
or "(default)" if it matches the factory default.
STEP 2, present ONE complete summary containing ALL of the following:
- Part name(s) and filament(s) from the project metadata
- bed_type (from metadata): ask whether it is correct for the plate physically on
the bed
- ams_mapping, from ``preview_ams_mapping``: each filament to a tray with its match
label; call out any "Type Match" (right material, wrong colour); ask whether it is
correct
- flow_calibration: show the stored value with its label; ask whether to run flow
calibration before printing
- timelapse: show the stored value with its label; ask whether to record a timelapse
- bed_leveling: show the stored value with its label; ask whether to run bed
leveling or skip it for speed
STEP 3, wait for explicit go-ahead AFTER the complete summary. Do NOT call print_file
after confirming individual parameters across separate turns. Confirming
flow_calibration, timelapse, or bed_leveling mid-conversation does NOT satisfy this
gate. The go-ahead must come in the turn immediately after the full summary is shown
with all six items visible. After print_file is called successfully, store the values
used with set_user_pref(name, key, value) for each of the three keys.
refresh_sdcard
Refresh SD Card Listing · read-only
Force a fresh SD card listing from the printer.
WHEN to use: you need up-to-date cached SD card data, for example after uploading a file or
after a print completes, before reading it with list_sdcard_files(cached=True).
Sibling disambiguation: refresh_sdcard re-reads the card and returns no listing;
list_sdcard_files returns the listing itself, and with its default cached=False it
already does a live FTPS fetch of its own.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).mode(string, default"full"):'full'(default) and'3mf'both perform ONE full live FTPS listing of the whole SD card and repopulate BOTH cached trees (the .3mf tree is derived by filtering the full one). The mode only selects whether the tool callsprinter.get_sdcard_contents()orprinter.get_sdcard_3mf_files()and checks that call's return value; there is no cost or scope difference. Case-insensitive.
Returns
{"success": True, "mode": <'full' or '3mf'>, "printer": <name>} on success. Errors
are {"error": str}: "Printer '<name>' not connected",
"Unknown mode '<mode>'. Must be 'full' or '3mf'.",
"Failed to retrieve SD card contents" (the printer library reported the listing as
failed, which it does by returning None and clearing both cached trees, so the cache
is empty, not merely stale), or "Error refreshing SD card on '<name>': <exception>".
Notes
The refresh is synchronous: the updated data is available immediately. It triggers an
explicit re-read of the SD card contents over FTPS and repopulates the printer library's
cache; it changes nothing on the printer. Success means the library returned a
listing tree, and an empty card is a success with no children. A listing that
failed (a timeout, a dropped connection, a folder that could not be listed) is the
Failed to retrieve SD card contents error, never a success. A folder the printer
refuses to list is treated as empty. If the call raises instead (for example the FTPS
connection cannot be opened), the error names the exception and the previous cached
trees are left in place.
rename_sdcard_file
Rename SD Card File · write · needs user_permission=True
Rename or move a file on the printer's SD card.
WHEN to use: change a file's name, or move it to another folder on the card, without re-uploading it.
WRITE GUARD: renames or moves the file on the printer's SD card over FTPS, so it no longer
exists at its old path. With user_permission False the tool changes nothing and returns
the {"error": ...} refusal naming that consequence.
Sibling disambiguation: rename_sdcard_file moves or renames a file that is already on
the card; upload_file copies a new file from this host, and delete_file removes a
file's data.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).src_path(string, required): Full SD card path of the existing file, for example'/cache/my_old_name.gcode.3mf'.dest_path(string, required): Full SD card path to move it to. Both paths must be on the SD card.user_permission(boolean, defaultfalse): Must be True to execute. Default False.
Returns
{"success": True, "src_path": <src_path>, "dest_path": <dest_path>} on success (no
listing is returned). Errors are {"error": str}: the _permission_denied refusal
when user_permission is False, "Printer '<name>' not connected", or
"Error renaming file on '<name>': <exception>".
Notes
This is an FTPS rename operation, not a copy: the file is moved or renamed in place and no data is re-uploaded. Each call then performs a FULL live FTPS listing of the card and repopulates the printer library's cached trees; a listing that raises surfaces as a rename error even though the rename succeeded, while a listing the library reports as failed is not surfaced, because the rename it followed did succeed. Cached plate metadata keyed to the old path is not renamed.
upload_file
Upload File To SD Card · write, destructive · needs user_permission=True
Upload a local file to the printer's SD card.
WHEN to use: put a file from this host onto the printer's SD card, for example a sliced .3mf you want to print, or to replace a file already on the card.
WRITE GUARD: writes the file to the printer's SD card over FTPS, replacing any existing
file at that remote path. With user_permission False the tool changes nothing and
returns the {"error": ...} refusal naming that consequence.
Sibling disambiguation: upload_file copies a file from this host to the printer;
download_file copies the other way, from the printer to this host.
rename_sdcard_file moves a file that is already on the card without re-uploading it.
Parameters
name(string, required): Configured printer name (seeget_configured_printers).local_path(string, required): Full path of the file on this host to upload. It is not constrained to any directory: any file readable by this host can be copied to the printer's SD card.remote_path(string, required): Full destination path on the printer's SD card.user_permission(boolean, defaultfalse): Must be True to execute. Default False.
Returns
{"success": True, "remote_path": <remote_path>, "contents": <refreshed SD card
tree>} on success; contents is the printer library's SD card listing taken after
the upload. It is null when that listing failed; the upload itself succeeded either
way, so the tool still returns success. Errors are {"error": str}: the
_permission_denied refusal when user_permission is False,
"Printer '<name>' not connected", or "Error uploading file: <exception>".
Notes
If local_path ends in .3mf, the project metadata is parsed and cached after the
transfer, and the SD card is then re-listed. A failure in either step (for example an
unsliced .3mf lacking Metadata/slice_info.config) surfaces as "Error uploading
file: ..." even though the file is ALREADY on the card; check with get_file_info
before retrying.