forge3d-mcp
Provides a geometry backend that drives Blender for organic forms, bevels, subdivision, materials, rigging, and animation.
Exports models as GLB/glTF and embeds GLB data directly into shareable viewer pages.
Provides a geometry backend that drives OpenSCAD for hard-surface CSG parts such as brackets, enclosures, and jigs.
Generates single-file Three.js viewer pages and an embeddable custom element for displaying exported GLB models.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
forge3d
A 3D-model toolchain any AI agent can drive. One MCP server, one agent skill, five interchangeable geometry engines, a validation layer that knows what "correct" means for print vs web vs game, and a Three.js viewer that turns a mesh into a single HTML file you can send to anyone.
Most "AI makes 3D" demos stop at a pretty mesh in a viewport. The hard parts are everything after: is it watertight, is it the right size in millimetres, will it survive a 60k-triangle budget, can the next agent pick up where this one left off without re-reading a megabyte of vertices. forge3d is built around those.

Nothing in that image is stock: the geometry came from examples/procedural_chair.py
and the render from forge3d.render — the same loop an agent runs.
Open examples/chair.html for the interactive version.
What it actually does
brief ──► plan_model ──► create_model ──► validate_model ──► repair_model ──► review_model
│ │
├──► previews (PNG, so the agent can *see* it) │
└──► viewer (single-file Three.js page) ◄─────────┘Step | Tool | What it prevents |
Brief |
| generating from a vague prompt with no scale or purpose |
Build |
| being locked into one engine |
Inspect |
| pasting geometry into a context window |
Check |
| shipping a non-manifold mesh to a printer |
Fix |
| silent holes, flipped normals, absurd poly counts |
Look |
| the agent guessing instead of iterating |
Ship |
| needing a host to show someone the result |
Hand off |
| two agents diverging on the same model |
Related MCP server: rupa3d
Install
git clone https://github.com/chaudharyvivek1/forge3d.git
cd forge3d
pip install -e ".[render]"Optional engines — install only what you need:
# exact CSG parts (brackets, enclosures)
sudo apt install openscad # macOS: brew install --cask openscad
# Windows: winget install OpenSCAD.OpenSCAD
# organic forms, bevels, materials, animation
sudo snap install blender --classic # macOS: brew install --cask blender
# Windows: winget install BlenderFoundation.Blender
# real B-rep CAD with STEP export
pip install cadquery
# decimation in repair_model
pip install fast-simplification
# boolean unions in trimesh (procedural backend)
pip install manifold3dCheck what this machine can actually do — never guess:
forge3d doctor # OS, Python, engines, packages, workdir, and how to fix gaps
forge3d backends # just the engine listdoctor is also an MCP tool, so an agent can diagnose its own runtime instead of
guessing why a backend is unavailable. It reports whether an env var is set,
never its value — an API key is not echoed back.
Works on Linux, macOS and Windows, in Docker, and in CPU-only agent sandboxes. The full matrix, including what does not work where, is in docs/platforms.md.
Quick start (agent)
Add to Claude Desktop, Cursor, or any MCP client:
{
"mcpServers": {
"forge3d": {
"command": "forge3d-mcp",
"env": { "FORGE3D_WORKDIR": "/absolute/path/to/forge3d-work" }
}
}
}For a remote agent or your own app, run it over HTTP instead:
pip install "forge3d[http]"
forge3d-mcp --http 8000 # loopback only, no auth
FORGE3D_HTTP_TOKEN=$(openssl rand -hex 32) \
forge3d-mcp --http 8000 --host 0.0.0.0 # network, authenticatedThe HTTP transport binds 127.0.0.1 by default and refuses a public bind
without a token — v0.2.0 bound 0.0.0.0 with no authentication, which meant
anyone who could reach the port could run arbitrary model code. HTTP mode also
forces subprocess isolation for that code. Read docs/security.md
before exposing it anywhere; it states plainly what is still not protected.
Then a single call gets you from brief to shareable page:
create_model(
prompt="a modern side chair with cross braces",
name="chair",
purpose="game",
backend="procedural",
source=open("examples/procedural_chair.py").read(),
dimensions={"x": 450, "y": 480, "z": 850},
units="mm",
scale_to_spec=True,
)
# -> { "ok": true, "path": ".../chair.glb", "viewer": ".../chair.html",
# "validation": { "ok": true, "summary": "PASS with 1 warning(s) ..." }, ... }Quick start (human, no agent)
forge3d plan --prompt "wall bracket for a 32mm pipe" --purpose print --dims x=120,y=60,z=40
forge3d create --name chair --purpose game --backend procedural \
--source examples/procedural_chair.py --dims x=450,y=480,z=850 \
--scale-to-spec --viewer
forge3d validate output/chair.glb --profile print
forge3d render output/chair.glb
forge3d viewer output/chair.glb --out chair.htmlThe five engines
Backend | Needs | Best for | Weak at |
| nothing (trimesh) | precise dimensions, repeated structure, editable output, offline | organic forms |
|
| hard-surface CSG, brackets, enclosures, jigs | sculpting, texturing |
|
| bevels, subdivision, materials, rigging, animation | exact mechanical dims |
|
| manufacturing, STEP deliverables, fillets | organic forms |
| a text-to-3D service | stylised props, characters, textured meshes fast | exact scale, watertight print geometry |
backend="auto" routes from the spec: print → OpenSCAD if present, cad →
CadQuery, game → Blender, web with references → hosted, otherwise
procedural. The routing table is data (backends/registry.py), so it is
testable and easy to change.
Three.js
Two ways, both in the repo:
Single-file page — make_viewer embeds the GLB as a data URI, so the HTML
needs no server, no CORS and no hosting. The model is embedded; three.js still
loads from a CDN by default, so for an air-gapped machine point
FORGE3D_THREE_URL at a local mirror of three before building the page:
forge3d viewer output/chair.glb --out chair.html
FORGE3D_THREE_URL=http://localhost:8080/three forge3d viewer output/chair.glb --out chair.htmlEmbeddable element — for your own app, a custom element that takes a URL:
<script type="importmap">
{"imports":{"three":"https://unpkg.com/three@0.169.0/build/three.module.js",
"three/addons/":"https://unpkg.com/three@0.169.0/examples/jsm/"}}
</script>
<script type="module" src="/forge3d-viewer.js"></script>
<forge3d-viewer src="/models/chair.glb" height="480" autorotate grid></forge3d-viewer>Events: forge3d:loaded (detail.triangles), forge3d:error.
See docs/threejs.md.
Why the context-window rules matter
A 100k-triangle GLB is a few megabytes; as text it is millions of tokens. So
every tool in forge3d takes and returns paths, never geometry. The one way to
describe a model in context is model_card — roughly 300 tokens:
**chair.glb** — glb
96 tris · 418.77 x 412.56 x 850 mm · watertight · 8 body
validation: PASS with 1 warning(s) — game profile (single_body)
ship as: .glbMulti-agent, multi-person
handoff.py defines the packet that lets a second agent — or a designer and a
3D artist — take over without re-deriving anything: spec, artifacts, checks,
owners, open questions, and who is next. It writes both JSON (for agents) and
Markdown (for humans). See docs/multi-agent.md.
create_handoff(
spec=spec, artifacts={"model": "chair.glb", "viewer": "chair.html"},
backend="procedural",
checks=checklist("game"),
owners={"design": "priya", "geometry": "agent-a"},
next_agent="review-agent",
)What was fixed in v0.2.0
The audit that produced 0.2.0 found seven real bugs, each now covered by a test
in tests/test_regressions.py:
The default backend crashed inside a worker thread. The code timeout used
signal.alarm, which is unavailable on Windows and raisesValueError: signal only works in main threadelsewhere — and MCP servers run sync tools in a threadpool. Timeouts are now thread-based..gltfexport was impossible. trimesh returns a dict of filename→payload for multi-file formats; that dict went straight towrite_bytes.A model name could break out of the viewer page.
</script>in a title terminated the script block — a real XSS vector on user-supplied names.embed=Falseproduced a page pointing at a file it never wrote.Non-Latin model names collapsed to
model. Hindi and CJK names are now preserved, matras included.Windows-illegal filenames were not avoided (
con,aux,COM1…).Subprocess output was decoded with the platform default, so a non-ASCII error message raised
UnicodeDecodeErroron Windows.
Plus: materials and seed are now reachable from create_model, the OpenSCAD
source detector no longer needs the module keyword, and the viewer explains a
blocked CDN instead of showing a blank canvas.
Repository layout
src/forge3d/
spec.py the brief as data — purpose, units, dimensions, budget
backends/ procedural · openscad · blender · cadquery · hosted
validate.py profile-based checks, every failure carries a fix hint
repair.py merge, drop, fill, re-orient, decimate
render.py CPU previews (matplotlib) — works headless, no GPU
viewer.py single-file Three.js page
viewer_assets/ template.html + forge3d-viewer.js custom element
platform_support.py binary discovery, UTF-8 subprocess, thread-safe timeouts, doctor
http_server.py HTTP transport: loopback default, bearer auth, bind policy
sandbox_runner.py the child process for FORGE3D_EXEC_MODE=subprocess
context.py model cards — the only sanctioned way to describe a mesh
handoff.py checklists + multi-agent handoff packets
jobs.py durable job records for slow generations
server.py the MCP surface (16 tools)
cli.py same capabilities without an agent
skill/ agent skill: SKILL.md + references
docs/ architecture, security, platforms, backends, threejs, multi-agent, licensing
examples/ chair (trimesh), bracket (OpenSCAD), gear (bpy), plate (CadQuery)
tests/ pytest — unit, platform and regression suites
Dockerfile CPU-only image, non-root, /work volumeSecurity
Two things worth knowing before you point this at anything other than your own machine:
Agent code execution. The procedural, cadquery and blender backends run
code the agent wrote. FORGE3D_ALLOW_CODE_EXEC=false disables that, and
FORGE3D_EXEC_MODE=subprocess runs it in a killable child process with rlimits
instead of in the server. Neither is a sandbox against a determined attacker —
for that, use the container and keep the caller trusted.
The HTTP transport requires a bearer token for any non-loopback bind, compares it in constant time, and forces subprocess isolation. It does not do TLS, rate limiting or per-user identity; put a reverse proxy in front for those.
Full detail, including the threat model and what is deliberately not covered: docs/security.md.
Honest limitations
Textures. The local engines produce geometry, not painted PBR materials. For textured output, route to a hosted text-to-3D service.
Hosted adapter. Provider APIs (Meshy, Tripo, Rodin, Hunyuan3D) differ.
hosted.pyspeaks one small documented contract — point it at a thin worker. It does not pretend to be a drop-in client for all of them.Rigging. Blender can rig; forge3d does not generate skeletons or weights for you. Auto-rig quality varies badly.
Preview renders are review-quality, not beauty shots. For beauty, the Three.js viewer with an environment map is the better tool.
Licensing. Output rights differ sharply between hosted services. That is your provider's terms, not this repo's. See
docs/licensing.md.No provider-specific integrations. The hosted adapter speaks one documented contract and ships a reference worker (
examples/hosted_worker.py) you adapt. A "universal" client for Meshy/Tripo/Rodin would be wrong in ways you would only find in production, so it does not pretend to be one.Subprocess isolation is not a security boundary. It gives real cancellation and resource ceilings; it does not stop a child process reading your files.
Licence
MIT — see LICENSE. Built by Vivek Chaudhary.
This server cannot be deployed
Maintenance
Related MCP Connectors
Parametric 3D CAD for AI agents: build print-ready parts, check them, export STL, 3MF or STEP.
Build, validate, and deploy multi-agent AI solutions from any AI environment.
214 tools for AI agents over one MCP endpoint: image, video, audio, 3D, data, storage, mail, GPUs.
CAD in ChatGPT and Claude: editable parts, STEP/STL/drawings, in-chat 3D, automatic checks.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI agents and software to create, edit, inspect, validate, and export CAD geometry through MCP using backend-neutral typed operations, with FreeCAD/OpenCascade as the authoritative B-rep backend and JSCAD preview.1Apache 2.0
- AlicenseAqualityCmaintenanceEnables AI agents and MCP clients to perform 3D asset creation and verification: exact b-rep CAD, GLB validation with embedded certificates, mesh inspection, and physics scenes, with most tools running without Blender.3648 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to model, sculpt, rig, animate and bake particle effects by editing a semantic scene document, with built-in software rendering, measurable critics that flag floating or broken geometry, and game-ready glTF export. It exposes templates, atomic edit batches, motion and effect previews, undo history, and no GPU, browser, or Blender required.0Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to design, modify, and verify exact B-rep 3D CAD models by running build123d scripts on an OpenCascade kernel, with live three.js preview, collision and FDM printability checks, text-based spatial perception, user notes/sketch annotations, version history, and one-click export to OrcaSlicer.1MIT