build123d MCP
PYPI · BUILD123D-MCP
AI-driven 3D CAD via build123d: execute, render, measure, and export geometry interactively.
Available components
Last scanned (12 hours ago)
Scores higher than 90% of PyPI servers
Category Design and Media
Recent critical change
GHSA-6q48-6c7w-9gw2 affects this package (21 Oct 2026). See the changelog before you install this server.
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security99
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 20 of 102 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency100
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to pzfreo/build123d-mcp). View diagnostics → Pass
- Clear OSI-approved license (Apache-2.0).Pass
- Actively maintained (last published 20 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability76
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 10246 tokens (~173/item across 59 items; 48 tools + 11 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management57
- Stability observed for 17 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
- Structured output schemas are declared (96% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 50 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Checks we ran (16)
- Malware scan
- Known CVEs
- Install scripts
- Dependency health
- Source repository
- Provenance
- License
- Maintenance
- Security disclosure
- Schema quality
- Stability
- Tool coverage
- Injection markers
- Destructive annotations
- Judged manipulation
- MCP protocol
Does not apply to this package (2)
- Endpoint SecurityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
- Transport & ReachabilityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
The score does not measure everything. What the score does not measure →
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 53 to 57. That category is still filling its 30-day observation window: 16 days of observed history at the previous scan, 17 at this one. The score rises as the window fills, whether or not the server changes.
- 2 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.
- 31 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.
- 29 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.
- 27 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.
- 25 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 17 to 20. That category is still filling its 30-day observation window: 5 days of observed history at the previous scan, 6 at this one. The score rises as the window fills, whether or not the server changes.
- 23 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 10 to 13. That category is still filling its 30-day observation window: 3 days of observed history at the previous scan, 4 at this one. The score rises as the window fills, whether or not the server changes.
- 22 Oct 26 +80
- GHSA-6q48-6c7w-9gw2 no longer affects this package ▲ security
- Known CVEs: fail → pass ▲ security
- Score status: failed → scored ▲ functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Analysed pypi/build123d-mcp@0.3.91
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | pzfreo/build123d-mcp |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/pzfreo/build123d-mcp/.github/workflows/publish.yml@refs/tags/v0.3.91 |
| Rekor log index | 3268933838 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:16cbc0ddf4fe8bc5ebfd8da44509c4f52c3f1aafbab8c8575cc9f5fbe58b9ac0 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | Known build tool | hatchling.build |
Background: Why install scripts are a supply-chain risk →
Dependencies 102 packages
| Packages resolved | 102 |
|---|---|
| Stale | 13 |
| No linked repository | 7 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
analyze_printability ~321
Analyse a build123d shape for FDM printability using augura (BREP-exact analysis). Checks: overhangs, manifold/watertight, tip-over risk, brim/raft need, minimum vertical feature (→ max layer height), and thin walls. Optionally checks bed-fit against a declared build volume. Returns a plain-text summary followed by a JSON report with per-finding detail (kind, severity, message, area/location where applicable). object_name: named object from show() (default: current shape). support_angle: faces shallower than this many degrees from horizontal need support (default 45). nozzle: nozzle diameter in mm for wall-thickness check (default 0.4). min_perimeters: walls thinner than min_perimeters × nozzle are flagged (default 2). build_volume: optional build envelope as 'X Y Z' in mm, e.g. '256 256 256'; omit to skip the bed-fit check. bed_tol: Z tolerance in mm for identifying bed-contact faces (default 0.001); raise it for parts whose bottom faces sit slightly off Z=0. min_feature: minimum vertical feature size in mm to flag (default 0.5).
| Name | Type | Req | Description |
|---|---|---|---|
| bed_tol | number | – | – |
| build_volume | string | – | – |
| min_feature | number | – | – |
| min_perimeters | integer | – | – |
| nozzle | number | – | – |
| object_name | string | – | – |
| support_angle | number | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
bank_candidate ~151
Atomically 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 existing output is preserved. If snapshot_name is supplied, the geometry snapshot is saved only after promotion. Returns JSON including banked, preservation/snapshot status, the export report, and the next recommended recognition or repair call. Use this instead of batching export() and save_snapshot() for scored floors and final candidates.
| Name | Type | Req | Description |
|---|---|---|---|
| filename | string | yes | – |
| object_name | string | – | – |
| snapshot_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
compare ~207
Unified comparison tool. kind='shape' compares two named shapes from show(), a and b, by volume/bbox/topology and localized surface deviation; b is required. kind='fit' reports the spatial relationship between two named shapes, a and b: clearance, apart/touching/containing/interpenetrating status, containment, and overlap volumes; b is required. kind='align' checks two named shapes, a and b, along one axis. axis: X, Y, or Z. mode: flush (bbox extreme offset), center (centroid offset), or clearance (nearest-face gap); b is required. kind='snapshot' compares snapshot a against the current session state or b as a second snapshot. format: 'text' or 'json'.
| Name | Type | Req | Description |
|---|---|---|---|
| a | string | yes | – |
| axis | string | – | – |
| b | string | – | – |
| format | string | – | – |
| kind | string | – | – |
| mode | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
crop_drawing ~130
Save 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 performs no OCR, feature recognition, or geometry inference.
| Name | Type | Req | Description |
|---|---|---|---|
| autocontrast | boolean | – | – |
| bbox_px | array | yes | – |
| image_path | string | yes | – |
| output_path | string | – | – |
| scale | number | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
cross_sections ~122
Compute 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's cross-section profile matches a reference. object_name: named object from show() (default: current shape).
| Name | Type | Req | Description |
|---|---|---|---|
| axis | string | – | – |
| num_slices | integer | – | – |
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
design_audit ~367
Audit 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 parameter nudged ±epsilon (default ±10%) in a hard-bounded subprocess (the live session is never mutated) and runs the validity gate on each result. Returns JSON: {parameters, baseline, audit:[{name, value, perturbations:[{delta_pct (realized), new_value, discrete_step?, rebuilt, passes_gate, volume_delta_pct, reasons?}], brittle}], summary:{robust, brittle, inconclusive, ...}, note}. A parameter is `brittle` if a small change fails to rebuild or drops below the validity gate — the thin-wall / coordinate-reasoning failure mode where a valid *shape* is not an editable *design* (Arko-T §6); a parameter reassigned at the top level is `inconclusive` (perturbation is overwritten), not counted as robust. If no named parameters are found, the program uses inline magic constants and the note advises hoisting them to a parameter block. Known limitation: only literal-valued top-level names are surfaced as Θ — a derived parameter (`radius = diameter / 2`) is not listed, though perturbing its upstream literal flows through. Bounded by a wall-clock budget and max_params (returns a partial report rather than risking a timeout). epsilon: relative nudge, 0<epsilon<1. max_params: cap on parameters audited.
| Name | Type | Req | Description |
|---|---|---|---|
| epsilon | number | – | – |
| max_params | integer | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
destroy_session ~72
Close THIS client's CAD session, discarding its namespace, objects and snapshots, and release its worker subprocess. The next tool call transparently starts a fresh session under the same handle. Use when abandoning a model entirely; prefer reset() to clear geometry while keeping the session. Only meaningful over HTTP with a session handle configured.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
edit_feature ~143
Transactionally 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 the outer envelope before registering the result. protected_refs is a JSON list of other hole handles; the target itself cannot be protected. On failure no result is registered. Defaults to replacing the named source; result_name can preserve it under a new name.
| Name | Type | Req | Description |
|---|---|---|---|
| diameter | number | yes | – |
| handle | string | yes | – |
| protected_refs | string | – | – |
| result_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
execute ~472
Execute 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 'shape'); show() immediately prints volume and face count confirming the shape is non-empty. After any boolean operation (-, +, &) call measure() to confirm it succeeded (check topology.faces). named_face(shape, name) is a built-in helper: named_face(box, 'top') returns the highest-Z face, 'bottom'/'front'/'back'/'left'/'right' work similarly. find_edges(shape, geom='circle', radius=4.25, at_z=10.2, length=None, tol=0.05) filters edges for fillet/chamfer selection and prints what matched. Analysis primitives are callable INSIDE this execute() code and return real Python objects so you compose (filter, do arithmetic) instead of copying numbers out of a tool result: measure(shape) -> dict (measure(part)['volume']), clearance(a, b) -> dict, cross_sections(shape) -> list of {position,area}, find_holes(shape) -> hole records with .location (an (x,y,z) tuple), .diameter, .depth, … ([h for h in find_holes(part) if h.location[0] < 5]); find_bosses(shape) / find_bored_bosses(shape) / find_countersinks(shape) / find_hole_patterns(shape) return recogniser records too; align_check(a, b, axis='Z', mode='flush') -> dict (align_check(a,b)['delta'] is a float). For standalone MCP comparison calls, use compare(a='axle', b='frame', kind='fit'), compare(a='a', b='b', kind='align'), compare(a='before', b='after', kind='shape'), or compare(a='before', kind='snapshot'). shape defaults to the current shape, and measure/clearance/cross_sections stay bounded on large shapes. save_json(name, obj) writes structured analysis data (face inventories, hole tables) to a server scratch file and returns its path — use it instead of printing large results; open()/os stay blocked.
| Name | Type | Req | Description |
|---|---|---|---|
| code | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
execute_file ~176
Execute 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_name to require/register a specific Shape or BuildPart variable. snapshot saves the promoted geometry checkpoint. Returns source SHA-256 provenance plus captured output. The source must be UTF-8, under an allowed read root, and no larger than BUILD123D_MAX_SCRIPT_BYTES (default 2 MiB). Use this for substantial generation revisions: edit model.py, execute_file(), then validate/measure/render/export through MCP.
| Name | Type | Req | Description |
|---|---|---|---|
| path | string | yes | – |
| result_name | string | – | – |
| snapshot | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
export ~315
Export model. format: step, stl, 3mf, dxf, svg, or comma-separated list e.g. 'step,stl' or 'dxf,svg'. 3D shapes (solids) export to step/stl/3mf; 2D shapes (Sketches and dimensioned drawings composed via build123d.drafting) export to dxf/svg. 3mf is a minimal core-spec mesh export (single object, no color/material) intended for slicers (Bambu Studio, PrusaSlicer, Orca) — use step for downstream CAD interop instead. Mixing 2D and 3D formats for the same shape errors with a clear message. object_name: named object from show(), '*' to export all named shapes as a combined assembly (default: current shape). STEP exports carry the session names as labels — single-object exports use the object_name, '*' exports produce a Compound labelled 'assembly' with each child labelled by its show() name. Downstream CAD tools (FreeCAD, Fusion) will see the structured assembly with named bodies. Use dxf for engineering-drawing handoff to other CAD tools; svg for embedding in docs/wikis. The result echoes the exported shape's volume/bbox/face count (or bbox/edge count for 2D) as a final sanity check that the right, non-degenerate object was written.
| Name | Type | Req | Description |
|---|---|---|---|
| filename | string | yes | – |
| format | string | – | – |
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
find_bored_bosses ~99
Find 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 carries a bore, whatever its outer profile; it is read-only and diagnostic, not proof of the requested target.
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
find_bosses ~80
Recognise external cylindrical bosses on a session object (defaults to current shape), including a turned part's OD — filter on diameter against the part envelope for local bosses only. Returns JSON: {count, bosses: [{axis (base toward free end), location (free-end point), diameter, height}]}.
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
find_candidates ~167
List 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 of the request frame (no mirror readings, none preferred). stated_value is checked against the measured feature value within 0.1 mm or 1%. An unmatched value is flagged; empty or truncated recognition is never treated as proof of absence. Returns exact @feature handles for recognised instances.
| Name | Type | Req | Description |
|---|---|---|---|
| kind | string | yes | – |
| object_name | string | – | – |
| qualifiers | string | – | – |
| stated_value | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
find_countersinks ~160
Recognise 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 edge chamfers are excluded. Returns JSON: {count, countersinks: [{location (opening centre), axis (into the part), major_diameter (countersink Ø at the surface), drill_diameter, included_angle (deg, e.g. 82/90/100/120), depth}]}. object_name: named object from show() (default: current shape).
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
find_hole_patterns ~111
Recognise 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], center/diameter | pitch/direction}]}. Each hole belongs to at most one pattern; make_drawing already annotates these automatically.
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
find_holes ~168
Recognise 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 direction, unit vector), location (opening point), diameter, depth (bore top to deep end; drill-point cone excluded), bottom: through|flat|drill_point|unknown, cbore: {diameter, depth}|null, spotface: {diameter, depth}|null}]}. Countersinks read as openings (not steps); threads and non-cylindrical features are not recognised.
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
health_check ~63
Verify 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.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
import_cad_file ~259
Import 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 registers an aggregate under name plus each member as name_1, name_2, etc.; the result includes per-member topology summaries. After importing, use render_view() to visualise the shape, measure() for geometry queries, or compare(a='imported', b='model', kind='shape') to diff against a show() object. Note: STL imports produce a shell (volume=0) rather than a solid. 3MF commonly yields editable solids when its meshes are closed, but callers must check the returned solids and volume fields rather than assuming every mesh is valid. If you have both the original built shape and an imported copy in session.objects, render the imported one by name (e.g. objects='mypart') to avoid Z-fighting artifacts from two co-located shapes.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | – | – |
| path | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
inspect_drawing ~374
DEPRECATED (#465) — moved to draftwright; off by default in 0.4.0, removed in 0.5.0. Calling it explains the replacement. Structured bbox and annotation report for a 2D drawing. Two modes: 1. Session mode (default): inspects objects registered via annotate()/show(). Returns per-object bounding boxes, face/edge counts, annotation metadata (label string, measured length, Leader tip/elbow), and structural lint. 2. SVG mode (svg_path set): parses an SVG file from disk and reports page size, layer ids, text content + positions, and element counts. Decouples inspection from the build-and-register ceremony — works on SVGs from any source (CI artifacts, third-party exports, prior runs). Use annotate(result, name) instead of show(result.shape, name) when building with build123d_drafting so metadata is captured: from build123d_drafting import Dimension, Draft draft = Draft(font_size=2.5, decimal_precision=1) w = Dimension((-20, -10, 0), (20, -10, 0), "below", 8, draft, label="40") annotate(w, "width_dim") For vanilla build123d.ExtensionLine/DimensionLine, pass the label explicitly: w = ExtensionLine(border=[...], offset=6, draft=draft, label="40") annotate(w, "width_dim", label="40") Args: objects: comma-separated object names (default: all). Session mode only. svg_path: path to an SVG file on disk. Switches to SVG mode.
| Name | Type | Req | Description |
|---|---|---|---|
| objects | string | – | – |
| svg_path | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
inspect_part ~216
Return 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/spec; supported keys are bbox [x,y,z], solid_count, holes/bosses/patterns group lists, section_varying, and tolerance. Pattern groups can check type, diameter, pitch, direction, center, member_count, and member_diameter. A supplied feature category is an exact inventory: unexpected or ambiguously matched groups fail. With expectations, returns explicit PASS/FAIL plus mismatches. Without them, returns INVENTORY plus heuristic warnings for shallow partial cuts and nearly constant sections. Unsupported expectation keys are rejected; this tool contains no built-in fixture expectations.
| Name | Type | Req | Description |
|---|---|---|---|
| expected | string | – | – |
| object_name | string | – | – |
| section_axis | string | – | – |
| section_slices | integer | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
install_skill ~265
Copy a b123d workflow skill into the current project. Writes the appropriate config file for the requested agent so the step-by-step workflow is available in future sessions. skill: which workflow to install (default "modeling") - drawing → DEPRECATED; still installs, but drawing generation has moved to draftwright, which publishes its own skill (#465) - modeling → build 3D parts/assemblies (incl. from technical drawings) - edit → modify existing build123d code and verify geometry deltas - repair → repair a solid that fails the validity gate target: one of "claude" (default), "agents-md", "cursor", "windsurf" - claude → .claude/skills/<skill-dir>/SKILL.md (Claude Code) - agents-md → AGENTS.md (Codex CLI, Antigravity, GitHub Copilot, Cline) - cursor → .cursor/rules/<skill-dir>.mdc - windsurf → .windsurfrules force: overwrite existing installation (default False)
| Name | Type | Req | Description |
|---|---|---|---|
| force | boolean | – | – |
| skill | string | – | – |
| target | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
interface_features ~66
Suggest 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.
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
last_error ~99
Return 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 {"error": null} if the last execute() succeeded or no execute() has failed yet. Call this immediately after an execute() error to get the exact failing line — much faster than re-reading the submitted code.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
lint_drawing ~444
DEPRECATED (#465) — moved to draftwright; off by default in 0.4.0, removed in 0.5.0. Calling it explains the replacement. Run structural drawing-quality checks and return JSON {violations: [...]}. Session mode (default): reconstructs the session's annotations and delegates to build123d-drafting-helpers (lint_drawing + find_interferences) — single source of truth. Surfaces label-vs-measured divergence (axis swap), Leader line through its own label, annotation/label overlap, a witness/extension line piercing a neighbour's label, redundant collinear lines, and page-bounds overshoot. SVG mode (svg_path set): scans an SVG file for export-only pathologies — most importantly native <text> elements (build123d renders glyph paths, so any <text> won't DXF-export and won't scale with the model). drawing_scale: when the geometry was scaled up before projecting — e.g. a 7.5 mm feature drawn at 5:1 via part.scale(5) — pass the same factor (5.0) so the label-vs-measured check divides each measured path length by it before comparing to the label. This lets labels carry the *real* dimension while the geometry is drawn enlarged, instead of every dim tripping a false axis-swap warning. Session mode only; defaults to 1.0 (no scaling). view_shape_names: list of shape names (from show()) representing the placed view outlines. Used to detect view_annotation_overlap (annotation bbox overlaps a view outline) and view_overlap (two view outlines overlap). Pass the visible-side placed compounds from each projection, e.g. ["front_placed", "side_placed", "plan_placed", "iso"]. Session mode only. Each violation is {severity, check, object, message}. Run this after major drawing additions; running it BEFORE rendering catches the bug at the source.
| Name | Type | Req | Description |
|---|---|---|---|
| drawing_scale | number | – | – |
| svg_path | string | – | – |
| view_shape_names | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
list_sessions ~58
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 deployments — over stdio there is always exactly one session.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
locate_gate_defects ~361
Report 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. "1 non-manifold edge", "BRepCheck failed") but not where; call this when validate() FAILs to get a per-defect list: brep_invalid_face (face index + center + BRepCheck status, e.g. an unorientable BSpline), open_edge / nonmanifold_edge (B-rep edge midpoint + faces_incident), the mesh self-touches strict CAD/mesh consumers reject — mesh_nonmanifold_edge (edge midpoint) and mesh_nonmanifold_vertex (corner-to-corner touch point), mesh_untriangulated_face (a face that cannot tessellate at the base tolerance), mesh_refined_untriangulated_face (a face that only fails at a finer tolerance) — and mesh_vertex_deflection_defect (a tessellated edge endpoint that misses its own BREP vertex by more than the mesh deflection — a patched/healed face whose boundary is topologically closed but geometrically off-vertex; BRepCheck and even the open-edge count can both read clean, but a strict mesh sanity check still rejects it). Each defect includes a generic repair hint plus diagnostic_class / repair_family / next_step metadata; the top-level diagnosis block counts defect kinds and recommends the next verification path. An empty list means the part passes the structural checks. Bounded out-of-process (it mesh-checks), so a huge part returns a clean budget error rather than hanging. object_name: named object from show() (default: current shape).
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
measure ~252
Measure a shape and return a complete geometric summary: volume (mm³), surface area (mm²), 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 as Plane/Cylinder/Cone/Sphere/Torus/BSpline with area and type-specific params (e.g. cylinder diameter and axis); identical faces are collapsed with a count, non-analytic sliver faces folded into one summary line. Prefer measure over render_view for verifying geometry — numbers are unambiguous. topology is the fastest confirmation that a boolean operation succeeded: a failed cut leaves face/edge/vertex counts unchanged. object_name: named object from show() (default: current shape). density (g/cm³) or material preset (steel, stainless, aluminum/6061, brass, copper, titanium, abs, pla, petg, nylon) adds mass_g and scales inertia to true mass moments in g·mm².
| Name | Type | Req | Description |
|---|---|---|---|
| density | number | – | – |
| material | string | – | – |
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
mesh_holes ~279
Find 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 topology and returns nothing for an imported STL - the usual case when remixing a downloaded model and you need its existing mounting features before designing a part that bolts on. Read `depth` and `through`: a blind pocket a few mm deep is a heat-set insert seat, not a screw hole, and coaxial pockets bored into opposite faces are reported separately rather than merged into one false through hole. min_diameter/max_diameter default to M2-M8 clearance, counterbores and insert pockets. min_depth drops chamfer rings and tessellation slivers. It reports what the cross-sections show and does not classify countersinks or thread forms. object_name: named object from show()/import_cad_file (default: current shape).
| Name | Type | Req | Description |
|---|---|---|---|
| max_diameter | number | – | – |
| min_depth | number | – | – |
| min_diameter | number | – | – |
| object_name | string | – | – |
| slices | integer | – | – |
| tolerance | number | – | – |
| weld | number | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
mesh_section ~184
Loops 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 material at this height. An open groove reads 0. Works on imported STL shells and solids. axis: X, Y or Z (the plane normal). position: absolute world coordinate. tolerance: tessellation tolerance. weld: point-merge distance when chaining segments. object_name: named object from show()/import_cad_file (default: current shape).
| Name | Type | Req | Description |
|---|---|---|---|
| axis | string | – | – |
| object_name | string | – | – |
| position | number | – | – |
| tolerance | number | – | – |
| weld | number | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
prepare_drawing ~178
Prepare 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, interpret lines, infer dimensions, or trace geometry. Use it once near the start instead of repeatedly writing shell/PIL crop scripts; inspect the returned overview and only the relevant crops. Printed dimensions remain authoritative. image_path: PNG/JPEG/TIFF drawing under an allowed read root. output_dir: crop directory under an allowed write root. max_regions: 1..30. padding: crop padding in pixels, 0..500.
| Name | Type | Req | Description |
|---|---|---|---|
| image_path | string | yes | – |
| max_regions | integer | – | – |
| output_dir | string | – | – |
| padding | integer | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
recognise_features ~194
Run the shared quiddity inventory once and return exact, run-local edit evidence. With families='' the response is a compact inventory and targetable-family count; pass comma-separated families such as 'holes,bosses,blends' for structured records and @feature handles. Returned handles are usable inside execute() as recognition_faces(handle), or recognition_faces(handle, role='defining'), and fail if their source geometry has been replaced. coordinate_frame='caller' (default) preserves the imported model coordinates used by edit instructions; 'part' uses a rigid-equivariant part-relative frame and returns that frame. include_faces adds exact caller-face indices and geometry descriptors. max_features limits expanded records to 1..100; counts remain exact.
| Name | Type | Req | Description |
|---|---|---|---|
| coordinate_frame | string | – | – |
| families | string | – | – |
| include_faces | boolean | – | – |
| max_features | integer | – | – |
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
render_drawing ~206
DEPRECATED (#465) — moved to draftwright; off by default in 0.4.0, removed in 0.5.0. Calling it explains the replacement. Rasterise an existing SVG file to PNG via resvg-py. Complements render_view (which takes build123d shapes from the live session) by accepting an SVG written outside the sandbox — typically by a short Python script that does the ExportSVG call directly. The PNG is returned inline so the LLM can see the drawing without you having to open the file in another tool. Args: svg_path: path to an SVG file on disk. width: output pixel width (default 1200); height set by SVG aspect ratio. save_to: optional path to write the PNG. If empty, PNG bytes are delivered inline only.
| Name | Type | Req | Description |
|---|---|---|---|
| save_to | string | – | – |
| svg_path | string | yes | – |
| width | integer | – | – |
No output schema declared.
No examples provided.
render_view ~243
Render 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 automatically retries once as a coarse preview. azimuth/elevation apply after the preset. objects selects comma-separated registered names. clip_plane: x/y/z. save_to writes the result. mode: auto/2d/3d. label_objects and highlights add PNG labels; colors controls object/layer colours.
| Name | Type | Req | Description |
|---|---|---|---|
| azimuth | number | – | – |
| clip_at | – | – | – |
| clip_plane | string | – | – |
| colors | – | – | – |
| direction | string | – | – |
| elevation | number | – | – |
| format | string | – | – |
| highlights | – | – | – |
| label_objects | boolean | – | – |
| mode | string | – | – |
| objects | string | – | – |
| quality | string | – | – |
| save_to | string | – | – |
No output schema declared.
No examples provided.
repair_advice ~137
Return 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_error() text as error_text, the intended edit as goal, and any extra notes from locate_gate_defects()/compare(a='before', b='after', kind='shape') as context. The tool is read-only and does not mutate geometry.
| Name | Type | Req | Description |
|---|---|---|---|
| context | string | – | – |
| error_text | string | – | – |
| goal | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
repair_hints ~99
Given 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 failures, and more. Pass the full error string from execute(), last_error(), validate(), or export().
| Name | Type | Req | Description |
|---|---|---|---|
| error_text | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
reset ~20
Clear the current session back to empty state, including all snapshots.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
resolve ~252
Evaluate a selector expression against a named object and return a geometry descriptor. selector is a Python expression suffix applied to the object, e.g. '.faces().filter_by(Axis.Z).last()'. If label is given, the descriptor is stored in session.geometry_refs[label] and appears in session_state(). Returns JSON: {label, ref, object, selector, type, geom_type, area/length, center}. center is the entity's true centre — the arc centre for a circular/elliptical edge, the area centroid otherwise — not the parametric midpoint, which for a circle or cylinder lies ON the entity a radius from its axis. A planar face also carries normal; a curved face carries axis {origin, direction} and radius instead, because a curved face has no single normal (a sphere carries neither — its centre and radius say everything). A list-valued selector carries count, an aggregate center averaged over every match, and per-entity descriptors in entities (first 50, with entities_truncated when there are more). The ref field uses @cad[object#label] format.
| Name | Type | Req | Description |
|---|---|---|---|
| label | string | – | – |
| object_name | string | yes | – |
| selector | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
restore_snapshot ~80
Restore geometric state from a previously saved snapshot (current_shape and the show() registry). The Python variable namespace is NOT restored — execute() calls made after the snapshot are still in scope, but current_shape and all show() objects revert to what they were at snapshot time. Raises an error if the snapshot name does not exist.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
save_drawing_annotations ~247
DEPRECATED (#465) — moved to draftwright; off by default in 0.4.0, removed in 0.5.0. Calling it explains the replacement. Write a .dims.json sidecar file alongside an SVG with label metadata. build123d renders Text as filled glyph paths, not <text> SVG elements, so label strings are irrecoverable from a finished SVG. Call this tool after completing a drawing (annotate all dims/leaders with annotate()) and before or after exporting the SVG. The sidecar is read automatically by inspect_drawing(svg_path=...) to restore annotation content. Workflow: 1. Build your drawing with Dimension / Leader / annotate() 2. Export SVG: execute("exporter.write('drawing.svg')") 3. Save metadata: save_drawing_annotations("drawing.svg") 4. Inspect later: inspect_drawing(svg_path="drawing.svg") → includes full annotations dict from the sidecar Args: svg_path: path to the SVG file (sidecar written as <svg_path>.dims.json).
| Name | Type | Req | Description |
|---|---|---|---|
| svg_path | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
save_snapshot ~67
Save a named checkpoint of the current geometric state (current_shape and the show() object registry). The Python variable namespace is NOT saved — only geometry. Call this before risky experiments so you can restore known-good geometry without re-running all prior execute() calls.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
script ~85
Return a single Python script assembled from all successfully executed code blocks in this session. Prepends 'from build123d import *' if not already present. If save_to is given, writes the script to that path and returns {script_path, blocks}; otherwise returns {script, blocks}. Useful for exporting a reproducible script after an interactive session.
| Name | Type | Req | Description |
|---|---|---|---|
| save_to | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
session_state ~89
Return 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 this to orient after a reset, restore, or multi-step build to confirm what geometry and variables are active.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
suggest_view_layout ~559
DEPRECATED (#465) — moved to draftwright; off by default in 0.4.0, removed in 0.5.0. Calling it explains the replacement. Auto-calculate safe VIEW_X / VIEW_Y positions for a multi-view engineering drawing. Measures the named shape's bounding box and returns per-view page positions (VIEW_X, VIEW_Y), look_at values, and camera/up vectors for a standard third-angle layout: [plan ] [ ] [front] [ side ] [ iso ] [ title block (bottom-right) ] Returns JSON with: views: {name: {VIEW_X, VIEW_Y, half_w, half_h, look_at, camera, up}} free_space: {name: {above/below: {x, y, h}, left/right: {x, y, w}}} — the empty rectangle outside each view edge, bounded by neighbouring views, the title block, and the margins; budget dimension tiers (n × tier pitch must fit in h/w) before placing annotations warnings: list of layout problems (out-of-bounds, title-block overlap) suggestion: recommended page_w/page_h/scale if the layout does not fit object_name: name from show() — use "" to measure the current shape page_w/page_h: sheet size in mm (default A4 landscape 297×210) scale: drawing scale factor (default 1.0; use 2.0 for 2:1) views: subset of ["front","plan","side","iso"] to place title_block_w/h: reserved bottom-right area (default 150×30 mm) margin: page margin in mm (default 10) extents: [x, y, z] part sizes in mm — lays out from these numbers instead of a session object (use when the part isn't loaded, e.g. import failed) centroid: [x, y, z] look_at origin when using extents (default [0, 0, 0]) Accuracy: front/plan/side positions are exact for orthographic projection. Iso position is approximate (75% of 3-D diagonal as half-extent) — verify with render_view() and adjust manually if the iso overlaps a neighbour.
| Name | Type | Req | Description |
|---|---|---|---|
| centroid | – | – | – |
| extents | – | – | – |
| margin | number | – | – |
| object_name | string | – | – |
| page_h | number | – | – |
| page_w | number | – | – |
| scale | number | – | – |
| title_block_h | number | – | – |
| title_block_w | number | – | – |
| views | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
validate ~162
Check 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 non-zero volume. A FAIL means a STEP/STL export would be rejected outright — common causes are a leftover 2D sketch or open shell as the current shape, an un-fused compound, or a degenerate boolean result. Run this immediately before export() on any part you intend to submit or hand off. object_name: named object from show() (default: current shape).
| Name | Type | Req | Description |
|---|---|---|---|
| object_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
version ~101
Return 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 build is running — e.g. to check whether a feature or fix is present, or whether the client is talking to a stale install.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
view_axes ~238
DEPRECATED (#465) — moved to draftwright; off by default in 0.4.0, removed in 0.5.0. Calling it explains the replacement. Return the world→page axis mapping for a project_to_viewport call, computed analytically (no projection performed). Use this BEFORE rendering a projected view to confirm which world axis ends up on which page axis and with what sign — catches bottom-view/side-view axis swaps before they show up in the render. Returns JSON like {"world_X": ["page_X", -1.0], "world_Y": ["page_Y", 1.0], "world_Z": ["depth", 0.0]} — for a bottom-view origin (0,0,-100), world-X flips to negative page-X. Args: viewport_origin: camera position, same arg as project_to_viewport. viewport_up: up vector. Defaults to (0,1,0). look_at: target point. Defaults to origin.
| Name | Type | Req | Description |
|---|---|---|---|
| look_at | – | – | – |
| viewport_origin | array | yes | – |
| viewport_up | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
workflow_hints ~36
Return guidance on how to use these tools effectively. Call this at the start of a session or whenever unsure which tool to reach for.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
How do I install the build123d MCP server?
build123d MCP runs locally as a PyPI package, launched with uvx build123d-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · build123d-mcp
claude mcp add pzfreo-build123d-mcp -- uvx build123d-mcp
What is the build123d MCP server?
build123d MCP is listed in the public MCP registry as io.github.pzfreo/build123d-mcp. AI-driven 3D CAD via build123d: execute, render, measure, and export geometry interactively. This page covers its PyPI package (build123d-mcp).
Is the build123d MCP server safe to use?
build123d MCP scores 87 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the build123d MCP server expose?
build123d MCP exposes 48 tools: execute, execute_file, render_view, measure, validate, and 43 more. Their descriptions and schemas cost roughly 9,174 tokens of context every time the server is loaded.
Is the build123d MCP server still maintained?
build123d MCP is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the build123d MCP server under?
build123d MCP declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.
What did VerifyMCP test on the build123d MCP server?
VerifyMCP ran 16 checks on build123d MCP, covering Malware scan, Known CVEs, Install scripts, Dependency health and 12 more. Endpoint Security and Transport & Reachability do not apply to a PyPI package, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.