mcp-printable 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_printable-0.1.0/.gitignore +46 -0
- mcp_printable-0.1.0/LICENSE +21 -0
- mcp_printable-0.1.0/PKG-INFO +207 -0
- mcp_printable-0.1.0/README.md +178 -0
- mcp_printable-0.1.0/SETUP.md +118 -0
- mcp_printable-0.1.0/addon/__init__.py +242 -0
- mcp_printable-0.1.0/addon/handlers.py +1405 -0
- mcp_printable-0.1.0/addon/utils.py +267 -0
- mcp_printable-0.1.0/docs/blender/blender-app.md +125 -0
- mcp_printable-0.1.0/docs/blender/design-loop.md +79 -0
- mcp_printable-0.1.0/docs/blender/image-displacement.md +79 -0
- mcp_printable-0.1.0/docs/design/print-in-place.md +178 -0
- mcp_printable-0.1.0/docs/openscad/README.md +97 -0
- mcp_printable-0.1.0/evals/README.md +139 -0
- mcp_printable-0.1.0/evals/adapters/__init__.py +1 -0
- mcp_printable-0.1.0/evals/adapters/goose.py +264 -0
- mcp_printable-0.1.0/evals/adapters/mock.py +93 -0
- mcp_printable-0.1.0/evals/framework.py +246 -0
- mcp_printable-0.1.0/evals/goose-recipes/blender.yaml +43 -0
- mcp_printable-0.1.0/evals/judges/__init__.py +1 -0
- mcp_printable-0.1.0/evals/judges/outcome_llm.py +153 -0
- mcp_printable-0.1.0/evals/judges/procedural.py +67 -0
- mcp_printable-0.1.0/evals/policies/always-clear-scene.md +52 -0
- mcp_printable-0.1.0/evals/policies/prefer-typed-boolean.md +52 -0
- mcp_printable-0.1.0/evals/policies/print-in-place-path-traceable.md +47 -0
- mcp_printable-0.1.0/evals/runner.py +251 -0
- mcp_printable-0.1.0/evals/scenarios/basic-hinge.md +36 -0
- mcp_printable-0.1.0/evals/scenarios/cube-with-hole.md +31 -0
- mcp_printable-0.1.0/evals/scenarios/simple-cube.md +25 -0
- mcp_printable-0.1.0/install.py +98 -0
- mcp_printable-0.1.0/pyproject.toml +70 -0
- mcp_printable-0.1.0/scad_backend.py +420 -0
- mcp_printable-0.1.0/server.py +1128 -0
- mcp_printable-0.1.0/tests/__init__.py +0 -0
- mcp_printable-0.1.0/tests/conftest.py +7 -0
- mcp_printable-0.1.0/tests/test_compositing.py +136 -0
- mcp_printable-0.1.0/tests/test_protocol.py +190 -0
- mcp_printable-0.1.0/tests/test_server.py +171 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
|
|
12
|
+
# Generated texture pipeline outputs
|
|
13
|
+
texture_maps/
|
|
14
|
+
|
|
15
|
+
# OS / editor
|
|
16
|
+
.DS_Store
|
|
17
|
+
Thumbs.db
|
|
18
|
+
.vscode/
|
|
19
|
+
.idea/
|
|
20
|
+
|
|
21
|
+
# Blender checkpoints
|
|
22
|
+
*.blend1
|
|
23
|
+
printable_blender_checkpoint.blend
|
|
24
|
+
printable_blender_scene.blend
|
|
25
|
+
|
|
26
|
+
# Eval runtime
|
|
27
|
+
evals/results/latest.json
|
|
28
|
+
evals/results/baseline.json
|
|
29
|
+
evals/results/logs/
|
|
30
|
+
|
|
31
|
+
# Local MCP client config — user-specific, not part of the project
|
|
32
|
+
.mcp.json
|
|
33
|
+
|
|
34
|
+
# Experiment scratch — local work that shouldn't ship.
|
|
35
|
+
# Drop one-off STLs / blends / scad / textures here.
|
|
36
|
+
experiments/
|
|
37
|
+
|
|
38
|
+
# Stray model artifacts at repo root (agents sometimes write here).
|
|
39
|
+
# Subdirectories are unaffected — only catches accidental root pollution.
|
|
40
|
+
/*.stl
|
|
41
|
+
/*.blend
|
|
42
|
+
/*.scad
|
|
43
|
+
|
|
44
|
+
# Claude Code local state
|
|
45
|
+
.claude/settings.local.json
|
|
46
|
+
.claude/worktrees/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aaron Goldsmith
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-printable
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for AI-driven 3D modeling and print validation (FDM-focused). Agent-agnostic; works with any MCP client (Claude Code, Goose, Cursor, Codex, ...).
|
|
5
|
+
Project-URL: Homepage, https://github.com/AaronGoldsmith/mcp-printable
|
|
6
|
+
Project-URL: Repository, https://github.com/AaronGoldsmith/mcp-printable
|
|
7
|
+
Project-URL: Issues, https://github.com/AaronGoldsmith/mcp-printable/issues
|
|
8
|
+
Author-email: Aaron Goldsmith <aargoldsmith@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: 3d-printing,ai-agents,blender,claude,fdm,mcp,model-context-protocol,openscad
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: mcp[cli]>=1.0.0
|
|
25
|
+
Requires-Dist: numpy>=1.24
|
|
26
|
+
Requires-Dist: pillow>=10.0.0
|
|
27
|
+
Requires-Dist: trimesh>=4.0.0
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Printable
|
|
31
|
+
|
|
32
|
+
**MCP server for AI-driven 3D modeling, optimized for FDM-printable geometry.**
|
|
33
|
+
|
|
34
|
+
Connect any MCP-capable agent (Claude Code, Goose, Cursor, Codex, Cline, etc.) to a 3D modeling backend and get tools tuned for the design loop that actually produces parts you can print.
|
|
35
|
+
|
|
36
|
+
## Why this exists
|
|
37
|
+
|
|
38
|
+
LLMs are good at writing geometry code but bad at the things that make a part actually printable: clearances on moving joints, overhangs, bridging, units, watertight meshes. Printable encodes those constraints into both the tool surface (typed booleans, printability checks, clearance sweeps, cross-sections) and the prose rules the agent reads (cardinal print-path rule, FDM clearance values, mechanism patterns).
|
|
39
|
+
|
|
40
|
+
The result: you can ask any MCP-aware agent "build me a hinge with 5mm barrel and 20×15mm flanges" and get a part that comes off the bed working.
|
|
41
|
+
|
|
42
|
+
## Backends
|
|
43
|
+
|
|
44
|
+
- **Blender** (`blender_*` tools, 25 of them). Full design loop with rendering, cross-sections, printability validation. Requires Blender 3.6+ installed and the included addon enabled.
|
|
45
|
+
- **OpenSCAD** (`scad_*` tools, 5 of them, see [`docs/openscad/README.md`](docs/openscad/README.md)). Code-first parametric backend. No app, no addon — shells out to the `openscad` CLI and uses [`trimesh`](https://github.com/mikedh/trimesh) for mesh validation. Requires OpenSCAD installed.
|
|
46
|
+
|
|
47
|
+
Cross-backend handoff happens via STL — both backends import and export it.
|
|
48
|
+
|
|
49
|
+
## Architecture
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Agent <--stdio/MCP--> server.py <--TCP :9876--> Blender addon
|
|
53
|
+
\
|
|
54
|
+
+----shell-out------> openscad CLI + trimesh
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- `server.py` — FastMCP server. Exposes the tool surface and embeds the always-on rules in the MCP `instructions` field, with pointers into `docs/` for deeper guidance.
|
|
58
|
+
- `addon/` — Blender addon. TCP server on `127.0.0.1:9876`. Commands run on Blender's main thread via `bpy.app.timers`.
|
|
59
|
+
- `docs/` — agent-agnostic prose guidance: print-in-place rules, design loop, image displacement. Also exposed as **MCP resources** under `printable://…` URIs (see [Documents](#documents) below) so any resource-aware MCP client can pull them via the protocol — no filesystem access required.
|
|
60
|
+
- `.claude/skills/` — thin Claude shims (description-triggered loading) that point into `docs/`. Other agents use resources or filesystem.
|
|
61
|
+
- `evals/` — policy-based regression tests that verify agents actually follow the rules. See [`evals/README.md`](evals/README.md).
|
|
62
|
+
|
|
63
|
+
## Status
|
|
64
|
+
|
|
65
|
+
v0.1.0 — alpha. Blender backend is feature-complete and dogfooded against real prints; OpenSCAD backend covers the parametric workflow but has fewer validation tools. API is stable enough to use but may shift before 1.0.
|
|
66
|
+
|
|
67
|
+
## Setup
|
|
68
|
+
|
|
69
|
+
### Install from PyPI
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install mcp-printable # or: uv pip install mcp-printable
|
|
73
|
+
printable-install-addon # copies the bundled addon into Blender's addon dir
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Then in Blender: Preferences → Add-ons → enable **"Printable Blender Bridge"**.
|
|
77
|
+
|
|
78
|
+
### Install from source
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone https://github.com/AaronGoldsmith/mcp-printable
|
|
82
|
+
cd mcp-printable
|
|
83
|
+
uv sync # or: pip install .
|
|
84
|
+
python install.py # equivalent to printable-install-addon
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> [!IMPORTANT]
|
|
88
|
+
> Run the install step from a terminal — **NOT** Blender's "Install from Disk" dialog. See [`SETUP.md`](SETUP.md) for why and other gotchas.
|
|
89
|
+
|
|
90
|
+
### Wire into your agent
|
|
91
|
+
|
|
92
|
+
For Claude Code (`~/.claude.json` or project `.mcp.json`):
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"printable-blender": {
|
|
97
|
+
"command": "printable"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
(Key is namespaced so the planned `printable-openscad` backend can register alongside without collision.)
|
|
103
|
+
|
|
104
|
+
For other agents (Goose, Cursor, etc.) — wire it up using your agent's standard MCP server configuration. The command is `printable`; no args needed.
|
|
105
|
+
|
|
106
|
+
### Agent skills (optional)
|
|
107
|
+
|
|
108
|
+
This repo bundles four [Claude Code skills](https://code.claude.com/docs/en/skills) under [`.claude/skills/`](.claude/skills/) — short shims that point at the same `docs/` content the MCP exposes as resources. Claude Code auto-discovers them when you launch it in the repo:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
git clone https://github.com/AaronGoldsmith/mcp-printable
|
|
112
|
+
cd mcp-printable && claude
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The 4 skills:
|
|
116
|
+
- `print-in-place` — design rules for moving-parts mechanisms (hinges, ball-sockets, snap fits)
|
|
117
|
+
- `blender-design-loop` — plan→build→verify→validate→export workflow
|
|
118
|
+
- `image-displacement` — turn a 2D image into 3D printable relief
|
|
119
|
+
- `blender-app` — launch / restart / multi-instance Blender setup
|
|
120
|
+
|
|
121
|
+
For Claude Code, copy a skill into `~/.claude/skills/` to make it available across all projects. **For other agents** (Codex, Cursor, Goose, ...) — see [AGENTS.md](AGENTS.md), which links each skill into the equivalent location for your agent and explains the MCP-resource fallback for agents that don't load project skills.
|
|
122
|
+
|
|
123
|
+
## Tool families
|
|
124
|
+
|
|
125
|
+
### Blender (25 tools)
|
|
126
|
+
|
|
127
|
+
**Scene** — `blender_get_scene_info`, `blender_get_object_info`, `blender_clear_scene`, `blender_rename_object`
|
|
128
|
+
|
|
129
|
+
**Code** — `blender_execute_code` (arbitrary bpy/bmesh; auto-checkpoints), `blender_boolean` (typed UNION/DIFFERENCE/INTERSECT — *prefer this over execute_code*)
|
|
130
|
+
|
|
131
|
+
**Visual feedback** — `blender_get_screenshot`, `blender_render_tiled`, `blender_render_turntable`, `blender_cross_section`, `blender_cross_section_gallery`, `blender_render_printability_heatmap`, `blender_render_with_dimensions`, `blender_render_before_after`
|
|
132
|
+
|
|
133
|
+
**Print validation** — `blender_check_overhangs`, `blender_check_thin_walls`, `blender_check_clearance`, `blender_check_clearance_sweep`, `blender_check_intersection`, `blender_check_retention`, `blender_mesh_health`, `blender_full_printability_check`
|
|
134
|
+
|
|
135
|
+
**Export** — `blender_export_stl`, `blender_import_stl`, `blender_save_blend`
|
|
136
|
+
|
|
137
|
+
### OpenSCAD (5 tools)
|
|
138
|
+
|
|
139
|
+
`scad_compile`, `scad_render_views`, `scad_cross_section`, `scad_validate_printability`, `scad_import_stl`. Shells out to the `openscad` CLI; uses [`trimesh`](https://github.com/mikedh/trimesh) for mesh validation. Full docs: [`docs/openscad/README.md`](docs/openscad/README.md).
|
|
140
|
+
|
|
141
|
+
## The Design Loop
|
|
142
|
+
|
|
143
|
+
Always-on rules embedded in the MCP server's `instructions` field — every agent that connects sees them automatically. Summary:
|
|
144
|
+
|
|
145
|
+
1. **Plan.** Compute coordinates and dimensions in one `execute_code` call that PRINTS them. Verify the math BEFORE creating geometry.
|
|
146
|
+
2. **Build.** 1–3 operations per `execute_code`, then `blender_mesh_health`.
|
|
147
|
+
3. **Verify.** Renders for shape, cross-sections for internal truth.
|
|
148
|
+
4. **Validate.** `blender_check_clearance_sweep` for any joint. `blender_full_printability_check` before export.
|
|
149
|
+
5. **Export.** `blender_export_stl` (no args = bundle all parts).
|
|
150
|
+
|
|
151
|
+
Full doc: [`docs/blender/design-loop.md`](docs/blender/design-loop.md).
|
|
152
|
+
|
|
153
|
+
For mechanism design (hinges, ball-sockets, snap fits, articulated chains): [`docs/design/print-in-place.md`](docs/design/print-in-place.md). This is backend-agnostic — same rules apply if you're using OpenSCAD.
|
|
154
|
+
|
|
155
|
+
## Documents
|
|
156
|
+
|
|
157
|
+
Every doc below is served two ways:
|
|
158
|
+
|
|
159
|
+
1. **As an MCP resource** under `printable://…` — the **preferred** path. Resource-aware clients fetch via `resources/read`, get the same content the maintainer ships, and don't need filesystem access to the project. Resources travel with the MCP server itself, so a `pip install mcp-printable` user has the docs even without cloning the repo.
|
|
160
|
+
2. **As a file in `docs/`** — fallback for filesystem-based clients, and for humans browsing the repo.
|
|
161
|
+
|
|
162
|
+
If you're writing an MCP client, prefer the URI. The filesystem path is documented mainly so a human can click through from this README.
|
|
163
|
+
|
|
164
|
+
| URI | File | Purpose |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| `printable://design/print-in-place` | [docs/design/print-in-place.md](docs/design/print-in-place.md) | FDM mechanism design: cardinal print-path rule, clearances, patterns, validation checklist (**backend-agnostic**) |
|
|
167
|
+
| `printable://blender/design-loop` | [docs/blender/design-loop.md](docs/blender/design-loop.md) | Plan→build→verify→validate→export workflow, boolean rules, failure modes |
|
|
168
|
+
| `printable://blender/image-displacement` | [docs/blender/image-displacement.md](docs/blender/image-displacement.md) | 2D image → printable 3D relief |
|
|
169
|
+
| `printable://blender/blender-app` | [docs/blender/blender-app.md](docs/blender/blender-app.md) | Launch / restart / multi-instance setup |
|
|
170
|
+
| `printable://openscad/backend` | [docs/openscad/README.md](docs/openscad/README.md) | OpenSCAD backend setup, tool reference, validator details, cross-backend handoff |
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
docs/
|
|
174
|
+
├── design/ # backend-agnostic design rules
|
|
175
|
+
│ └── print-in-place.md
|
|
176
|
+
├── blender/ # Blender-specific
|
|
177
|
+
│ ├── design-loop.md
|
|
178
|
+
│ ├── image-displacement.md
|
|
179
|
+
│ └── blender-app.md
|
|
180
|
+
└── openscad/ # OpenSCAD-specific
|
|
181
|
+
└── README.md
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Testing
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
python -m pytest tests/ -v # unit tests, no Blender required
|
|
188
|
+
python evals/runner.py # policy-based regression evals (see evals/README.md)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Unit tests cover TCP protocol framing, image compositing (PIL), MCP tool registration. The eval suite checks that agents using the MCP actually follow the always-on rules (e.g. clear scene first, prefer `blender_boolean`, no monolithic `execute_code` blocks) — procedural checks from the tool trace, plus LLM-judged outcome policies for things like "moving parts have a continuous print path to the bed."
|
|
192
|
+
|
|
193
|
+
## Roadmap
|
|
194
|
+
|
|
195
|
+
Things on the list, not yet shipped:
|
|
196
|
+
|
|
197
|
+
- **Validated parameter recipes** — turnkey parameter sets for common print-in-place mechanisms (wheel-on-axle, flip-tile, ball-and-socket, snap fit) so an agent can ask for "a toy car wheel" and get a known-good geometry without re-solving the clearance + retention math each time. Earlier drafts existed but weren't dialed in enough to ship as authoritative; new ones will land once they're validated against real prints.
|
|
198
|
+
- **Blender app-lifecycle tools** (`blender_launch` / `blender_status` / `blender_kill`) — let the agent spin Blender up itself instead of needing the user to start it first.
|
|
199
|
+
- **Second OpenSCAD parity pass** — match Blender's clearance-sweep / retention / thin-wall checks on the SCAD side.
|
|
200
|
+
|
|
201
|
+
## Contributing
|
|
202
|
+
|
|
203
|
+
The interesting design surface is in `docs/`. New always-on rules belong in [`docs/design/`](docs/design/) (backend-agnostic) or [`docs/blender/`](docs/blender/) / [`docs/openscad/`](docs/openscad/) (backend-specific). If a rule should be enforced, also add a policy file under [`evals/policies/`](evals/policies/) and a scenario under [`evals/scenarios/`](evals/scenarios/) so the eval runner picks it up.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT — see [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Printable
|
|
2
|
+
|
|
3
|
+
**MCP server for AI-driven 3D modeling, optimized for FDM-printable geometry.**
|
|
4
|
+
|
|
5
|
+
Connect any MCP-capable agent (Claude Code, Goose, Cursor, Codex, Cline, etc.) to a 3D modeling backend and get tools tuned for the design loop that actually produces parts you can print.
|
|
6
|
+
|
|
7
|
+
## Why this exists
|
|
8
|
+
|
|
9
|
+
LLMs are good at writing geometry code but bad at the things that make a part actually printable: clearances on moving joints, overhangs, bridging, units, watertight meshes. Printable encodes those constraints into both the tool surface (typed booleans, printability checks, clearance sweeps, cross-sections) and the prose rules the agent reads (cardinal print-path rule, FDM clearance values, mechanism patterns).
|
|
10
|
+
|
|
11
|
+
The result: you can ask any MCP-aware agent "build me a hinge with 5mm barrel and 20×15mm flanges" and get a part that comes off the bed working.
|
|
12
|
+
|
|
13
|
+
## Backends
|
|
14
|
+
|
|
15
|
+
- **Blender** (`blender_*` tools, 25 of them). Full design loop with rendering, cross-sections, printability validation. Requires Blender 3.6+ installed and the included addon enabled.
|
|
16
|
+
- **OpenSCAD** (`scad_*` tools, 5 of them, see [`docs/openscad/README.md`](docs/openscad/README.md)). Code-first parametric backend. No app, no addon — shells out to the `openscad` CLI and uses [`trimesh`](https://github.com/mikedh/trimesh) for mesh validation. Requires OpenSCAD installed.
|
|
17
|
+
|
|
18
|
+
Cross-backend handoff happens via STL — both backends import and export it.
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
Agent <--stdio/MCP--> server.py <--TCP :9876--> Blender addon
|
|
24
|
+
\
|
|
25
|
+
+----shell-out------> openscad CLI + trimesh
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `server.py` — FastMCP server. Exposes the tool surface and embeds the always-on rules in the MCP `instructions` field, with pointers into `docs/` for deeper guidance.
|
|
29
|
+
- `addon/` — Blender addon. TCP server on `127.0.0.1:9876`. Commands run on Blender's main thread via `bpy.app.timers`.
|
|
30
|
+
- `docs/` — agent-agnostic prose guidance: print-in-place rules, design loop, image displacement. Also exposed as **MCP resources** under `printable://…` URIs (see [Documents](#documents) below) so any resource-aware MCP client can pull them via the protocol — no filesystem access required.
|
|
31
|
+
- `.claude/skills/` — thin Claude shims (description-triggered loading) that point into `docs/`. Other agents use resources or filesystem.
|
|
32
|
+
- `evals/` — policy-based regression tests that verify agents actually follow the rules. See [`evals/README.md`](evals/README.md).
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
v0.1.0 — alpha. Blender backend is feature-complete and dogfooded against real prints; OpenSCAD backend covers the parametric workflow but has fewer validation tools. API is stable enough to use but may shift before 1.0.
|
|
37
|
+
|
|
38
|
+
## Setup
|
|
39
|
+
|
|
40
|
+
### Install from PyPI
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install mcp-printable # or: uv pip install mcp-printable
|
|
44
|
+
printable-install-addon # copies the bundled addon into Blender's addon dir
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Then in Blender: Preferences → Add-ons → enable **"Printable Blender Bridge"**.
|
|
48
|
+
|
|
49
|
+
### Install from source
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git clone https://github.com/AaronGoldsmith/mcp-printable
|
|
53
|
+
cd mcp-printable
|
|
54
|
+
uv sync # or: pip install .
|
|
55
|
+
python install.py # equivalent to printable-install-addon
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
> [!IMPORTANT]
|
|
59
|
+
> Run the install step from a terminal — **NOT** Blender's "Install from Disk" dialog. See [`SETUP.md`](SETUP.md) for why and other gotchas.
|
|
60
|
+
|
|
61
|
+
### Wire into your agent
|
|
62
|
+
|
|
63
|
+
For Claude Code (`~/.claude.json` or project `.mcp.json`):
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"printable-blender": {
|
|
68
|
+
"command": "printable"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
(Key is namespaced so the planned `printable-openscad` backend can register alongside without collision.)
|
|
74
|
+
|
|
75
|
+
For other agents (Goose, Cursor, etc.) — wire it up using your agent's standard MCP server configuration. The command is `printable`; no args needed.
|
|
76
|
+
|
|
77
|
+
### Agent skills (optional)
|
|
78
|
+
|
|
79
|
+
This repo bundles four [Claude Code skills](https://code.claude.com/docs/en/skills) under [`.claude/skills/`](.claude/skills/) — short shims that point at the same `docs/` content the MCP exposes as resources. Claude Code auto-discovers them when you launch it in the repo:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/AaronGoldsmith/mcp-printable
|
|
83
|
+
cd mcp-printable && claude
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The 4 skills:
|
|
87
|
+
- `print-in-place` — design rules for moving-parts mechanisms (hinges, ball-sockets, snap fits)
|
|
88
|
+
- `blender-design-loop` — plan→build→verify→validate→export workflow
|
|
89
|
+
- `image-displacement` — turn a 2D image into 3D printable relief
|
|
90
|
+
- `blender-app` — launch / restart / multi-instance Blender setup
|
|
91
|
+
|
|
92
|
+
For Claude Code, copy a skill into `~/.claude/skills/` to make it available across all projects. **For other agents** (Codex, Cursor, Goose, ...) — see [AGENTS.md](AGENTS.md), which links each skill into the equivalent location for your agent and explains the MCP-resource fallback for agents that don't load project skills.
|
|
93
|
+
|
|
94
|
+
## Tool families
|
|
95
|
+
|
|
96
|
+
### Blender (25 tools)
|
|
97
|
+
|
|
98
|
+
**Scene** — `blender_get_scene_info`, `blender_get_object_info`, `blender_clear_scene`, `blender_rename_object`
|
|
99
|
+
|
|
100
|
+
**Code** — `blender_execute_code` (arbitrary bpy/bmesh; auto-checkpoints), `blender_boolean` (typed UNION/DIFFERENCE/INTERSECT — *prefer this over execute_code*)
|
|
101
|
+
|
|
102
|
+
**Visual feedback** — `blender_get_screenshot`, `blender_render_tiled`, `blender_render_turntable`, `blender_cross_section`, `blender_cross_section_gallery`, `blender_render_printability_heatmap`, `blender_render_with_dimensions`, `blender_render_before_after`
|
|
103
|
+
|
|
104
|
+
**Print validation** — `blender_check_overhangs`, `blender_check_thin_walls`, `blender_check_clearance`, `blender_check_clearance_sweep`, `blender_check_intersection`, `blender_check_retention`, `blender_mesh_health`, `blender_full_printability_check`
|
|
105
|
+
|
|
106
|
+
**Export** — `blender_export_stl`, `blender_import_stl`, `blender_save_blend`
|
|
107
|
+
|
|
108
|
+
### OpenSCAD (5 tools)
|
|
109
|
+
|
|
110
|
+
`scad_compile`, `scad_render_views`, `scad_cross_section`, `scad_validate_printability`, `scad_import_stl`. Shells out to the `openscad` CLI; uses [`trimesh`](https://github.com/mikedh/trimesh) for mesh validation. Full docs: [`docs/openscad/README.md`](docs/openscad/README.md).
|
|
111
|
+
|
|
112
|
+
## The Design Loop
|
|
113
|
+
|
|
114
|
+
Always-on rules embedded in the MCP server's `instructions` field — every agent that connects sees them automatically. Summary:
|
|
115
|
+
|
|
116
|
+
1. **Plan.** Compute coordinates and dimensions in one `execute_code` call that PRINTS them. Verify the math BEFORE creating geometry.
|
|
117
|
+
2. **Build.** 1–3 operations per `execute_code`, then `blender_mesh_health`.
|
|
118
|
+
3. **Verify.** Renders for shape, cross-sections for internal truth.
|
|
119
|
+
4. **Validate.** `blender_check_clearance_sweep` for any joint. `blender_full_printability_check` before export.
|
|
120
|
+
5. **Export.** `blender_export_stl` (no args = bundle all parts).
|
|
121
|
+
|
|
122
|
+
Full doc: [`docs/blender/design-loop.md`](docs/blender/design-loop.md).
|
|
123
|
+
|
|
124
|
+
For mechanism design (hinges, ball-sockets, snap fits, articulated chains): [`docs/design/print-in-place.md`](docs/design/print-in-place.md). This is backend-agnostic — same rules apply if you're using OpenSCAD.
|
|
125
|
+
|
|
126
|
+
## Documents
|
|
127
|
+
|
|
128
|
+
Every doc below is served two ways:
|
|
129
|
+
|
|
130
|
+
1. **As an MCP resource** under `printable://…` — the **preferred** path. Resource-aware clients fetch via `resources/read`, get the same content the maintainer ships, and don't need filesystem access to the project. Resources travel with the MCP server itself, so a `pip install mcp-printable` user has the docs even without cloning the repo.
|
|
131
|
+
2. **As a file in `docs/`** — fallback for filesystem-based clients, and for humans browsing the repo.
|
|
132
|
+
|
|
133
|
+
If you're writing an MCP client, prefer the URI. The filesystem path is documented mainly so a human can click through from this README.
|
|
134
|
+
|
|
135
|
+
| URI | File | Purpose |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| `printable://design/print-in-place` | [docs/design/print-in-place.md](docs/design/print-in-place.md) | FDM mechanism design: cardinal print-path rule, clearances, patterns, validation checklist (**backend-agnostic**) |
|
|
138
|
+
| `printable://blender/design-loop` | [docs/blender/design-loop.md](docs/blender/design-loop.md) | Plan→build→verify→validate→export workflow, boolean rules, failure modes |
|
|
139
|
+
| `printable://blender/image-displacement` | [docs/blender/image-displacement.md](docs/blender/image-displacement.md) | 2D image → printable 3D relief |
|
|
140
|
+
| `printable://blender/blender-app` | [docs/blender/blender-app.md](docs/blender/blender-app.md) | Launch / restart / multi-instance setup |
|
|
141
|
+
| `printable://openscad/backend` | [docs/openscad/README.md](docs/openscad/README.md) | OpenSCAD backend setup, tool reference, validator details, cross-backend handoff |
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
docs/
|
|
145
|
+
├── design/ # backend-agnostic design rules
|
|
146
|
+
│ └── print-in-place.md
|
|
147
|
+
├── blender/ # Blender-specific
|
|
148
|
+
│ ├── design-loop.md
|
|
149
|
+
│ ├── image-displacement.md
|
|
150
|
+
│ └── blender-app.md
|
|
151
|
+
└── openscad/ # OpenSCAD-specific
|
|
152
|
+
└── README.md
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Testing
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python -m pytest tests/ -v # unit tests, no Blender required
|
|
159
|
+
python evals/runner.py # policy-based regression evals (see evals/README.md)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Unit tests cover TCP protocol framing, image compositing (PIL), MCP tool registration. The eval suite checks that agents using the MCP actually follow the always-on rules (e.g. clear scene first, prefer `blender_boolean`, no monolithic `execute_code` blocks) — procedural checks from the tool trace, plus LLM-judged outcome policies for things like "moving parts have a continuous print path to the bed."
|
|
163
|
+
|
|
164
|
+
## Roadmap
|
|
165
|
+
|
|
166
|
+
Things on the list, not yet shipped:
|
|
167
|
+
|
|
168
|
+
- **Validated parameter recipes** — turnkey parameter sets for common print-in-place mechanisms (wheel-on-axle, flip-tile, ball-and-socket, snap fit) so an agent can ask for "a toy car wheel" and get a known-good geometry without re-solving the clearance + retention math each time. Earlier drafts existed but weren't dialed in enough to ship as authoritative; new ones will land once they're validated against real prints.
|
|
169
|
+
- **Blender app-lifecycle tools** (`blender_launch` / `blender_status` / `blender_kill`) — let the agent spin Blender up itself instead of needing the user to start it first.
|
|
170
|
+
- **Second OpenSCAD parity pass** — match Blender's clearance-sweep / retention / thin-wall checks on the SCAD side.
|
|
171
|
+
|
|
172
|
+
## Contributing
|
|
173
|
+
|
|
174
|
+
The interesting design surface is in `docs/`. New always-on rules belong in [`docs/design/`](docs/design/) (backend-agnostic) or [`docs/blender/`](docs/blender/) / [`docs/openscad/`](docs/openscad/) (backend-specific). If a rule should be enforced, also add a policy file under [`evals/policies/`](evals/policies/) and a scenario under [`evals/scenarios/`](evals/scenarios/) so the eval runner picks it up.
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT — see [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Setup
|
|
2
|
+
|
|
3
|
+
End-to-end install for the Printable MCP server + Blender addon, plus the gotchas that aren't obvious until they bite.
|
|
4
|
+
|
|
5
|
+
## 1. Install dependencies
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync # or: pip install .
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 2. Install the Blender addon — from a terminal
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
python install.py
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This copies `addon/` to `<blender-config>/scripts/addons/printable_blender/`.
|
|
18
|
+
|
|
19
|
+
> [!WARNING]
|
|
20
|
+
> **Do NOT use Blender's `Edit > Preferences > Add-ons > Install from Disk`** on `install.py`.
|
|
21
|
+
> That dialog treats the file you point at as the addon itself, copies the lone `install.py`
|
|
22
|
+
> into `scripts/addons/`, and then registers nothing because `install.py` has no `bl_info`.
|
|
23
|
+
> You'll see a misleading **`Modules Installed ()`** popup (note the empty parens) and the
|
|
24
|
+
> TCP server will never start.
|
|
25
|
+
>
|
|
26
|
+
> Always run `python install.py` from a shell in the project root.
|
|
27
|
+
|
|
28
|
+
After install, verify the directory exists:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
<blender-config>/scripts/addons/printable_blender/
|
|
32
|
+
__init__.py
|
|
33
|
+
handlers.py
|
|
34
|
+
utils.py
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If you instead see `install.py` and/or `addon.py` loose in `scripts/addons/`, the GUI-install
|
|
38
|
+
pitfall above happened. Delete those stray files and re-run `python install.py` from the terminal.
|
|
39
|
+
|
|
40
|
+
## 3. Enable the addon in Blender
|
|
41
|
+
|
|
42
|
+
`Edit > Preferences > Add-ons` → search **`Printable`** → tick **"Printable Blender Bridge"**.
|
|
43
|
+
|
|
44
|
+
You should see this in Blender's system console:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
[Printable Bridge] Listening on 127.0.0.1:9876
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 4. Verify the TCP bridge
|
|
51
|
+
|
|
52
|
+
From any terminal:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python - <<'PY'
|
|
56
|
+
import socket, struct, json, uuid
|
|
57
|
+
s = socket.socket(); s.connect(('127.0.0.1', 9876))
|
|
58
|
+
msg = json.dumps({'id': str(uuid.uuid4()), 'command': 'get_scene_info', 'params': {}}).encode()
|
|
59
|
+
s.sendall(struct.pack('>I', len(msg)) + msg)
|
|
60
|
+
n = struct.unpack('>I', s.recv(4))[0]
|
|
61
|
+
print(json.loads(s.recv(n)))
|
|
62
|
+
PY
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
A successful response means the agent can talk to Blender.
|
|
66
|
+
|
|
67
|
+
## 5. Wire the MCP server into your agent
|
|
68
|
+
|
|
69
|
+
See [README.md](README.md#setup) for the per-agent config snippet.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Reinstalling / updating the addon
|
|
74
|
+
|
|
75
|
+
Python modules don't hot-reload in Blender. After running `python install.py` again:
|
|
76
|
+
|
|
77
|
+
- **First-time install of a new module name** (e.g. you renamed the addon): toggling enabled in
|
|
78
|
+
Preferences is enough — the new module loads fresh.
|
|
79
|
+
- **Updating an already-loaded addon**: you must **fully restart Blender**. Disabling and
|
|
80
|
+
re-enabling the addon does *not* re-import the Python modules.
|
|
81
|
+
|
|
82
|
+
Save your `.blend` first if you want to keep the scene.
|
|
83
|
+
|
|
84
|
+
### Dev-mode hot-reload (advanced)
|
|
85
|
+
|
|
86
|
+
Inside the running Blender, via `blender_execute_code`:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
import importlib
|
|
90
|
+
from printable_blender import handlers, utils
|
|
91
|
+
importlib.reload(utils)
|
|
92
|
+
importlib.reload(handlers)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This reloads handler logic without a restart. The version shown in `bl_info` may still read
|
|
96
|
+
the old number, but the running code is current. Note: changes to `__init__.py` (the TCP server
|
|
97
|
+
itself) still require a full restart.
|
|
98
|
+
|
|
99
|
+
## "Missing Add-ons" warnings after a rename
|
|
100
|
+
|
|
101
|
+
If the addon was previously installed under a different module name (e.g. `claude_blender`)
|
|
102
|
+
and you've since renamed/replaced it (e.g. with `printable_blender`), Blender will show the
|
|
103
|
+
old name under **Preferences → Add-ons → Missing Add-ons** because it's still listed in
|
|
104
|
+
`userpref.blend` as previously enabled, but the directory no longer exists.
|
|
105
|
+
|
|
106
|
+
This is harmless. To clean it up: click the trash/X next to the missing entry, or just save
|
|
107
|
+
preferences after enabling the new addon — Blender will drop the dead reference on next load.
|
|
108
|
+
|
|
109
|
+
## Troubleshooting
|
|
110
|
+
|
|
111
|
+
| Symptom | Likely cause |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `ConnectionRefusedError` on port 9876 | Addon not enabled, or addon errored on load — check Blender's system console |
|
|
114
|
+
| `Modules Installed ()` (empty parens) | You used Blender's "Install from Disk" on `install.py` — see [step 2](#2-install-the-blender-addon--from-a-terminal) |
|
|
115
|
+
| Addon enables but immediately disables | Python error during `register()` — open `Window > Toggle System Console` to read it |
|
|
116
|
+
| Code changes not taking effect | Module cache — restart Blender, or use the dev-mode reload above |
|
|
117
|
+
| Missing Add-ons shows `claude_blender` (or other old name) | Stale reference from a previous install — see above, harmless |
|
|
118
|
+
| TCP listening but commands hang | Blender is in a modal state (e.g. modal operator running, viewport editing) — main-thread timer is blocked |
|