Skip to content

Latest commit

Β 

History

61 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PrintMCP

From "I want to print a coffee cup" to a finished print β€” driven by your AI agent.

PrintMCP is a Model Context Protocol server that automates the entire 3D-printing pipeline: find a model, slice it to G-code, and print it β€” all through tools an AI assistant can call.

Website CI Python Protocol Built with uv Pipeline License: Apache 2.0 GitHub stars

🌐 View the website β†’ β€” interactive demo, pipeline visualization, and full documentation.

If PrintMCP is useful to you, please ⭐ star the repo β€” it helps others find it.


🧭 The pipeline

PrintMCP is built in three levels. Each level is a group of tools, and together they form one continuous workflow from a vague idea to plastic on the bed.

flowchart LR
    Start(["πŸ—£οΈ User request"]) --> S1
    subgraph L1["1 Β· Source β€” Thingiverse"]
        direction TB
        S1["search_models"] --> S2["get_model"] --> S3["download_model"]
    end
    subgraph L2["2 Β· Slice β€” Cura / OrcaSlicer"]
        direction TB
        SL["cura_slice_model"]
        OR["orca_slice_model / orca_list_profiles"]
    end
    subgraph L3["3 Β· Print β€” OctoPrint"]
        direction TB
        P1["upload_file"] --> P2["start_print"] --> P3["get_job"]
    end
    S3 --> SL --> P1
    P3 --> Done(["βœ… Finished print"])
Loading
Level Scope Backend Status
1 Β· Source Search for and download 3D model files Thingiverse REST API βœ… Implemented
2 Β· Slice Slice models into printer-ready G-code Ultimaker Cura (headless CuraEngine) or OrcaSlicer βœ… Implemented
3 Β· Print Upload, start, monitor, and control prints OctoPrint REST API βœ… Implemented

πŸ“‘ Table of contents


✨ Highlights

  • One server, the whole pipeline. Search β†’ download β†’ slice β†’ print, without leaving your assistant.
  • License-aware sourcing. Every model's license is surfaced before you download, so you don't misuse it.
  • Real slicing, real estimates. Slice with Ultimaker Cura's CuraEngine or OrcaSlicer (CLI, native or Flatpak), and report the true print time and filament usage from the engine itself.
  • Safe by default. Tools that physically actuate the printer (heaters, motors) refuse to act unless you explicitly pass confirm=true β€” see Safety model.
  • Structured or human output. Every tool accepts response_format (markdown or json).
  • Zero-secret-in-output design. Credentials live in .env and are sent only to the services they belong to.

πŸ“š Documentation

Full guides, a per-tool reference, and step-by-step tutorials live in docs/.

Start here Then
πŸ“– Documentation hub the index of everything below
πŸš€ Getting Started install, configure, connect a client
βš™οΈ Configuration every env var + where files are stored
πŸ›‘οΈ Safety Model how confirm=true protects your machine
πŸ”§ Troubleshooting common errors β†’ fixes
πŸ›οΈ Architecture how it's built (for contributors)

Tutorials β€” learn to 3D print by chatting with your assistant:

  1. Find Something to Print
  2. Get It Print-Ready
  3. Send It to Your Printer
  4. From Idea to Object

For developers β€” tool reference & API: the shared invocation contract, plus per-level details for Thingiverse, Cura, and OctoPrint.


πŸ›‘οΈ Safety model

Warning

Level 3 drives a real machine. A bad tool call could heat a nozzle, move an axis, or abandon a print.

To prevent accidents, every physical-actuation tool defaults to a dry run. Called without confirm, it describes exactly what would happen and sends nothing to the printer. Pass confirm=true to actually act.

octoprint_start_print(path="cup.gcode")              β†’ 🟑 dry run: "this would start printing cup.gcode"
octoprint_start_print(path="cup.gcode", confirm=true) β†’ 🟒 starts the print

Note

Read-only tools (octoprint_get_status, octoprint_list_files, octoprint_get_job) never need confirm. Temperatures are also sanity-checked (e.g. the bed is capped at ~140 Β°C) so a typo can't command a wild value.


🧰 Tool reference

All tools accept response_format (markdown or json). Tools marked πŸ”’ physically actuate the printer and require confirm=true; without it they return a harmless dry-run preview.

Level 1 Β· Source β€” Thingiverse

Tool What it does
thingiverse_search_models Keyword search for printable "things"; returns candidates with IDs.
thingiverse_get_model Details for one thing: license, description, and downloadable files.
thingiverse_download_model Download a thing's files (printable models by default) to local disk.

Level 2 Β· Slice β€” Cura or OrcaSlicer

PrintMCP ships two interchangeable slicer backends; use whichever you have installed. Both are auto-detected.

Tool What it does
cura_slice_model Slice a local .stl/.obj/.3mf/.amf/.ply into G-code via CuraEngine. Choose printer, layer height, infill, supports, adhesion, and temperatures; returns the G-code path plus estimated print time and filament.
orca_slice_model Slice a local model into G-code via OrcaSlicer's CLI using its 3-tier presets (machine + process + filament). Works with native or Flatpak installs. Returns the G-code path plus estimated print time and filament.
orca_list_profiles List available OrcaSlicer presets by tier (machine/process/filament), with an optional name filter β€” use it to find the exact preset names orca_slice_model needs.

Level 3 Β· Print β€” OctoPrint

Tool What it does
octoprint_get_status Connection state, printer state, and live tool/bed temperatures. πŸ‘οΈ
octoprint_list_files List G-code files on the server, with their server-side paths. πŸ‘οΈ
octoprint_get_job Active job: file, % complete, elapsed, and estimated time remaining. πŸ‘οΈ
octoprint_connect Open or close the printer's serial connection. πŸ”’
octoprint_upload_file Upload a local .gcode to the server (optionally select/print). πŸ”’ΒΉ
octoprint_start_print Select a server-side file and begin printing. πŸ”’
octoprint_control_job Pause, resume, or cancel the running job. πŸ”’
octoprint_set_temperature Set a tool (nozzle) or bed target temperature. πŸ”’
octoprint_home Home one or more axes. πŸ”’
octoprint_move Jog the print head by a relative offset. πŸ”’

πŸ‘οΈ read-only Β· πŸ”’ requires confirm=true Β· ΒΉ uploading alone is safe; only starting a print needs confirm.


πŸ“¦ Requirements

Needed for Notes
Python β‰₯ 3.10 everything β€”
uv everything Project & dependency manager.
Thingiverse API token Level 1 Free β€” register an app.
Ultimaker Cura Level 2 (Cura) Its bundled CuraEngine is auto-detected on Windows.
OrcaSlicer Level 2 (Orca) Native or Flatpak; CLI and presets are auto-detected. Either slicer satisfies Level 2.
An OctoPrint server + API key Level 3 Any printer running OctoPrint on your network.

Tip

The levels are independent. You can use Level 1 with just a Thingiverse token, add Cura later for slicing, and wire up OctoPrint whenever your printer is ready.


πŸš€ Quick start

Install from PyPI

uv tool install printmcp      # or:  pipx install printmcp

This puts a printmcp command on your PATH. You can also run it without installing:

uvx printmcp

Install from source

git clone https://github.com/SourceBox-LLC/PrintMCP
cd PrintMCP
uv sync                       # creates .venv, installs PrintMCP + dev tools

Then: configure and run

# Configure your secrets (in the working directory you'll run from)
cp .env.example .env          # Windows: copy .env.example .env
#   …then edit .env (see Configuration below)

# Run the server (stdio β€” it blocks waiting for an MCP client; that's expected)
printmcp                      # if installed; from source: uv run printmcp

You normally won't run the server by hand β€” you register it with a client, which launches it for you.


βš™οΈ Configuration

PrintMCP reads configuration from environment variables. A .env file in the project root is loaded automatically (and is git-ignored, so your secrets stay local).

Variable Required Default Purpose
THINGIVERSE_TOKEN Level 1 β€” Thingiverse REST API App Token.
PRINTMCP_DOWNLOAD_DIR β€” OS Downloads folder (e.g. %USERPROFILE%\Downloads, ~/Downloads); falls back to ~/PrintMCP/downloads if not found Where downloaded models are saved.
PRINTMCP_CURA_DIR β€” auto-detected Ultimaker Cura install folder (e.g. C:\Program Files\UltiMaker Cura 5.11.0). Set only if auto-detection fails.
PRINTMCP_CURAENGINE β€” <cura>/CuraEngine.exe Full path to the CuraEngine executable, if it lives outside the Cura folder.
PRINTMCP_ORCA_COMMAND β€” auto-detected OrcaSlicer launch command, e.g. orca-slicer or flatpak run com.orcaslicer.OrcaSlicer. Set only if auto-detection fails.
PRINTMCP_ORCA_PROFILES β€” auto-detected OrcaSlicer's bundled .../share/OrcaSlicer/profiles directory (the vendor folders of machine/process/filament presets).
OCTOPRINT_URL Level 3 β€” Base URL of your OctoPrint server, e.g. http://octopi.local or http://192.168.1.50:80.
OCTOPRINT_API_KEY Level 3 β€” OctoPrint API key. Sent only in the X-Api-Key header to OCTOPRINT_URL.
Where do I get each credential?
  • Thingiverse token β€” Create an app at https://www.thingiverse.com/apps/create and copy its App Token.
  • OctoPrint API key β€” In OctoPrint: Settings β†’ API (global key), or generate a per-user Application Key under your user account. Either works.

πŸ”Œ Register with an MCP client

PrintMCP runs as a stdio server any MCP client can launch. PrintPal is one such client; you can also point your own agent β€” Claude Code, Claude Desktop, Cursor, Windsurf, opencode β€” at it directly.

Automatic

The setup script detects your installed MCP clients (Claude Code, Claude Desktop, Cursor, Windsurf, opencode), lets you pick one, and configures it for you. By default it registers the published package (uvx printmcp); pass --directory <path> / -Directory <path> to register a local checkout instead.

# macOS / Linux β€” run from anywhere
curl -fsSL https://raw.githubusercontent.com/SourceBox-LLC/PrintMCP/master/scripts/setup-mcp.sh | bash
# or, from a clone:  ./scripts/setup-mcp.sh
# Windows (PowerShell) β€” from a clone
.\scripts\setup-mcp.ps1

Important

Close the client first. MCP clients rewrite their config when they exit, so a setup that runs while the client is open gets clobbered. If the client you choose is running, the script tells you to quit it and run again. See scripts/README.md.

Manual

Add the server to your client's MCP config. Most users want the published package (uvx printmcp) β€” no clone needed:

Claude Desktop / Cursor / Windsurf (mcpServers format)
{
  "mcpServers": {
    "printmcp": {
      "command": "uvx",
      "args": ["printmcp"]
    }
  }
}
Claude Code CLI
claude mcp add --scope user --transport stdio printmcp -- uvx printmcp
opencode (opencode.json)
{
  "mcp": {
    "printmcp": {
      "type": "local",
      "command": ["uvx", "printmcp"],
      "enabled": true
    }
  }
}

Working on PrintMCP itself? Use a local checkout

Contributors developing PrintMCP alongside its clients should point the client at their clone (so edits take effect immediately) instead of the published package:

{
  "mcpServers": {
    "printmcp": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/PrintMCP", "printmcp"]
    }
  }
}

πŸ’‘ Example: coffee cup to print

You don't call tools β€” you just talk to your assistant, and it drives the whole pipeline. A full run sounds like this:

πŸ’¬ You: "I want to 3D print a coffee cup. Find one, get it ready for my Ender 3, and start it."

πŸ€– Assistant: "I found a few coffee cups on Thingiverse β€” here are the top three…"

πŸ’¬ You: "The first one."

πŸ€– Assistant: "Good pick β€” it's licensed Creative Commons (free to print). I've downloaded and sliced it for your Ender-3 Pro: about 6h 31m and ~25.5 m of filament. Before I start the physical printer β€” ready for me to begin?"

πŸ’¬ You: "Yes, go."

πŸ€– Assistant: "Printing now! πŸŽ‰ Ask me any time for progress."

πŸ’¬ You: (later) "How's it going?"

πŸ€– Assistant: "About 42% done β€” roughly 2h 14m left."

One request, one finished cup. The assistant handles the busywork (searching, downloading, slicing, uploading); you make the decisions that matter β€” which model, and the go-ahead to start.

Note

Anything that touches the physical printer β€” heating, moving, starting a print β€” pauses for your confirmation first. Everything up to slicing is purely local and needs no go-ahead. See the Safety Model.

Want the step-by-step version? The tutorials walk through it in plain conversation.


πŸ—‚οΈ Project structure

PrintMCP/
β”œβ”€β”€ src/printmcp/
β”‚   β”œβ”€β”€ app.py          # shared FastMCP instance
β”‚   β”œβ”€β”€ server.py       # entry point β€” registers tools, runs over stdio
β”‚   β”œβ”€β”€ config.py       # env-driven config (tokens, Cura + OrcaSlicer paths, OctoPrint URL/key)
β”‚   β”œβ”€β”€ thingiverse.py  # Level 1 β€” search & download
β”‚   β”œβ”€β”€ cura.py         # Level 2 β€” slice via CuraEngine
β”‚   β”œβ”€β”€ orca.py         # Level 2 β€” list presets & slice via OrcaSlicer CLI
β”‚   └── octoprint.py    # Level 3 β€” print management
β”œβ”€β”€ docs/                # full documentation (guides, tool reference, tutorials)
β”‚   β”œβ”€β”€ README.md        # documentation hub
β”‚   β”œβ”€β”€ getting-started.md, configuration.md, safety.md, troubleshooting.md, architecture.md
β”‚   β”œβ”€β”€ tools/           # per-level tool reference
β”‚   └── tutorials/       # step-by-step walkthroughs
β”œβ”€β”€ tests/               # offline tests (validation + mock-transport HTTP)
β”œβ”€β”€ .env.example
β”œβ”€β”€ pyproject.toml
└── README.md

πŸ§ͺ Development

uv run pytest                       # tests
uvx ruff check src tests            # lint
uvx ruff format --check src tests   # formatting

CI runs all three on every push and PR (tests across Python 3.10–3.13).

The suite is fully offline β€” it requires no token, network, or Cura install and runs in under two seconds. It covers:

  • Input validation & helpers β€” tool registration, filename sanitization, slice-input ranges, stats parsing.
  • The Level 3 safety gate β€” every actuating tool refuses to act (and sends nothing) without confirm=true.
  • OctoPrint HTTP plumbing β€” using a mock transport, it asserts the exact method, path, JSON body, and X-Api-Key header of every request, that responses parse correctly, and that error statuses (401/409/ connection-refused) map to friendly messages β€” all without a printer.
  • OrcaSlicer plumbing (test_orca.py) β€” preset name resolution across vendor dirs and the global library, scalar override application, per-OS binary/profile discovery (monkeypatched), flatpak --filesystem grant ordering in the launch argv, and G-code footer stats parsing β€” all offline against a synthetic profiles tree.
  • The real stdio transport (test_stdio.py) β€” spawns python -m printmcp as a subprocess, speaks the MCP JSON-RPC protocol over stdio with the official client, and round-trips a tool call. Catches startup/registration failures and any accidental stdout writes that would corrupt the stream β€” without network or a printer.

Developing with PrintPal

PrintPal (the terminal UI) launches PrintMCP as a subprocess. To have PrintPal use your local PrintMCP checkout instead of the PyPI release while you edit tools, set PRINTPAL_PRINTMCP_COMMAND before starting it:

export PRINTPAL_PRINTMCP_COMMAND="uv run --directory /path/to/PrintMCP printmcp"
# then, from your PrintPal checkout:  uv run printpal

PrintPal's banner shows which server it connected to. See the PrintPal README for details.

Notable changes are tracked in CHANGELOG.md; releasing is documented in docs/RELEASING.md.


πŸ—ΊοΈ Roadmap

  • More print backends β€” a Moonraker/Klipper backend exposing moonraker_* tools alongside the OctoPrint ones, so non-OctoPrint printers work too.
  • Slicing depth β€” more printer profiles and quality presets, and surfacing CuraEngine warnings (e.g. a model larger than the build volume).
  • More model sources β€” Printables, MyMiniFactory, and others behind a shared search interface.

βš–οΈ Model licensing

Models on Thingiverse carry their own licenses (often Creative Commons; some are non-commercial). thingiverse_get_model and thingiverse_download_model surface each model's license β€” respect it before reusing, remixing, or selling a print.


πŸ“„ License

Licensed under the Apache License 2.0 β€” Β© 2026 SourceBox LLC.

You may freely use, modify, and distribute this software, including for commercial purposes, provided you retain the copyright and license notices and state any significant changes. The license also includes an express patent grant. It comes with no warranty. See the LICENSE file for the full text.

Note

This license covers PrintMCP's own code only. Third-party tools it drives (Ultimaker Cura, OctoPrint) and any 3D models you download carry their own licenses β€” see Model licensing above.

About

A self-hosted MCP server completely automating the 3D printing pipeline. Search and download files from Thingiverse, load and slice files with UltiMaker Cura, and print with Octoprint.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages