Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
meshy-dev avatar

Meshy 3d Printing

  • 790 installs
  • 65 repo stars
  • Updated July 31, 2026
  • meshy-dev/meshy-3d-agent

meshy-3d-printing is a Claude Code skill from meshy-dev/meshy-3d-agent that helps developers prepare AI-generated 3D models for 3D printing workflows including mesh cleanup, export formats, and print-ready asset handoff.

About

meshy-3d-printing is a skill in the meshy-3d-agent repository focused on turning Meshy AI-generated 3D assets into printable models. It guides developers through mesh validation, export format choices, scale and wall-thickness checks, and handoff to slicer tools so generated geometry survives real fabrication. Teams use meshy-3d-printing when prototyping physical products, game collectibles, or demo hardware from generative meshes rather than manual CAD. The skill sits at the intersection of generative media APIs and maker hardware pipelines, emphasizing printability constraints that raw AI meshes often violate.

  • meshy-3d-printing
  • AI & Agent Building
  • AI-coding skill

Meshy 3d Printing by the numbers

  • 790 all-time installs (skills.sh)
  • +97 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #1,332 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/meshy-dev/meshy-3d-agent --skill meshy-3d-printing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs790
repo stars65
Last updatedJuly 31, 2026
Repositorymeshy-dev/meshy-3d-agent

How do you prepare AI meshes for 3D printing?

Helps with ai & agent building tasks.

Who is it for?

Developers or technical artists piping Meshy AI 3D output into FDM or resin printing pipelines for prototypes or merch.

Skip if: Pure software projects with no physical output or teams needing full CAD engineering instead of generative-to-print prep.

When should I use this skill?

A developer needs to convert Meshy-generated 3D models into printable STL or 3MF assets with mesh cleanup and slicer-ready settings.

What you get

Print-ready mesh exports, slicer settings notes, scale and wall-thickness checklist, and fabrication handoff documentation.

  • Print-ready mesh export
  • Printability checklist
  • Slicer settings notes

Files

SKILL.mdMarkdownGitHub ↗

Meshy 3D Printing

Prepare and send Meshy-generated 3D models to a slicer for 3D printing. Supports white model (single-color) and multicolor printing workflows with automatic slicer detection.

Prerequisite: This skill reuses the utility functions (create_task, poll_task, download, get_project_dir, etc.) and environment setup from meshy-3d-generation. However, when the user wants to 3D print, this skill controls the entire workflow — including generation, format selection, downloading, and slicer integration. Do NOT run meshy-3d-generation's workflow first and then hand off here — this skill must control parameters from the start (e.g. target_formats with "3mf" for multicolor).

---

Intent Detection

Proactively suggest 3D printing when these keywords appear in the user's request:

  • Direct: print, 3d print, slicer, slice, bambu, orca, prusa, cura, multicolor, multi-color, 3mf
  • Implied: figurine, miniature, statue, physical model, desk toy, phone stand

When detected, guide the user through the appropriate print pipeline below.

---

Decision Tree: White Model vs Multicolor

IMPORTANT: When the user wants to 3D print, follow this flow:

1. Detect installed slicers first (see Slicer Detection Script below) 2. Ask the user: "Do you want a single-color (white) print or multicolor?" 3. If white model → follow White Model Pipeline 4. If multicolor: a. Check if a multicolor-capable slicer is installed b. Supported multicolor slicers: OrcaSlicer, Bambu Studio, Creality Print, Elegoo Slicer, Anycubic Slicer Next c. If no multicolor slicer detected, warn the user and suggest installing one d. Ask: "How many colors? (default: 4, max: 16)" and "Segmentation depth? (3=coarse, 6=fine, default: 4)" e. Confirm cost: generation (20) + texture (10) + multicolor (10) = 40 credits total (+10 if repair is needed) f. Follow Multicolor Pipeline 5. (Recommended) Insert a printability analysis step (POST /openapi/v1/print/analyze, FREE) after generation in either pipeline. Run `POST /openapi/v1/print/repair` (10 credits) only if analyze flags errors.

---

Slicer Detection Script

Append this to the reusable script template from meshy-3d-generation:

import subprocess, shutil, platform, os, glob as glob_mod

SLICER_MAP = {
    "OrcaSlicer":           {"mac_app": "OrcaSlicer",          "win_exe": "orca-slicer.exe",         "win_dir": "OrcaSlicer",          "linux_exe": "orca-slicer"},
    "Bambu Studio":         {"mac_app": "BambuStudio",         "win_exe": "bambu-studio.exe",        "win_dir": "BambuStudio",         "linux_exe": "bambu-studio"},
    "Creality Print":       {"mac_app": "Creality Print",      "win_exe": "CrealityPrint.exe",       "win_dir": "Creality Print*",     "linux_exe": None},
    "Elegoo Slicer":        {"mac_app": "ElegooSlicer",        "win_exe": "elegoo-slicer.exe",       "win_dir": "ElegooSlicer",        "linux_exe": None},
    "Anycubic Slicer Next": {"mac_app": "AnycubicSlicerNext",  "win_exe": "AnycubicSlicerNext.exe",  "win_dir": "AnycubicSlicerNext",  "linux_exe": None},
    "PrusaSlicer":          {"mac_app": "PrusaSlicer",         "win_exe": "prusa-slicer.exe",        "win_dir": "PrusaSlicer",         "linux_exe": "prusa-slicer"},
    "UltiMaker Cura":       {"mac_app": "UltiMaker Cura",      "win_exe": "UltiMaker-Cura.exe",     "win_dir": "UltiMaker Cura*",     "linux_exe": None},
}
MULTICOLOR_SLICERS = {"OrcaSlicer", "Bambu Studio", "Creality Print", "Elegoo Slicer", "Anycubic Slicer Next"}

def detect_slicers():
    """Detect installed slicer software. Returns list of {name, path, multicolor}."""
    found = []
    system = platform.system()
    for name, info in SLICER_MAP.items():
        path = None
        if system == "Darwin":
            app = info.get("mac_app")
            if app and os.path.exists(f"/Applications/{app}.app"):
                path = f"/Applications/{app}.app"
        elif system == "Windows":
            win_dir = info.get("win_dir", "")
            win_exe = info.get("win_exe", "")
            for base in [os.environ.get("ProgramFiles", r"C:\Program Files"),
                         os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)")]:
                if "*" in win_dir:
                    matches = glob_mod.glob(os.path.join(base, win_dir, win_exe))
                    if matches:
                        path = matches[0]
                        break
                else:
                    candidate = os.path.join(base, win_dir, win_exe)
                    if os.path.exists(candidate):
                        path = candidate
                        break
        else:  # Linux
            exe = info.get("linux_exe")
            if exe:
                path = shutil.which(exe)
        if path:
            found.append({"name": name, "path": path, "multicolor": name in MULTICOLOR_SLICERS})
    return found

def open_in_slicer(file_path, slicer_name):
    """Open a model file in the specified slicer."""
    info = SLICER_MAP.get(slicer_name, {})
    system = platform.system()
    abs_path = os.path.abspath(file_path)
    if system == "Darwin":
        app = info.get("mac_app", slicer_name)
        subprocess.run(["open", "-a", app, abs_path])
    elif system == "Windows":
        exe = info.get("win_exe")
        exe_path = shutil.which(exe) if exe else None
        if exe_path:
            subprocess.Popen([exe_path, abs_path])
        else:
            os.startfile(abs_path)
    else:
        exe = info.get("linux_exe")
        exe_path = shutil.which(exe) if exe else None
        if exe_path:
            subprocess.Popen([exe_path, abs_path])
        else:
            subprocess.run(["xdg-open", abs_path])
    print(f"Opened {abs_path} in {slicer_name}")

# --- Detect slicers ---
slicers = detect_slicers()
if slicers:
    print("Installed slicers:")
    for s in slicers:
        mc = " [multicolor]" if s["multicolor"] else ""
        print(f"  - {s['name']}{mc}: {s['path']}")
else:
    print("No slicer software detected. Install one of: OrcaSlicer, Bambu Studio, PrusaSlicer, etc.")

---

Printability Analysis & Repair (FREE → optional 10-credit fix)

Before downloading and printing, run the automated printability check to decide whether the mesh needs repair. The analyze step is FREE (0 credits), so there's no reason to skip it for production prints.

Analyze Script

# Run after the generation/refine/retexture step that produced your printable mesh
INPUT_TASK_ID = refine_id  # or whatever produced the textured / final mesh
# IMPORTANT: input_task_id MUST refer to a task that used Meshy 6 or any Preview model.
# For Meshy 4/5 outputs, pass `model_url` (the GLB download URL) instead.

analyze_id = create_task("/openapi/v1/print/analyze", {
    "input_task_id": INPUT_TASK_ID,
    # OR: "model_url": "https://example.com/model.glb"
})

analyze_task = poll_task("/openapi/v1/print/analyze", analyze_id)

p = analyze_task.get("printability") or {}
metrics = p.get("metrics", {})
status = p.get("status", "unknown")

print(f"Printability: {status} (issues: {p.get('issue_count', 0)} = "
      f"errors {p.get('error_count', 0)} + warnings {p.get('warning_count', 0)})")
print(f"  watertight={metrics.get('is_watertight')}, "
      f"volume={metrics.get('volume')} m³, "
      f"non_manifold_edges={metrics.get('non_manifold_edges')}, "
      f"degenerate_faces={metrics.get('degenerate_faces')}, "
      f"holes={metrics.get('holes')}")

needs_repair = status == "error"  # warning is optional; error means won't print well

Status meanings:

  • healthy — print as-is.
  • warning — degenerate faces or holes present. Repair is OPTIONAL but recommended for thin-feature prints.
  • error — non-watertight, non-positive volume, or non-manifold edges. Recommend repair before printing.
  • unknown — analyze couldn't process the model. Inspect manually or retry.

Repair Script (only if analyze flagged errors)

if needs_repair:
    repair_id = create_task("/openapi/v1/print/repair", {
        "input_task_id": INPUT_TASK_ID,    # output is GLB
        # OR: "model_url": "https://example.com/model.stl"   # output is STL
    })
    repair_task = poll_task("/openapi/v1/print/repair", repair_id)

    # Output format mirrors input. Find the populated field:
    repaired_url = next(
        (url for url in repair_task["model_urls"].values() if url),
        None
    )
    # Use this repaired URL for downstream download / multicolor / slicer steps.

Note: repair preserves geometry only, not textures. If you need a textured + repaired model for multicolor printing, run repair first, then re-texture (or feed repair's task_id to multi-color directly — the API handles re-texturing internally if applicable).

---

White Model Print Pipeline

StepActionCreditsNotes
1Detect installed slicers0Run slicer detection script
2Generate untextured model5–20Text to 3D or Image to 3D (should_texture: False)
3Download OBJ0OBJ format for slicer compatibility
4Fix OBJ for printing0Coordinate conversion (see below)
5Open in slicer0open_in_slicer(obj_path, slicer_name)

White Model Generation + Print Script

Use the create_task/poll_task/download/get_project_dir helpers from meshy-3d-generation, then:

# --- Step 2: Generate untextured model for printing ---
# Text to 3D:
task_id = create_task("/openapi/v2/text-to-3d", {
    "mode": "preview",
    "prompt": "USER_PROMPT",
    "ai_model": "latest",
    "target_formats": ["obj"],  # Only OBJ for white model printing
})
# OR Image to 3D:
# task_id = create_task("/openapi/v1/image-to-3d", {
#     "image_url": "IMAGE_URL",
#     "should_texture": False,          # White model — no texture
#     "target_formats": ["glb", "obj"], # OBJ needed for slicer
# })

task = poll_task("/openapi/v2/text-to-3d", task_id)  # adjust endpoint for image-to-3d
project_dir = get_project_dir(task_id, task.get("prompt", "print"))

# --- Step 3-4: Download OBJ + fix for printing ---
obj_url = task["model_urls"].get("obj")
if not obj_url:
    print("OBJ format not available. Available:", list(task["model_urls"].keys()))
    print("Download GLB and import manually into your slicer.")
    obj_url = task["model_urls"].get("glb")

obj_path = os.path.join(project_dir, "model.obj")
download(obj_url, obj_path)

# --- Post-process OBJ for slicer compatibility ---
def fix_obj_for_printing(input_path, output_path=None, target_height_mm=75.0):
    """
    Fix OBJ coordinate system, scale, and position for 3D printing slicers.
    - Rotates from glTF Y-up to slicer Z-up: (x, y, z) -> (x, -z, y)
    - Scales model to target_height_mm (default 75mm)
    - Centers model on XY plane
    - Aligns model bottom to Z=0
    """
    if output_path is None:
        output_path = input_path

    lines = open(input_path, "r").readlines()

    rotated = []
    min_x, max_x = float("inf"), float("-inf")
    min_y, max_y = float("inf"), float("-inf")
    min_z, max_z = float("inf"), float("-inf")
    for line in lines:
        if line.startswith("v "):
            parts = line.split()
            x, y, z = float(parts[1]), float(parts[2]), float(parts[3])
            rx, ry, rz = x, -z, y
            min_x, max_x = min(min_x, rx), max(max_x, rx)
            min_y, max_y = min(min_y, ry), max(max_y, ry)
            min_z, max_z = min(min_z, rz), max(max_z, rz)
            rotated.append(("v", rx, ry, rz, parts[4:]))
        elif line.startswith("vn "):
            parts = line.split()
            nx, ny, nz = float(parts[1]), float(parts[2]), float(parts[3])
            rotated.append(("vn", nx, -nz, ny, []))
        else:
            rotated.append(("line", line))

    model_height = max_z - min_z
    scale = target_height_mm / model_height if model_height > 1e-6 else 1.0
    x_offset = -(min_x + max_x) / 2.0 * scale
    y_offset = -(min_y + max_y) / 2.0 * scale
    z_offset = -(min_z * scale)

    with open(output_path, "w") as f:
        for item in rotated:
            if item[0] == "v":
                _, rx, ry, rz, extra = item
                tx = rx * scale + x_offset
                ty = ry * scale + y_offset
                tz = rz * scale + z_offset
                extra_str = " " + " ".join(extra) if extra else ""
                f.write(f"v {tx:.6f} {ty:.6f} {tz:.6f}{extra_str}\n")
            elif item[0] == "vn":
                _, nx, ny, nz, _ = item
                f.write(f"vn {nx:.6f} {ny:.6f} {nz:.6f}\n")
            else:
                f.write(item[1])

    print(f"OBJ fixed: rotated Y-up→Z-up, scaled to {target_height_mm:.0f}mm, centered, bottom at Z=0")
    print(f"Output: {os.path.abspath(output_path)}")

fix_obj_for_printing(obj_path, target_height_mm=75.0)

# --- Open in slicer ---
if slicers:
    open_in_slicer(obj_path, slicers[0]["name"])
else:
    print(f"\nModel ready: {os.path.abspath(obj_path)}")
    print("Open this file in your preferred slicer: File → Import / Open")
Parameters:
- target_height_mm: Default 75mm. Adjust based on user's request (e.g. "print at 15cm" → 150.0).

---

Multicolor Print Pipeline

StepActionCreditsNotes
1Detect slicers + check multicolor0Warn if no multicolor slicer
2Generate 3D model20Text to 3D or Image to 3D
3Add textures10Refine or Retexture (REQUIRED)
4Multi-color processing10POST /openapi/v1/print/multi-color
5Poll until SUCCEEDED0GET /openapi/v1/print/multi-color/{id}
6Download 3MF0From model_urls["3mf"]
7Open in multicolor slicer0open_in_slicer(path, slicer)
Total40

Multi-Color Full Script

Use the create_task/poll_task/download/get_project_dir helpers from meshy-3d-generation:

# --- Step 1: Check for multicolor slicer (already done above) ---
mc_slicers = [s for s in slicers if s["multicolor"]]
if not mc_slicers:
    print("WARNING: No multicolor-capable slicer detected.")
    print("Supported: OrcaSlicer, Bambu Studio, Creality Print, Elegoo Slicer, Anycubic Slicer Next")
    print("Install one before proceeding.")
else:
    print(f"Multicolor slicer(s): {', '.join(s['name'] for s in mc_slicers)}")

# --- Step 2-3: Generate + texture (with 3mf in target_formats!) ---
# Text to 3D preview:
preview_id = create_task("/openapi/v2/text-to-3d", {
    "mode": "preview",
    "prompt": "USER_PROMPT",
    "ai_model": "latest",
    # No target_formats needed — 3MF comes from the multi-color API, not from generate/refine
})
poll_task("/openapi/v2/text-to-3d", preview_id)

# Refine (add textures — REQUIRED for multicolor):
refine_id = create_task("/openapi/v2/text-to-3d", {
    "mode": "refine",
    "preview_task_id": preview_id,
    "enable_pbr": True,
})
refine_task = poll_task("/openapi/v2/text-to-3d", refine_id)
project_dir = get_project_dir(preview_id, "multicolor-print")

# OR for Image to 3D with texture:
# task_id = create_task("/openapi/v1/image-to-3d", {
#     "image_url": "IMAGE_URL",
#     "should_texture": True,
#     # No target_formats needed — 3MF comes from multi-color API
# })
# refine_task = poll_task("/openapi/v1/image-to-3d", task_id)

INPUT_TASK_ID = refine_id  # Use the textured task
MAX_COLORS = 4   # 1-16, ask user
MAX_DEPTH = 4    # 3-6, ask user

mc_task_id = create_task("/openapi/v1/print/multi-color", {
    "input_task_id": INPUT_TASK_ID,
    "max_colors": MAX_COLORS,
    "max_depth": MAX_DEPTH,
})
print(f"Multi-color task created: {mc_task_id} (10 credits)")

task = poll_task("/openapi/v1/print/multi-color", mc_task_id)

# --- Download 3MF ---
threemf_url = task["model_urls"]["3mf"]
threemf_path = os.path.join(project_dir, "multicolor.3mf")
download(threemf_url, threemf_path)
print(f"3MF ready: {os.path.abspath(threemf_path)}")

# --- Open in multicolor slicer ---
if mc_slicers:
    open_in_slicer(threemf_path, mc_slicers[0]["name"])
else:
    print(f"Open {threemf_path} in a multicolor-capable slicer manually.")

---

Manual Sanity Checks (in addition to the automated analyze API)

The analyze API covers geometric correctness (watertight, manifold edges, degenerate faces, holes). Some print-quality concerns still need a human eye in the slicer:

CheckRecommendationWhere to verify
Wall thicknessMinimum 1.2mm for FDM, 0.8mm for resinSlicer (after import)
OverhangsKeep below 45° or add supportsSlicer support generation
Minimum detailAt least 0.4mm for FDM, 0.05mm for resinVisual inspection in slicer
Base stabilityFlat base or add brim/raft in slicerSlicer plate adhesion
HollowingConsider hollowing for figurines/miniaturesSlicer hollow tool (resin)

The automated analyze API now handles: watertightness, volume, non-manifold edges, degenerate faces, holes — these no longer require manual inspection.

---

Key Rules for Print Workflow

  • Always detect slicer first and report results to the user before proceeding
  • Always run analyze (FREE) for production / functional prints, miniatures with thin features, mechanical parts
  • Repair is conditional: only when analyze status = error, or warning if the user cares about quality
  • White model: Download OBJ format, apply fix_obj_for_printing() for coordinate conversion
  • Multicolor: The multi-color API outputs 3MF directly — no coordinate conversion needed (3MF uses Z-up natively)
  • 3MF for multicolor: The Multi-Color Print API outputs 3MF directly — no need to request 3MF from generate/refine via target_formats. For non-print use cases that need 3MF, pass "3mf" in target_formats at generation time.
  • For multicolor, verify slicer supports it before proceeding with the (costly) pipeline
  • After opening in slicer, remind user to check print settings (layer height, infill, supports)
  • If OBJ is not available: Download GLB and guide user to import manually
  • Repair caveat: textures are NOT preserved. For a multicolor print on a model that needs repair, run repair first, then re-texture, then multicolor.

---

Additional Resources

For the complete API endpoint reference, read reference.md.

Related skills

FAQ

What does meshy-3d-printing help developers produce?

meshy-3d-printing helps developers turn Meshy-generated models into print-ready STL or 3MF exports. The skill covers mesh validation, scale checks, and slicer handoff so AI geometry survives real fabrication.

When should meshy-3d-printing be invoked?

meshy-3d-printing fits when generative 3D output must become a physical prototype or product sample. Invoke it after Meshy asset generation and before sending files to a slicer or printer.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.