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.
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 "]
direction TB
SL[cura_slice_model]
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])
| 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) | β Implemented |
| 3 Β· Print | Upload, start, monitor, and control prints | OctoPrint REST API | β Implemented |
- β¨ Highlights
- π‘οΈ Safety model
- π§° Tool reference
- π¦ Requirements
- π Quick start
- βοΈ Configuration
- π Register with an MCP client
- π‘ Example: coffee cup to print
- ποΈ Project structure
- π§ͺ Development
- πΊοΈ Roadmap
- βοΈ Model licensing
- π License
- 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. Drives the same CuraEngine that Ultimaker Cura ships, and reports 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(markdownorjson). - Zero-secret-in-output design. Credentials live in
.envand are sent only to the services they belong to.
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.
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.
| 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. |
| Tool | What it does |
|---|---|
cura_slice_model |
Slice a local .stl/.obj/.3mf/.amf/.ply into G-code. Choose printer, layer height, infill, supports, adhesion, and temperatures; returns the G-code path plus estimated print time and filament. |
| 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.
| 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 | Its bundled CuraEngine is auto-detected on Windows. |
| 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.
# 1. Install (creates .venv, installs PrintMCP + dev tools, writes uv.lock)
uv sync
# 2. Configure your secrets
cp .env.example .env # Windows: copy .env.example .env
# β¦then edit .env (see Configuration below)
# 3. Run the server (stdio β it waits for an MCP client; that's expected)
uv run printmcpYou normally won't run the server by hand β you register it with a client, which launches it for you.
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 |
β | ~/PrintMCP/downloads |
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. |
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.
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"printmcp": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\Users\\Sbuss\\Documents\\Software Development\\Projects\\PrintMCP",
"printmcp"
]
}
}
}Claude Code CLI
claude mcp add printmcp -- uv run --directory "C:\Users\Sbuss\Documents\Software Development\Projects\PrintMCP" printmcpTip
Point --directory at wherever you cloned PrintMCP. The client launches the server and talks to it over stdio.
A full pipeline run, the way an assistant would drive it:
1. thingiverse_search_models(query="coffee cup")
β browse results, pick an id
2. thingiverse_get_model(thing_id=4928322)
β check the LICENSE and the file list
3. thingiverse_download_model(thing_id=4928322)
β .stl files land in your download directory
4. cura_slice_model(model_path="β¦/cup.stl")
β writes cup.gcode (Ender-3 Pro, 0.2 mm, 20% infill)
+ reports "β 6h 31m, 25.5 m filament"
5. octoprint_get_status()
β confirm the printer is connected and ready
(octoprint_connect(confirm=true) if not)
6. octoprint_upload_file(gcode_path="β¦/cup.gcode")
β note the returned server path
7. octoprint_start_print(path="cup.gcode", confirm=true)
β π’ printing begins
8. octoprint_get_job()
β watch progress: "42% Β· 2h 14m remaining"
Note
Steps 5β7 talk to a live printer. Tools that move the machine need confirm=true; everything up to slicing
is purely local.
PrintMCP/
βββ src/printmcp/
β βββ app.py # shared FastMCP instance
β βββ server.py # entry point β registers tools, runs over stdio
β βββ config.py # env-driven config (tokens, Cura paths, OctoPrint URL/key)
β βββ thingiverse.py # Level 1 β search & download
β βββ cura.py # Level 2 β slice via CuraEngine
β βββ octoprint.py # Level 3 β print management
βββ tests/test_server.py
βββ .env.example
βββ pyproject.toml
βββ README.md
uv run pytestThe suite is offline smoke tests β tool registration, filename sanitization, slice-input validation, stats parsing, and the Level 3 safety gate. They require no token, network, or Cura install, so they run anywhere in well under a second.
- 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.
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.
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.