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.
Files changed (38) hide show
  1. mcp_printable-0.1.0/.gitignore +46 -0
  2. mcp_printable-0.1.0/LICENSE +21 -0
  3. mcp_printable-0.1.0/PKG-INFO +207 -0
  4. mcp_printable-0.1.0/README.md +178 -0
  5. mcp_printable-0.1.0/SETUP.md +118 -0
  6. mcp_printable-0.1.0/addon/__init__.py +242 -0
  7. mcp_printable-0.1.0/addon/handlers.py +1405 -0
  8. mcp_printable-0.1.0/addon/utils.py +267 -0
  9. mcp_printable-0.1.0/docs/blender/blender-app.md +125 -0
  10. mcp_printable-0.1.0/docs/blender/design-loop.md +79 -0
  11. mcp_printable-0.1.0/docs/blender/image-displacement.md +79 -0
  12. mcp_printable-0.1.0/docs/design/print-in-place.md +178 -0
  13. mcp_printable-0.1.0/docs/openscad/README.md +97 -0
  14. mcp_printable-0.1.0/evals/README.md +139 -0
  15. mcp_printable-0.1.0/evals/adapters/__init__.py +1 -0
  16. mcp_printable-0.1.0/evals/adapters/goose.py +264 -0
  17. mcp_printable-0.1.0/evals/adapters/mock.py +93 -0
  18. mcp_printable-0.1.0/evals/framework.py +246 -0
  19. mcp_printable-0.1.0/evals/goose-recipes/blender.yaml +43 -0
  20. mcp_printable-0.1.0/evals/judges/__init__.py +1 -0
  21. mcp_printable-0.1.0/evals/judges/outcome_llm.py +153 -0
  22. mcp_printable-0.1.0/evals/judges/procedural.py +67 -0
  23. mcp_printable-0.1.0/evals/policies/always-clear-scene.md +52 -0
  24. mcp_printable-0.1.0/evals/policies/prefer-typed-boolean.md +52 -0
  25. mcp_printable-0.1.0/evals/policies/print-in-place-path-traceable.md +47 -0
  26. mcp_printable-0.1.0/evals/runner.py +251 -0
  27. mcp_printable-0.1.0/evals/scenarios/basic-hinge.md +36 -0
  28. mcp_printable-0.1.0/evals/scenarios/cube-with-hole.md +31 -0
  29. mcp_printable-0.1.0/evals/scenarios/simple-cube.md +25 -0
  30. mcp_printable-0.1.0/install.py +98 -0
  31. mcp_printable-0.1.0/pyproject.toml +70 -0
  32. mcp_printable-0.1.0/scad_backend.py +420 -0
  33. mcp_printable-0.1.0/server.py +1128 -0
  34. mcp_printable-0.1.0/tests/__init__.py +0 -0
  35. mcp_printable-0.1.0/tests/conftest.py +7 -0
  36. mcp_printable-0.1.0/tests/test_compositing.py +136 -0
  37. mcp_printable-0.1.0/tests/test_protocol.py +190 -0
  38. 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 |