Skip to main content
Glama

compose_multicolor_3mf

Combines multiple STL files into one multi-color, multi-material .3mf with per-part AMS extruder slot assignments, ready for slicing in BambuStudio, OrcaSlicer, PrusaSlicer, or Cura.

Instructions

Compose a multi-color / multi-material .3mf from multiple STL files.

Creates a **single .3mf, ready to slice**, containing all parts with
per-part AMS/extruder slot assignments.  This is the correct way to hand
a multi-color design to a slicer — it receives one file, not multiple.
It is a model, not a sliced plate, so no printer starts it as it stands:
slice it first.  ``fits_bed`` says whether the plate fits the bed it was
composed for; when it does not, the message says by how much and what to
do, and does not offer it for printing.

Parts whose bodies touch or overlap are one print: they become ONE
object with a part per input, and where two overlap the smaller part is
printed.  Parts placed apart stay separate objects.

Compatible with:
* **BambuStudio / OrcaSlicer / Bambu A1, X1, P1 + AMS** — read ``Metadata/model_settings.config``
* **PrusaSlicer / MMU** — reads ``Metadata/Slic3r_PE_model.config``
* **Cura** and any 3MF-capable slicer

Typical two-color workflow::

    # 1. Export body STL (main color, e.g. grey PLA)
    # 2. Export accent STL (second color, same coordinate origin)
    # 3. Compose:
    result = compose_multicolor_3mf(parts=[
        {"stl_path": "/tmp/body.stl",    "extruder": 1,
         "name": "body",    "color": "#AAAAAA", "material": "PLA Grey"},
        {"stl_path": "/tmp/qr_pads.stl", "extruder": 2,
         "name": "qr_code", "color": "#111111", "material": "PLA Black"},
    ])
    # 4. Slice and print (or slice_model to look at the slice first):
    slice_and_print(result["output_path"])

Args:
    parts: List of part dicts.  Each dict requires:

        * ``stl_path`` (str) — absolute path to the STL for this part
        * ``extruder`` (int) — 1-indexed AMS slot (1 = AMS tray 1 on
          Bambu); omitted, 1

        Optional per-part keys:

        * ``name`` (str) — label shown in the slicer object list
        * ``color`` (str) — hex preview color e.g. ``"#AAAAAA"`` (display only)
        * ``material`` (str) — filament label e.g. ``"PLA Grey"`` (display only)

    output_path: Where to write the .3mf.  Defaults to a temp file whose
        path is returned in the result.
    plate_width: Print plate X dimension in mm (default 256 for legacy
        callers without a printer id).
    plate_depth: Print plate Y dimension in mm (default 256).
    material: Optional material the parts will be printed in (e.g.
        ``"PETG"``).  A spool on record in a clearly different
        material is then not named as one to load.
    printer_id: Optional supported printer model id.  When it resolves,
        its build volume overrides ``plate_width`` / ``plate_depth``.
        The composer centres an off-plate group on THIS plate, so name
        the printer whenever you know it — a group arranged for a
        larger or smaller bed and composed against the 256 default is
        re-centred onto a plate the machine does not have.

Returns:
    Dict with ``success``, ``output_path``, ``parts``, ``objects`` (build
    objects, after touching parts are joined), ``colours`` (extruder
    slots used), ``total_triangles``, ``total_vertices``, ``extruder_map``
    (which parts print from each slot), ``fits_bed`` (``False`` when the
    plate is bigger than its bed, ``None`` when it could not be measured),
    ``bed_fit`` (the sizes behind that verdict), and ``message``.  It also says
    whether the part colours are on the printer, as
    ``colour_availability`` (absent when Kiln cannot see what is loaded).
    Relay its ``say`` as written and add nothing about filament: never
    suggest buying filament unless the person asks for one or says yes
    to the offer in ``say``.  On a yes, call ``find_closest_filaments``
    with these colours and the print's material.

INLINE 3D STAGE: on success this tool opens Kiln's interactive 3D stage — an inline viewer panel the user can orbit, zoom, and turn over — in hosts that render MCP Apps panels (Kiln's hosted connection attaches a browser stage link for hosts that don't). Oversized meshes are decimated automatically for the stage; the PNG preview is the floor, not the whole experience.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "parts": "<parts>"
    },
    "name": "compose_multicolor_3mf"
  }
}

Input Schema

NameRequiredDescriptionDefault
partsYesList of part dicts. Each dict requires: * ``stl_path`` (str) — absolute path to the STL for this part * ``extruder`` (int) — 1-indexed AMS slot (1 = AMS tray 1 on Bambu); omitted, 1 Optional per-part keys: * ``name`` (str) — label shown in the slicer object list * ``color`` (str) — hex preview color e.g. ``"#AAAAAA"`` (display only) * ``material`` (str) — filament label e.g. ``"PLA Grey"`` (display only)
materialNoOptional material the parts will be printed in (e.g. ``"PETG"``). A spool on record in a clearly different material is then not named as one to load. Default: "".
printer_idNoOptional supported printer model id. When it resolves, its build volume overrides ``plate_width`` / ``plate_depth``. The composer centres an off-plate group on THIS plate, so name the printer whenever you know it — a group arranged for a larger or smaller bed and composed against the 256 default is re-centred onto a plate the machine does not have. Default: "".
output_pathNoWhere to write the .3mf. Defaults to a temp file whose path is returned in the result. Default: "".
plate_depthNoPrint plate Y dimension in mm (default 256). Default: 256.0.
plate_widthNoPrint plate X dimension in mm (default 256 for legacy callers without a printer id). Default: 256.0.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changedv1.5.1
    • changedInput schema / properties / material / description
      Previous value: -"Default: \"\"."New value: +"Optional material the parts will be printed in (e.g. ``\"PETG\"``).  A spool on record in a clearly different material is then not named as one to load. Default: \"\"."
    • changedInput schema / properties / output_path / description
      Previous value: -"Default: \"\"."New value: +"Where to write the .3mf.  Defaults to a temp file whose path is returned in the result. Default: \"\"."
    • addedInput schema / properties / parts / description
      Added value: +"List of part dicts.  Each dict requires: * ``stl_path`` (str) — absolute path to the STL for this part * ``extruder`` (int) — 1-indexed AMS slot (1 = AMS tray 1 on Bambu); omitted, 1 Optional per-part keys: * ``name`` (str) — label shown in the slicer object list * ``color`` (str) — hex preview color e.g. ``\"#AAAAAA\"`` (display only) * ``material`` (str) — filament label e.g. ``\"PLA Grey\"`` (display only)"
    • changedInput schema / properties / plate_depth / description
      Previous value: -"Default: 256.0."New value: +"Print plate Y dimension in mm (default 256). Default: 256.0."
    • changedInput schema / properties / plate_width / description
      Previous value: -"Default: 256.0."New value: +"Print plate X dimension in mm (default 256 for legacy callers without a printer id). Default: 256.0."
    • changedInput schema / properties / printer_id / description
      Previous value: -"Default: \"\"."New value: +"Optional supported printer model id.  When it resolves, its build volume overrides ``plate_width`` / ``plate_depth``. The composer centres an off-plate group on THIS plate, so name the printer whenever you know it — a group arranged for a larger or smaller bed and composed against the 256 default is re-centred onto a plate the machine does not have. Default: \"\"."
  2. Changed6 schema fields changedv1.5.0
    • addedInput schema / properties / material
      Added value: +{
      +  "description": "Default: \"\".",
      +  "title": "Material",
      +  "type": "string"
      +}
    • removedInput schema / properties / output_path / default
      Removed value: -""
    • addedInput schema / properties / output_path / description
      Added value: +"Default: \"\"."
    • addedInput schema / properties / plate_depth
      Added value: +{
      +  "description": "Default: 256.0.",
      +  "title": "Plate Depth",
      +  "type": "number"
      +}
    • addedInput schema / properties / plate_width
      Added value: +{
      +  "description": "Default: 256.0.",
      +  "title": "Plate Width",
      +  "type": "number"
      +}
    • addedInput schema / properties / printer_id
      Added value: +{
      +  "description": "Default: \"\".",
      +  "title": "Printer Id",
      +  "type": "string"
      +}
  3. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish that this is a non-readonly, non-destructive, closed-world tool. The description goes well beyond that by explaining touching/overlapping part joining, which overlapping part wins, bed-fit behavior including the fits_bed/None distinction, per-slicer compatibility, return fields, the relay-the-say rule, and the inline 3D stage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is long but front-loaded with purpose, then behavior, compatibility, workflow, parameters, returns, and stage behavior in a logical order. Almost every section earns its place for this complexity, though the parameter and returns prose duplicates structured fields and could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a complex 6-parameter composition tool with no output schema, and the description compensates fully: it covers output semantics, bed-fit interpretation, part joining, slicer compatibility, downstream filament handling, and the inline stage. An agent has enough information to call it and interpret its result correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: it explains why printer_id matters by describing plate centering against the resolved build volume, and it clarifies how material affects spool recommendations. The per-part keys are repeated from the schema rather than extended, which keeps it from a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and resource — compose a multi-color .3mf from multiple STL files — and the follow-up states that this is the correct handoff to a slicer rather than multiple files. That scope clearly separates it from siblings such as merge_stl, merge_multicolor_gcode, compose_models, and export_model_3mf.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explains the typical two-color workflow, states that the output is a model not a sliced plate that must be sliced first, and recommends naming the printer when known. It also gives a downstream instruction to call find_closest_filaments only after a yes. It does not explicitly name the sibling alternative to use instead, so this is strong context without full when-not/alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools