Atlas / MCP servers / pzfreo / Build123d

Build123dBLOCK

mcp/pzfreo/build123d

MCP server for build123d to improve AI cognition when creating 3D CAD models

Verdict
BLOCK
Grade
F
Trust score
46 /100
Exposed tools
44 30r · 12w · 2d
Transport
stdio · streamable-http
License
Apache-2.0
Stars
110
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://pypi.org/project/build123d-mcp/) [](https://pepy.tech/project/build123d-mcp) [](https://pypi.org/project/build123d-mcp/) [](https://github.com/pzfreo/build123d-mcp/actions/workflows/ci.yml) [](LICENSE) [](https://registry.modelcontextprotocol.io/v0/servers?search=build123d) [](https://glama.ai/mcp/servers/pzfreo/build123d-mcp)

[](https://insiders.vscode.dev/redirect/mcp/install?name=build123d-mcp&config=%7B%22command%22%3A%22uv%22%2C%22args%22%3A%5B%22tool%22%2C%22run%22%2C%22--python%22%2C%223.12%22%2C%22build123d-mcp%40latest%22%5D%7D) [](https://cursor.com/en/install-mcp?name=build123d-mcp&config=eyJjb21tYW5kIjoidXYiLCJhcmdzIjpbInRvb2wiLCJydW4iLCItLXB5dGhvbiIsIjMuMTIiLCJidWlsZDEyM2QtbWNwQGxhdGVzdCJdfQ==)

Give your AI CAD eyes.

build123d-mcp is not a standalone chatbot or CAD program. It is a CAD toolbox that an AI/LLM app can use through MCP.

With an LLM app such as Claude, Cursor, VS Code, Continue, Cline, or Codex CLI, build123d-mcp lets the assistant create build123d CAD models, render previews, measure geometry, fix mistakes, and export files such as STEP, STL, SVG, and DXF. Instead of writing a whole CAD script blindly, the assistant can build a part in small steps and check the result as it goes.

On the public [CADGenBench](h

Read from source at commit de8e6242de54OBSERVED · 2026-10-08
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control.

claude-code (pypi)
claude mcp add build123d-mcp -- None build123d-mcp==0.3.91
03

Exposed tools (44)

30 read · 12 write · 2 destructive. Blast radius: 2 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
analyze_printabilityreadAnalyse a build123d shape for FDM printability using augura (BREP-exact analysis).
bank_candidatereadAtomically promote a gate-clean STEP as the safe output/checkpoint. Writes the candidate to a private sibling file, runs the authoritative written-and-reimported STEP gate, and replaces filename only on a fully verified PASS; on FAIL or an unchecked mesh gate, the candidate is deleted and any existi
comparereadUnified comparison tool.
crop_drawingwriteSave one model-selected raster drawing region at readable scale. bbox_px is exact source-image [x0,y0,x1,y1]; scale is 0.25..12. Returns the saved PNG path and an exact crop-pixel→source-pixel transform, so coordinates read from the enlargement remain usable. This is a mechanical crop only: it perfo
cross_sectionsreadCompute cross-sectional areas at evenly spaced planes along an axis. Returns a list of {position, area} pairs. axis: X, Y, or Z (default Z). num_slices: number of planes (default 10, minimum 2). Useful for detecting internal voids, wall-thickness variation, or verifying that a shape
design_auditreadAudit the current session program as a *design*, not just a shape: surface its named numeric parameters (Θ) and test how robust each is to editing. Parses the assembled program (see script()) for top-level numeric assignments (e.g. `plate_thickness = 5.0`), then rebuilds the program with each parame
destroy_sessiondestructiveClose THIS client
edit_featurewriteTransactionally resize one plain cylindrical through hole identified by a current @feature handle. Reject holes with counterbores, spotfaces, countersinks or multiple constituent faces. Predict the annular volume change, then check exact added/removed material, hole recognition, every other hole and
executewriteExecute build123d Python code in the persistent session. Errors include automatic fix hints — read them before retrying. Use show(shape, name) to register named objects (name defaults to
execute_filewriteExecute a canonical build123d .py file in a clean namespace and atomically promote its result. The prior active model is restored if the source has a syntax/runtime error, times out, produces no shape, or does not produce result_name. Assign a Shape to `result` or call show(); optionally set result_
exportreadExport model. format: step, stl, 3mf, dxf, svg, or comma-separated list e.g.
find_bored_bosseswriteFind candidate bored bosses and report target-selection/edit evidence: bore opening location, axis into the part, outward axis, bore diameter/depth, planar cap faces at the opening, whether the cap is split across multiple faces, and construction advice. Use this before lengthening any boss that car
find_bossesreadRecognise external cylindrical bosses on a session object (defaults to current shape), including a turned part
find_candidatesreadList recognised instances of a hole, boss, polygonal boss, slot, chamfer or fillet. qualifiers is JSON with optional axis (X/Y/Z), side (+X/-X/+Y/-Y/+Z/-Z, relative to the part bounding-box centre), and value_field; matches are reported for the literal axes and grouped over all 24 proper rotations o
find_countersinksreadRecognise countersinks (conical screw-head recesses) on a session object (defaults to current shape) — the feature find_holes reports only as a plain opening. A countersink is an internal cone flaring from a drilled bore out to a larger opening, coaxial with the drill; drill-point cones and external
find_hole_patternsreadRecognise hole patterns on a session object (defaults to current shape): ≥3 identical-spec holes equally spaced on a circle → bolt_circle (center, diameter/BCD), collinear at constant pitch → linear_array (pitch, direction). Returns JSON: {count, patterns: [{type, holes: [HoleFeature records], cente
find_holesreadRecognise drilled holes on a session object (defaults to current shape). Coaxial internal cylinders are grouped into one record per hole: drill + counterbore + spotface stacks, keyway-split bores, and bores interrupted by crossing holes all count once. Returns JSON: {count, holes: [{axis (drilling d
health_checkreadVerify that render and export dependencies are working. Tests PNG render (VTK), SVG render (build123d HLR), STEP export, and STL export with a trivial shape. Returns JSON with ok/error per capability. Run at session start if you suspect a missing dependency.
import_cad_filewriteImport a STEP (.step/.stp), STL (.stl), or 3MF (.3mf) file as a named object in the session. path: absolute or relative path to the file. name: name to register the shape under (defaults to the filename stem). The shape becomes both the named object and the current_shape. A multi-object 3MF register
inspect_partreadReturn one compact generation-checkpoint inventory: bbox, solid/topology counts, holes grouped by axis/diameter/depth/bottom, bosses grouped by axis/diameter/height, recognised patterns with member counts, and a cross-section area profile. expected is an optional JSON object derived from the drawing
install_skillwriteCopy a b123d workflow skill into the current project.
interface_featuresreadSuggest planar mounting faces from recognised hole openings, with exact hole handles. These are geometric candidates, not a declaration of design intent. Pass chosen hole handles as protected_refs to edit_feature(); that edit also checks every other recognised hole and the outer envelope.
last_errorwriteReturn details of the last failed execute() call: exception type, message, and (for runtime and syntax errors) line number and a 5-line excerpt around the failing line. Security errors include a message but no line/excerpt. Returns {\
list_sessionsreadReport how many CAD sessions this server process is holding, its configured limit, and how long each has been idle. Handles are secrets and are never returned. Operator/diagnostic tool for HTTP deployments — over stdio there is always exactly one session.
load_partreadLoad a named part from the library into the session. name: part name from search_library. params: optional JSON object of parameter overrides e.g.
locate_gate_defectsreadReport WHERE a solid fails the validity gate, with 3D coordinates — so you can fix the exact edge/face instead of guessing. validate()/export() tell you WHAT is wrong (e.g.
measurereadMeasure a shape and return a complete geometric summary: volume (mm3), surface area (mm2), topology (face/edge/vertex counts), bounding box with per-axis size and center, volumetric center of mass, 6-component inertia tensor (Ixx/Iyy/Izz/Ixy/Ixz/Iyz), and a face-type inventory classifying every face
mesh_holesreadFind fastener holes in a MESH by slicing it on all three axes. Returns JSON {count, holes:[{axis, diameter, location, span, depth, through}]} where axis is the drilling direction and location is the hole centre in world coordinates. This is the mesh counterpart to find_holes(), which needs real topo
mesh_sectionreadLoops on one cross-section plane of a mesh, largest first. Returns JSON {axis, position, loop_count, enclosed_passages, loops:[{points, center, size, min, max, enclosed}]}, all in the two axes that are not `axis`. enclosed_passages counts loops at odd nesting depth, representing passages through mat
prepare_drawingreadPrepare a raster engineering drawing for efficient inspection. Detects substantial spatial regions, saves one labelled overview plus readable PNG crops, and returns their pixel bounding boxes and paths. Region ids are layout evidence only: this tool does NOT label views, recognise CAD features, inte
recognise_featureswriteRun the shared quiddity inventory once and return exact, run-local edit evidence. With families=
render_viewreadRender model. Auto-detects 3D vs 2D: solids use VTK; flat drawings use the 2D pipeline. Renders confirm appearance, not geometry. format: png, svg, dxf, or both. direction accepts top, bottom, front, rear, side, left, right, or iso. quality: preview, standard, or high; a timed-out standard/high PNG
repair_advicewriteReturn structured, field-proven repair/edit recipes for an agent to implement explicitly in execute(). Unlike repair_hints(), which gives short error-specific tips, this emits a sequenced plan with code-pattern names, acceptance checks, and stop conditions. Provide the full validate()/export()/last_
repair_hintsreadGiven an error message or validity-gate reason, return targeted fix suggestions for common build123d mistakes and gate failures: wrong Location syntax, missing .part, CadQuery idioms, blocked imports, degenerate boolean results, fillet edge selection, B-rep defects, mesh non-manifold/open-edge failu
resetdestructiveClear the current session back to empty state, including all snapshots.
resolvereadEvaluate a selector expression against a named object and return a geometry descriptor. selector is a Python expression suffix applied to the object, e.g.
restore_snapshotreadRestore geometric state from a previously saved snapshot (current_shape and the show() registry).
save_snapshotwriteSave a named checkpoint of the current geometric state (current_shape and the show() object registry).
scriptreadReturn a single Python script assembled from all successfully executed code blocks in this session. Prepends
search_libraryreadSearch the part library. query: keywords matched against name, description, tags, category (empty returns all). Returns name, category, description, tags, and full parameter specs including types, defaults, and descriptions.
session_statereadReturn a structured JSON snapshot of the current session: current_shape metrics, all named objects (replaces list_objects) with geometry stats, snapshot names, and a variables summary of the Python namespace (type + volume for shapes, type + length for collections, type + value for scalars). Use thi
validatereadCheck whether a shape would pass a CAD validity gate before exporting it. Returns a PASS/FAIL verdict plus JSON (passes_gate, n_solids, volume, is_manifold, brep_valid, reasons). The gate mirrors what strict CAD and mesh consumers require: a well-formed (BRepCheck), watertight, manifold solid with n
versionreadReturn the installed versions of the build123d-mcp server, its key dependencies (build123d, build123d-drafting-helpers), and the companion packages importable inside execute() (bd_warehouse for threads/fasteners/gears/bearings, augura for printability analysis). Use this to confirm which server buil
workflow_hintswriteReturn guidance on how to use these tools effectively. Call this at the start of a session or whenever unsure which tool to reach for.
04

Trust audit

BLOCKgrade F · trust 46/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)FAIL
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (5 observation(s))
Network
none-observed
Shell
declared (7 observation(s))
Dependencies
pinned
Secrets in source
none-found

Findings (25)

CRITICALPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
<tool:list_sessions>:1
Report how many CAD sessions this server process is holding, its configured limit, and how long each has been idle. Handles are secrets and are never returned. Operator/diagnostic tool for HTTP deploy
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
HIGHCode injection · code.deserialize · CWE-78, CWE-94, CWE-95
src/build123d_mcp/_vtk_render_subprocess_worker.py:22
args = pickle.load(f)
Why it matters. deserialises untrusted bytes into live objects
Fix. use json or yaml.safe_load
HIGHCode injection · code.deserialize · CWE-78, CWE-94, CWE-95
src/build123d_mcp/tools/render.py:506
result = pickle.load(f)
Why it matters. deserialises untrusted bytes into live objects
Fix. use json or yaml.safe_load
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/build123d_mcp/session.py:806
exec(compiled, self.namespace)  # noqa: S102
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/build123d_mcp/tools/library.py:160
exec(compile(source, entry["path"], "exec"), namespace)  # noqa: S102
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/build123d_mcp/tools/resolve.py:234
result = eval(expression, namespace)  # noqa: S307
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMInventory / provenance · inv.binary · CWE-1104
.coverage
.coverage
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.symlink · CWE-1104
.claude/skills/b123d-drawing/SKILL.md
.claude/skills/b123d-drawing/SKILL.md
Why it matters. link not followed
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
src/build123d_mcp/bd_warehouse_resource.py:158
m = importlib.import_module(mod_name)
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
src/build123d_mcp/worker.py:277
fn = getattr(importlib.import_module(module_name), func_name)
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
destroy_session, reset
Why it matters. 2 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.coverage
.coverage
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
tests/test_worker_boundary_coverage.py:76
fn = getattr(importlib.import_module(module_name), func_name)
LOWFilesystem / path · fs.system_paths · CWE-22, CWE-59
tests/test_allow_all_imports_sandbox.py:29
check_ast("open('/etc/passwd')")
LOWFilesystem / path · fs.system_paths · CWE-22, CWE-59
tests/test_no_sandbox.py:49
check_ast("open('/etc/passwd'); getattr(x, '__class__')")  # must not raise
LOWFilesystem / path · fs.system_paths · CWE-22, CWE-59
tests/test_outcomes.py:143
result = execute_code(session, "data = open('/etc/passwd').read()")
LOWFilesystem / path · fs.system_paths · CWE-22, CWE-59
tests/test_path_safety.py:30
r"C:\Windows\System32\drivers\etc\hosts" if sys.platform == "win32" else "/etc/passwd"
LOWFilesystem / path · fs.system_paths · CWE-22, CWE-59
tests/test_tools.py:22
r"C:\Windows\System32\drivers\etc\hosts" if sys.platform == "win32" else "/etc/passwd"
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_path_safety.py:32
_TRAVERSAL = "../../etc/passwd"
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_tools.py:1601
export_file(session, "../../etc/passwd", "step")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_tools.py:2025
render_view(session, "iso", save_to="../../etc/passwd")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_viewer.py:389
assert mod._safe_filename("../../etc/passwd") == "passwd.glb"  # cannot escape
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
.github/workflows/ci.yml:94
body=$(curl -s -X POST http://127.0.0.1:3111/mcp \
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
.github/workflows/ci.yml:123
--url http://127.0.0.1:3111/mcp \
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
tests/test_outcomes.py:1050
png_bytes = base64.b64decode(img_data)

Gates applied: critical_finding, no_behavioural_pass, undeclared_transfer.

Audited 2026-10-08 · audit v0.4.1 · source sha de8e6242de54full audit observations/trust-audit/mcp-server/pzfreo__build123d.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-08de8e6242de54BLOCKF46first audit
06

Questions

What is the Build123d MCP server?

MCP server for build123d to improve AI cognition when creating 3D CAD models

What tools does Build123d expose?

44 in total: 30 read-only, 12 that write, and 2 that can delete or overwrite (destroy_session, reset). Every one is listed on this page with its risk.

Is Build123d safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (46/100) and found 6 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 2 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Build123d need?

No credential environment variables were found in its source, so it appears to need none.

How does Build123d run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on PyPI as build123d-mcp.

How current is this page?

The grade is for one exact copy of the source (de8e6242de54), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement