Skip to main content
Glama

decorate_surface

Destructive

Emboss or deboss logos, text, or images onto a 3D model surface, auto-picking the best face and scaling content to fit. Returns a new STL ready to print.

Instructions

Put any image, text, or pattern onto a 3D model surface.

For repeating patterns (wood grain, camo, honeycomb) that tile across
the entire surface, use ``apply_geometric_texture`` or
``apply_procedural_texture`` instead.  This tool is for one-off
content placement (logos, text, images).

Takes a model and content (image file, text string, SVG) and returns
a new STL with the content embossed or debossed onto the surface.
Automatically detects the best face for placement and scales content
to fit.  Single-color coin-relief style — no multi-material needed.

**Content types** (auto-detected from *content* string):

- **Image file** (PNG/JPG/SVG): ``"/path/to/photo.jpg"``
- **Text**: ``"text:KILN"`` or ``"text:Hello World"``

**Image styles** for raster images:

- "auto" — a logo/wordmark/line-art image routes to "stencil"
  (crisp traced strokes); a photo is sculpted and Kiln picks the look
  from the photo and the part, saying why in relief.chosen_because
- "coin" — a sunk relief, the subject rising to the rim plane
- "cameo" — the same relief raised on the face (emboss)
- "etched" — edges first, for a small part
- "sketch" — engraved contour lines, one layer deep (was "portrait")
- "medallion" — a coin with a rim ring; "photo" and
  "composite" mean "coin"
- "stencil" (alias "logo") — the mark's ink is traced into
  vector strokes and carved directly: crisp edges, no background
  tile, correct orientation.  The right choice for brand logos.

**Examples**::

    decorate_surface(model_path="coaster.stl", content="photo.jpg",
                     mode="deboss", depth_mm=1.5, image_style="coin")

    decorate_surface(model_path="keychain.stl", content="text:KILN",
                     face="top", depth_mm=0.5)

Requires OpenSCAD installed locally for compilation.

:param model_path: Path to the base model (STL or OBJ).
:param content: What to put on the surface — file path (PNG/JPG/SVG)
    or ``"text:..."`` for text.
:param face: Which face to decorate: ``"auto"`` (largest flat face),
    ``"top"``, ``"bottom"``, ``"front"``, ``"back"``, ``"left"``,
    ``"right"``, or ``"wall"`` (wraps text, an SVG logo or a line-art
    mark around the upright round wall of a cup, jar, vase or bowl;
    STL and deboss only; a photo relief goes on a flat face).  On
    ``"wall"``, *scale* is the letter height or mark width as a share
    of the wall, *absolute_size_mm* pins it exactly, and
    *offset_x/y_mm* / *placement* do not apply; the response reports
    the size and depth used.  Placement on ``top``/``bottom``/``front``
    is exact; on ``back`` content may land rotated 180°.
:param depth_mm: Emboss/deboss depth in mm.  ``0`` picks a depth for
    *material* and for the content (a photo relief is bounded by how
    much part sits under the face); the response reports the depth
    used.
:param mode: ``"deboss"`` (cut into surface) or ``"emboss"`` (raised).
:param scale: Fraction of the face to cover (0.1-1.0, default 0.7).
:param material: Material for depth auto-tuning (default ``"PLA"``).
:param content_type: Override auto-detection: ``"svg"``, ``"image"``,
    ``"text"``.  Default ``"auto"`` detects from *content*.
:param offset_x_mm: Placement offset from the face centre along the
    face's own WIDTH axis, in mm — positive slides the content
    toward the content's right.  Offsets are FACE-LOCAL: they are
    applied inside the face-aligning rotation, so they always move
    the art in the face plane, never along its normal.
:param offset_y_mm: Same, along the face's HEIGHT axis — positive
    slides the content toward the content's top.  Measured
    world-axis mapping per face: top +y, bottom −y, front +z,
    back −z.
:param image_style: Image preprocessing style: ``"auto"`` (a logo or
    line-art image is traced as ``"stencil"``; a photo is sculpted and
    the look chosen for it), ``"coin"``, ``"cameo"``, ``"etched"``,
    ``"sketch"``, ``"medallion"``, ``"stencil"`` (alias ``"logo"``).
    An unknown style is refused naming the accepted list.
:param placement: Named position preset for content placement.
    ``"center"`` (default), ``"top"``, ``"bottom"``, ``"top-rim"``,
    ``"bottom-rim"``.  Use ``"bottom"`` for text below a centered
    portrait on a coaster.  Manual ``offset_x/y_mm`` is added on
    top of the preset for fine-tuning.
:param svg_id: Target a specific SVG group by ``id`` attribute when using
    SVG ``import()`` fallback on OpenSCAD 2024+.  E.g. ``"icon"`` targets
    ``<g id="icon">``.  No effect on the native polygon path.
:param svg_layer: Target a specific SVG layer by ``layer`` attribute when
    using SVG ``import()`` fallback on OpenSCAD 2024+.  E.g.
    ``"foreground"`` targets a layer named ``foreground``.
:param template_id: Optional template ID (e.g. ``"nameplate"``), used
    for provenance tracking only.  To auto-fill ``face``, ``depth_mm``,
    ``mode``, ``scale``, and ``image_style`` from a template's curated
    decoration profile, call ``resolve_template_decoration()`` first
    (kiln-pro) and pass its results explicitly.
:returns: Dict with output STL path, preview info, and metadata.
:param absolute_size_mm: Exact letter height (text) or mark width (marks)
    in mm, overriding *scale*; ``0`` leaves *scale* in charge.

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": {
      "model_path": "<model_path>",
      "content": "<content>"
    },
    "name": "decorate_surface"
  }
}

Input Schema

NameRequiredDescriptionDefault
faceNoWhich face to decorate: ``"auto"`` (largest flat face), ``"top"``, ``"bottom"``, ``"front"``, ``"back"``, ``"left"``, ``"right"``, or ``"wall"`` (wraps text, an SVG logo or a line-art mark around the upright round wall of a cup, jar, vase or bowl; STL and deboss only; a photo relief goes on a flat face). On ``"wall"``, *scale* is the letter height or mark width as a share of the wall, *absolute_size_mm* pins it exactly, and *offset_x/y_mm* / *placement* do not apply; the response reports the size and depth used. Placement on ``top``/``bottom``/``front`` is exact; on ``back`` content may land rotated 180°. Default: "auto".
modeNo``"deboss"`` (cut into surface) or ``"emboss"`` (raised). Default: "deboss".
scaleNoFraction of the face to cover (0.1-1.0, default 0.7). Default: 0.7.
svg_idNoTarget a specific SVG group by ``id`` attribute when using SVG ``import()`` fallback on OpenSCAD 2024+. E.g. ``"icon"`` targets ``<g id="icon">``. No effect on the native polygon path. Default: "".
contentYesWhat to put on the surface — file path (PNG/JPG/SVG) or ``"text:..."`` for text.
depth_mmNoEmboss/deboss depth in mm. ``0`` picks a depth for *material* and for the content (a photo relief is bounded by how much part sits under the face); the response reports the depth used. Default: 0.0.
materialNoMaterial for depth auto-tuning (default ``"PLA"``). Default: "PLA".
placementNoNamed position preset for content placement. ``"center"`` (default), ``"top"``, ``"bottom"``, ``"top-rim"``, ``"bottom-rim"``. Use ``"bottom"`` for text below a centered portrait on a coaster. Manual ``offset_x/y_mm`` is added on top of the preset for fine-tuning. Default: "center".
svg_layerNoTarget a specific SVG layer by ``layer`` attribute when using SVG ``import()`` fallback on OpenSCAD 2024+. E.g. ``"foreground"`` targets a layer named ``foreground``. Default: "".
model_pathYesPath to the base model (STL or OBJ).
image_styleNoImage preprocessing style: ``"auto"`` (a logo or line-art image is traced as ``"stencil"``; a photo is sculpted and the look chosen for it), ``"coin"``, ``"cameo"``, ``"etched"``, ``"sketch"``, ``"medallion"``, ``"stencil"`` (alias ``"logo"``). An unknown style is refused naming the accepted list. Default: "auto".
offset_x_mmNoPlacement offset from the face centre along the face's own WIDTH axis, in mm — positive slides the content toward the content's right. Offsets are FACE-LOCAL: they are applied inside the face-aligning rotation, so they always move the art in the face plane, never along its normal. Default: 0.0.
offset_y_mmNoSame, along the face's HEIGHT axis — positive slides the content toward the content's top. Measured world-axis mapping per face: top +y, bottom −y, front +z, back −z. Default: 0.0.
template_idNoOptional template ID (e.g. ``"nameplate"``), used for provenance tracking only. To auto-fill ``face``, ``depth_mm``, ``mode``, ``scale``, and ``image_style`` from a template's curated decoration profile, call ``resolve_template_decoration()`` first (kiln-pro) and pass its results explicitly. Default: "".
content_typeNoOverride auto-detection: ``"svg"``, ``"image"``, ``"text"``. Default ``"auto"`` detects from *content*. Default: "auto".
absolute_size_mmNoExact letter height (text) or mark width (marks) in mm, overriding *scale*; ``0`` leaves *scale* in charge. Default: 0.0.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed16 schema fields changedv1.5.1
    • changedInput schema / properties / absolute_size_mm / description
      Previous value: -"Default: 0.0."New value: +"Exact letter height (text) or mark width (marks) in mm, overriding *scale*; ``0`` leaves *scale* in charge. Default: 0.0."
    • addedInput schema / properties / content / description
      Added value: +"What to put on the surface — file path (PNG/JPG/SVG) or ``\"text:...\"`` for text."
    • changedInput schema / properties / content_type / description
      Previous value: -"Default: \"auto\"."New value: +"Override auto-detection: ``\"svg\"``, ``\"image\"``, ``\"text\"``.  Default ``\"auto\"`` detects from *content*. Default: \"auto\"."
    • changedInput schema / properties / depth_mm / description
      Previous value: -"Default: 0.0."New value: +"Emboss/deboss depth in mm.  ``0`` picks a depth for *material* and for the content (a photo relief is bounded by how much part sits under the face); the response reports the depth used. Default: 0.0."
    • changedInput schema / properties / face / description
      Previous value: -"Default: \"auto\"."New value: +"Which face to decorate: ``\"auto\"`` (largest flat face), ``\"top\"``, ``\"bottom\"``, ``\"front\"``, ``\"back\"``, ``\"left\"``, ``\"right\"``, or ``\"wall\"`` (wraps text, an SVG logo or a line-art mark around the upright round wall of a cup, jar, vase or bowl; STL and deboss only; a photo relief goes on a flat face).  On ``\"wall\"``, *scale* is the letter height or mark width as a share of the wall, *absolute_size_mm* pins it exactly, and *offset_x/y_mm* / *placement* do not apply; the response reports the size and depth used.  Placement on ``top``/``bottom``/``front`` is exact; on ``back`` content may land rotated 180°. Default: \"auto\"."
    • changedInput schema / properties / image_style / description
      Previous value: -"Default: \"auto\"."New value: +"Image preprocessing style: ``\"auto\"`` (a logo or line-art image is traced as ``\"stencil\"``; a photo is sculpted and the look chosen for it), ``\"coin\"``, ``\"cameo\"``, ``\"etched\"``, ``\"sketch\"``, ``\"medallion\"``, ``\"stencil\"`` (alias ``\"logo\"``). An unknown style is refused naming the accepted list. Default: \"auto\"."
    • changedInput schema / properties / material / description
      Previous value: -"Default: \"PLA\"."New value: +"Material for depth auto-tuning (default ``\"PLA\"``). Default: \"PLA\"."
    • changedInput schema / properties / mode / description
      Previous value: -"Default: \"deboss\"."New value: +"``\"deboss\"`` (cut into surface) or ``\"emboss\"`` (raised). Default: \"deboss\"."
    • addedInput schema / properties / model_path / description
      Added value: +"Path to the base model (STL or OBJ)."
    • changedInput schema / properties / offset_x_mm / description
      Previous value: -"Default: 0.0."New value: +"Placement offset from the face centre along the face's own WIDTH axis, in mm — positive slides the content toward the content's right.  Offsets are FACE-LOCAL: they are applied inside the face-aligning rotation, so they always move the art in the face plane, never along its normal. Default: 0.0."
    • changedInput schema / properties / offset_y_mm / description
      Previous value: -"Default: 0.0."New value: +"Same, along the face's HEIGHT axis — positive slides the content toward the content's top.  Measured world-axis mapping per face: top +y, bottom −y, front +z, back −z. Default: 0.0."
    • changedInput schema / properties / placement / description
      Previous value: -"Default: \"center\"."New value: +"Named position preset for content placement. ``\"center\"`` (default), ``\"top\"``, ``\"bottom\"``, ``\"top-rim\"``, ``\"bottom-rim\"``.  Use ``\"bottom\"`` for text below a centered portrait on a coaster.  Manual ``offset_x/y_mm`` is added on top of the preset for fine-tuning. Default: \"center\"."
    • changedInput schema / properties / scale / description
      Previous value: -"Default: 0.7."New value: +"Fraction of the face to cover (0.1-1.0, default 0.7). Default: 0.7."
    • changedInput schema / properties / svg_id / description
      Previous value: -"Default: \"\"."New value: +"Target a specific SVG group by ``id`` attribute when using SVG ``import()`` fallback on OpenSCAD 2024+.  E.g. ``\"icon\"`` targets ``<g id=\"icon\">``.  No effect on the native polygon path. Default: \"\"."
    • changedInput schema / properties / svg_layer / description
      Previous value: -"Default: \"\"."New value: +"Target a specific SVG layer by ``layer`` attribute when using SVG ``import()`` fallback on OpenSCAD 2024+.  E.g. ``\"foreground\"`` targets a layer named ``foreground``. Default: \"\"."
    • changedInput schema / properties / template_id / description
      Previous value: -"Default: \"\"."New value: +"Optional template ID (e.g. ``\"nameplate\"``), used for provenance tracking only.  To auto-fill ``face``, ``depth_mm``, ``mode``, ``scale``, and ``image_style`` from a template's curated decoration profile, call ``resolve_template_decoration()`` first (kiln-pro) and pass its results explicitly. Default: \"\"."
  2. Changed28 schema fields changedv1.5.0
    • removedInput schema / properties / absolute_size_mm / default
      Removed value: -0
    • addedInput schema / properties / absolute_size_mm / description
      Added value: +"Default: 0.0."
    • removedInput schema / properties / content_type / default
      Removed value: -"auto"
    • addedInput schema / properties / content_type / description
      Added value: +"Default: \"auto\"."
    • removedInput schema / properties / depth_mm / default
      Removed value: -0
    • addedInput schema / properties / depth_mm / description
      Added value: +"Default: 0.0."
    • removedInput schema / properties / face / default
      Removed value: -"auto"
    • addedInput schema / properties / face / description
      Added value: +"Default: \"auto\"."
    • removedInput schema / properties / image_style / default
      Removed value: -"auto"
    • addedInput schema / properties / image_style / description
      Added value: +"Default: \"auto\"."
    • removedInput schema / properties / material / default
      Removed value: -"PLA"
    • addedInput schema / properties / material / description
      Added value: +"Default: \"PLA\"."
    • removedInput schema / properties / mode / default
      Removed value: -"deboss"
    • addedInput schema / properties / mode / description
      Added value: +"Default: \"deboss\"."
    • removedInput schema / properties / offset_x_mm / default
      Removed value: -0
    • addedInput schema / properties / offset_x_mm / description
      Added value: +"Default: 0.0."
    • removedInput schema / properties / offset_y_mm / default
      Removed value: -0
    • addedInput schema / properties / offset_y_mm / description
      Added value: +"Default: 0.0."
    • removedInput schema / properties / placement / default
      Removed value: -"center"
    • addedInput schema / properties / placement / description
      Added value: +"Default: \"center\"."
    • removedInput schema / properties / scale / default
      Removed value: -0.7
    • addedInput schema / properties / scale / description
      Added value: +"Default: 0.7."
    • removedInput schema / properties / svg_id / default
      Removed value: -""
    • addedInput schema / properties / svg_id / description
      Added value: +"Default: \"\"."
    • removedInput schema / properties / svg_layer / default
      Removed value: -""
    • addedInput schema / properties / svg_layer / description
      Added value: +"Default: \"\"."
    • removedInput schema / properties / template_id / default
      Removed value: -""
    • addedInput schema / properties / template_id / description
      Added value: +"Default: \"\"."
  3. First observedv0.1.0

TDQS

A4.2/5.0
Behavior4/5

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

Annotations declare destructiveHint=true and readOnlyHint=false, and the description is consistent with that while adding real context: it writes a new STL rather than mutating in place, auto-picks face and scale, reports the depth/size actually used, refuses unknown styles, may rotate content 180° on the back face, and opens an interactive 3D stage with oversized meshes decimated. It stops short of stating overwrite/collision behaviour for the output path, which is the main missing behavioural detail for a destructive write.

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

Conciseness2/5

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

The routing statement and content-type/style sections are well front-loaded and earn their place, but the description then re-documents all 16 parameters in full, duplicating text the schema already carries at 100% coverage. The result is a very long definition whose second half is largely redundant with structured fields rather than adding value.

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?

For a 16-parameter tool with no output schema, the description covers what the return contains (STL path, preview info, metadata), the external dependency, per-face placement caveats, wall-mode constraints, and even host-dependent UI behaviour. An agent has everything needed to call it correctly and interpret the result.

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

Parameters3/5

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

Schema coverage is 100% and the per-parameter text in the description largely restates the schema fields verbatim, so it adds little beyond the structured data. The two worked examples showing parameter combinations (coin relief on a coaster, text on a keychain face) are the only genuine additions. Baseline 3 applies when the schema does the heavy lifting.

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?

States a specific verb and resource — put image/text/pattern onto a 3D model surface — and states the output (a new STL with the content embossed or debossed). It explicitly separates itself from the sibling texture tools ('For repeating patterns ... use apply_geometric_texture or apply_procedural_texture instead. This tool is for one-off content placement'), so the agent can route without opening a schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use and when-not-to-use conditions with named alternatives, plus decision guidance inside the tool itself (image_style 'stencil' for brand logos, 'auto' behaviour, wall mode limited to text/SVG/line-art on STL with deboss). It also names a prerequisite (OpenSCAD installed locally) that gates invocation.

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