mcp-build123d

mcp
Guvenlik Denetimi
Basarisiz
Health Uyari
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Basarisiz
  • new Function() — Dynamic code execution via Function constructor in scripts/build-results-viewer.ts
  • network request — Outbound network request in scripts/release-guard.ts
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

MCP server for build123d — parametric CAD as code (Python/OCCT) driven by AI agents. Exact mass properties, STEP/STL/GLTF export

README.md

@casys/mcp-build123d

JSR
CI
License: MIT

Turn a build123d Python model into
measured CAD and verifiable export artifacts through MCP. Agent-facing
operations execute a parametric model, report OCCT geometry metrics, and export
STEP, STL, or GLB. Every export is promoted into a server-owned, immutable MCP
resource addressed by its SHA-256; agents receive the resource URI, MIME type,
size, and digest—not a host path.

agent writes build123d script
        │
   build123d_execute ──► volume, area, centroid, bbox, topology
        │
   build123d_export  ──► private delivery staging
        │
        └──────────────► casys://build123d/artifacts/<sha256>.step → FEA/CAD
                          casys://build123d/artifacts/<sha256>.stl  → printing
                          casys://build123d/artifacts/<sha256>.glb  → viewers
                                      │
                               resources/read (rehashes bytes)

exact STEP bytes or current-process casys:// STEP ──► build123d_observe_assembly_integrity ──► factual XCAF/OCCT assembly observation

build123d_export result in the MCP App viewer

The viewer renders a real build123d_export result from
docs/fixtures/bracket-r1.py, run in the published provider image. The model
and its status stay visible; geometry details and provenance open on demand. It
follows the host's light or dark theme and uses English or French labels.
deno task capture:docs regenerates the image from the committed fixture and
bundle.

At a glance:

  • Parametric solids, sketches, extrusions, revolves, sweeps, lofts, booleans,
    holes, fillets, chamfers, patterns, and compounds can use the normal build123d
    API installed with the selected Python interpreter.
  • STEP preserves the BREP, while STL and GLB are tessellated delivery formats.
  • Every export returns an immutable resource URI with exact MIME type, byte
    count, and SHA-256 digest. resources/read rehashes the issued in-memory
    bytes before returning them.
  • Mass is reported only from an explicit uniform density. No material or density
    is guessed.
  • build123d_observe_assembly_integrity accepts one bounded, digest-bound STEP
    artifact, either inline or as a current-process owned stepResource; it never
    executes caller code and returns factual import, unit, topology, occurrence,
    placement and pair observations.

Why CAD-as-code for agents

An agent doesn't click — it writes. With a GUI CAD's API, building geometry
means one HTTP call per feature against a stateful document. With build123d,
the script is the artifact: generated in one shot, versionable, diffable,
replayable with a pinned build123d package and a configured execution
environment, and carrying its own traceability (the SysML element or requirement
that motivated a dimension can live in the code, as a comment or a variable
name).

The metrics are not estimates. Volume, surface area, center of mass and bounding
box come analytically from the BREP kernel rather than from the STL or GLB
tessellation.

Quick start

Already have build123d installed

No Docker image or source checkout is needed if you have Deno 2.9.6 and a Python
3.10+ interpreter with build123d==0.11.1 and OCP.__version__ == "7.9.3.1"
(cadquery-ocp-novtk==7.9.3.1.1). Check the interpreter that the MCP server
will use:

python3 -I -c 'import sys, build123d, OCP; print(sys.executable, build123d.__version__, OCP.__version__)'

Put the printed Python path in your MCP client's stdio entry. Deno downloads the
published JSR package on first run:

{
  "mcpServers": {
    "build123d": {
      "command": "deno",
      "args": ["run", "-A", "jsr:@casys/[email protected]/server", "--stdio"],
      "env": {
        "BUILD123D_PYTHON_BIN": "/absolute/path/to/qualified/python",
        "BUILD123D_EXPORT_DIR": "/absolute/path/to/private/cad-exports"
      }
    }
  }
}

The server checks those versions at startup and refuses a different pair. The
Python probe uses -I, so packages available only through PYTHONPATH or the
user site are not sufficient. If your client cannot find deno, set command
to its absolute path.

Run a source checkout

Requirements are Deno 2.9.6 and Python 3.10+. The provider qualifies the exact
build123d==0.11.1 / cadquery-ocp-novtk==7.9.3.1.1 pair (reported by Python
as OCP.__version__ == "7.9.3.1"). Immutable export promotion uses POSIX
directory-descriptor safeguards, so this release supports that promotion on
macOS and Linux; an unsupported host refuses promotion rather than weakening
containment. A virtual environment keeps the OCCT dependency isolated from the
system Python:

git clone https://github.com/Casys-AI/mcp-build123d.git
cd mcp-build123d
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements/runtime.txt -c requirements/constraints.txt
BUILD123D_PYTHON_BIN="$PWD/.venv/bin/python" deno task serve

The server binds to loopback and exposes Streamable HTTP at
http://127.0.0.1:3014/mcp. Check the process separately with:

curl http://127.0.0.1:3014/health

The same source checkout also runs as native stdio, with the identical tool,
resource, viewer, and error contracts:

BUILD123D_PYTHON_BIN="$PWD/.venv/bin/python" deno task serve:stdio

For example, a checkout-backed stdio entry is:

{
  "mcpServers": {
    "build123d": {
      "command": "deno",
      "args": [
        "run",
        "-A",
        "/absolute/path/to/mcp-build123d/server.ts",
        "--stdio"
      ],
      "env": {
        "BUILD123D_PYTHON_BIN": "/absolute/path/to/mcp-build123d/.venv/bin/python",
        "BUILD123D_EXPORT_DIR": "/absolute/path/to/mcp-build123d/cad-exports"
      }
    }
  }
}

Run the published package

The published JSR package 0.6.4 can be started directly; Python and build123d
are still host dependencies:

BUILD123D_PYTHON_BIN="/absolute/path/to/qualified/python" \
  deno run -A jsr:@casys/[email protected]/server --port=3014

-A is intentional here: the public tools run arbitrary Python and write
exports. Use the source task or a container when you want to replace it with a
deployment-specific Deno permission set.

Point a Streamable HTTP-capable MCP client at the endpoint. The exact config
file location depends on the host; the connection entry is typically:

{
  "mcpServers": {
    "build123d": {
      "type": "streamable-http",
      "url": "http://127.0.0.1:3014/mcp"
    }
  }
}

HTTP binds to 127.0.0.1 by default; --hostname=0.0.0.0 is an explicit
network exposure. The 0.6.4 checkout supports native stdio and the
digest-bound resource contract described below.

Run the published provider image

The dedicated image includes the qualified Python/CAD pair and Deno runtime. Set
MCP_BUILD123D_IMAGE_DIGEST to the exact sha256: digest in the GitHub Release
notes for the version you select. Do not substitute the historical broader
engineering-toolchain image, which is a different server release.

mkdir -p "$PWD/cad-exports"
: "${MCP_BUILD123D_IMAGE_DIGEST:?Set this to the exact sha256 digest in the GitHub Release notes}"
docker run --rm \
  --publish 127.0.0.1:3014:3014 \
  --volume "$PWD/cad-exports:/exports" \
  "ghcr.io/casys-ai/mcp-build123d@${MCP_BUILD123D_IMAGE_DIGEST}"

Build a checkout locally

For a dedicated local image built from this checkout, use the committed
Dockerfile. It applies the same exact constraints and Deno base
image as CI and the published image:

docker build -t mcp-build123d:local .
mkdir -p cad-exports
docker run --rm \
  --publish 127.0.0.1:3014:3014 \
  --volume "$PWD/cad-exports:/exports" \
  mcp-build123d:local

The container is packaging, not a sandbox: the submitted Python still has the
container user's authority and can access anything mounted into it.

Security and trust boundary

build123d_execute and build123d_export run arbitrary Python on the
machine hosting this server. That is the point (CAD-as-code), not an accident.
Consequences:

  • Only expose this server to callers you trust with shell-equivalent access.
  • build123d_export's managed outputs are confined to BUILD123D_EXPORT_DIR:
    file names are reduced to a safe basename (directory components stripped,
    extension imposed by the format). Those mutable delivery paths are verified,
    then copied into the server process's immutable resource memory; they are
    never a resources/read surface. The submitted Python is not confined by that
    output-path rule and can do anything Python can.
  • Promotion reads delivery bytes through a short-lived isolated reader with a
    fixed five-second deadline. A special file or post-check staging swap fails
    closed; it cannot indefinitely block artifact issuance.
  • Inputs, bridge stdout/stderr, each promoted export, and retained
    current-process artifacts have fixed server-side byte budgets. Exceeding one
    returns a stable non-retryable resource-limit recovery rather than retaining
    unbounded bytes. The bridge kills its POSIX process group on timeout or output
    overflow; this covers normal descendants, not a hostile process that escapes
    the group or a security sandbox.
  • Loopback binding, safe export names, content-addressed resources, and timeouts
    are useful controls; none of them isolates the Python process. Put untrusted
    code behind a real sandbox with no secrets, network, or sensitive mounts.
  • HTTP starts with wildcard CORS and no authentication. CORS is not an
    access-control mechanism. Keep HTTP on loopback, or place an authenticated
    reverse proxy or equivalent authenticated deployment boundary in front of the
    server before any non-loopback exposure.
  • Submitted Python is not sandboxed. It has host or container user authority,
    including filesystem, process, and network access.

Report vulnerabilities privately as described in SECURITY.md.

The server itself needs no account or API key. A submitted Python script still
inherits the host or container's filesystem, process, and network access.

Evidence versus canonical product geometry

This standalone server returns real OCCT measurements and exact export-byte
digests. That proves what this invocation computed and wrote; it does not prove
that the script was reviewed, admitted, requirement-compliant, or canonical for
a product Digital Thread.

In casys-digital-thread, the canonical STEP route is the governed technical
source capture and compilation review followed by compile.seal-admission@3,
project_admitted_geometry_export, and design.write-geometry@1. The separate
design.execute-build123d@1 isolated execution and
design.seal-isolated-geometry@1 publication path is documentary, not the
canonical STEP authority. Keep those product-level authorities distinct from a
direct call to this standalone server.

Tools and result viewer

build123d_execute and build123d_export provide a compact geometry datasheet
in compatible MCP Apps hosts. Inspect the model with orbit, pan, zoom, fit,
reset, and wireframe controls. Open the details to inspect measured geometry,
export artifacts, and exact provenance. Text responses remain available to every
MCP client.

The same viewer presents recorded Digital Thread geometry and provisional
Project reviews, keeping their status visible and exact provenance accessible.
It uses MCP View components that a Compose host can also mount individually:
geometry, readings, status, or artifacts.

See the MCP App documentation for session contracts, resource
transport, component composition, local builds, and screenshot capture.

Script and geometry contract

The server does not maintain a second recipe language or a feature allowlist.
The selected Python environment determines which build123d APIs are available.
The stable server convention is smaller: the script must leave its final Part,
Solid, Compound, or BuildPart builder in a top-level variable named
result.

Build123d's default length convention is millimetres, which is why the public
metric fields are explicitly named *_mm, *_mm2, and *_mm3. A compound is
measured as one aggregate result, with total topology and one BREP centroid. The
server does not currently return an inertia tensor, per-solid mass properties,
material identity, tolerances, or manufacturing feasibility.

build123d_execute

Runs a build123d script, returns exact metrics. The script must assign its final
shape to a variable named result (a Part, Solid, Compound, or a BuildPart
builder):

from build123d import *

length, width, thickness = 60.0, 40.0, 5.0   # from a SysML PartUsage

with BuildPart() as bracket:
    Box(length, width, thickness)
    with Locations((15, 12, 0), (15, -12, 0)):
        Hole(3)

result = bracket

Structured response:

{
  "schemaVersion": "1.0",
  "kind": "execution",
  "metrics": {
    "volume_mm3": 11717.2567,
    "area_mm2": 5875.3982,
    "center_of_mass_mm": [-0.362, 0, 0],
    "bounding_box_mm": {
      "min": [-30, -20, -2.5],
      "max": [30, 20, 2.5],
      "size": [60, 40, 5]
    },
    "solids": 1,
    "faces": 8,
    "edges": 18,
    "density_kg_m3": 2700,
    "mass_kg": 0.0316366
  },
  "files": []
}

Values are rounded from build123d 0.11.1 / OCCT for this example; the installed
Python environment is part of reproducibility.

Mass requires an explicit density_kg_m3 (2700 for aluminium 6061, 7850 for
steel…). Without it, mass_kg is absent — it is never guessed from a material
name. One density applies uniformly to the complete result; heterogeneous
assemblies need to be evaluated per material outside this contract.

build123d_export

Every entry in files[] contains format and an artifact object with a
content-addressed uri, MIME type, byte size, and SHA-256. The tool writes into
private managed delivery staging, verifies the bridge-reported bytes, then
issues a process-local immutable resource copy. Downstream tools should use
resources/read on that exact URI and recompute the digest on their own copy
when retaining evidence.

Same execution, plus files. formats: step (exact BREP), stl (mesh), gltf
(binary .glb). BUILD123D_EXPORT_DIR is mutable staging (default
./cad-exports); it is not an agent-readable interface. Each call uses and
removes its own staging directory when it finishes. The response returns only
immutable artifact references alongside the same metrics.

Example tool input using the script above:

{
  "script": "from build123d import *\nwith BuildPart() as bracket:\n    Box(60, 40, 5)\nresult = bracket\n",
  "formats": ["step", "stl", "gltf"],
  "name": "bracket-r1",
  "density_kg_m3": 2700,
  "timeout_ms": 60000
}

build123d_observe_assembly_integrity

Observes one exact STEP Part 21 artifact without executing caller code. Supply
exactly one of two closed forms — never both, neither, or extra fields.

Inline digest-bound bytes, for STEP evidence this process does not already own:

{
  "step": {
    "mimeType": "model/step",
    "sha256": "lowercase-sha256-of-the-decoded-bytes",
    "bytes": 32536,
    "blob": "canonical-padded-base64-of-those-exact-bytes"
  }
}

bytes must be positive and at most 128 MiB.

A current-process owned STEP resource, using the issued artifact identity fields
uri, mimeType, sha256, and bytes (not schemaVersion or format):

{
  "stepResource": {
    "uri": "casys://build123d/artifacts/<lowercase-sha256>.step",
    "mimeType": "model/step",
    "sha256": "<lowercase-sha256>",
    "bytes": 32536
  }
}

The URI digest must match sha256 and the registered object. Only an immutable
model/step artifact issued by this process's artifact store is accepted;
generic MCP resources, host paths, and leftover disk objects are not. After
restart the store is empty, so a previous URI is unknown even if a forged file
still exists. Owned artifacts stay at the store's 32 MiB per-object bound (the
inline form remains 128 MiB). The bridge rehashes verified bytes and checks the
Part 21 envelope before staging them privately for a fixed OCCT/XCAF harness.
There are no caller-selected paths, Python, tolerances, transforms or timeouts.

The versioned build123d-assembly-integrity-observation/1.0 result carries the
exact input identity, fixed method, and a closed producer block:

{
  "producer": {
    "service": "mcp-build123d",
    "packageVersion": "0.6.4",
    "tool": "build123d_observe_assembly_integrity",
    "engine": { "name": "cadquery-ocp", "version": "7.9.3.1" }
  }
}

Every fact is either observed, unresolved, or unavailable. Direct
occurrences are printable-ASCII labels sorted bytewise (maximum 32). An observed
placement is a row-major rigid 4×4 XCAF Location matrix in the STEP file's
observed millimetres; it is not an expected or requested pose. The tool emits
every canonical direct-label pair (maximum 496) with the fixed 1e-6 mm
tolerance, minimum distance, intersection volume, and contact fact. These are
kernel facts, not a pass/fail decision. The contract has no project,
requirement, fitness, safety, motion, strength, or verdict fields.

The producer.engine block identifies the installed cadquery-ocp binding
whose OCP.__version__ is read by the fixed harness. It does not claim a
Standard OCCT API build version, an image digest, or a sandbox/network policy
attestation; the fixed method still describes the OCCT/XCAF observation.

Content and digest semantics

  • Each call runs the script once. build123d_export derives all requested
    formats and the reported metrics from that one in-memory result.
  • After that successful bridge result, the current server process holds a
    direct-execution receipt alongside an immutable in-memory artifact copy. The
    receipt binds source, request, metrics and output-set digests with literal
    not-admitted status; it never stores submitted source text or crosses
    structuredContent. Resources are deliberately not restored after restart:
    any object or receipt prewritten on disk is ignored. This is not a Digital
    Thread operation or admission ledger, and it does not make an artifact
    canonical product geometry.
  • An export delivery path is mutable and private. Each call stages under a
    separate directory, then removes that directory on completion; reusing a
    name in another call does not share a delivery path. The returned
    artifact.uri is digest-bound and names the immutable current-process copy.
    resources/read rehashes that copy before it returns any bytes. Promotion
    uses a fixed five-second isolated read deadline, so a special file or staging
    swap fails closed instead of stalling the artifact queue. After a server
    restart, run a new export before reading an artifact URI again.
  • build123d_export passes the UTC sentinel 1970-01-01T00:00:00Z to
    build123d's native STEP timestamp parameter. That sentinel is a
    reproducibility marker, not the execution or export time. This provider starts
    only with the qualified build123d==0.11.1 and
    cadquery-ocp-novtk==7.9.3.1.1 pair. Its observed OCP.__version__ is
    7.9.3.1; other provider releases may change bytes.
  • Digest equality proves byte equality, not geometric equivalence. Export bytes
    can change across build123d, OCCT, or exporter versions even when a shape is
    visually equivalent.
  • STEP, STL, and GLB all use the same general artifact-resource contract.
    Resource metadata contains the MIME type, size, SHA-256, format, and immutable
    flag. No caller-controlled filesystem path is accepted by the resource reader.

Environment Variables

Variable Default Description
BUILD123D_PYTHON_BIN python3 Python interpreter that has build123d
BUILD123D_EXPORT_DIR ./cad-exports Private mutable delivery staging for the Python bridge

Architecture

mod.ts                  # Public API
server.ts               # HTTP bootstrap or native stdio bootstrap
src/
  api/
    harness.py          # Python side: exec script, compute metrics, export
    python-bridge.ts    # Deno side: subprocess, JSON over stdin/stdout
    assembly-integrity-harness.py # fixed OCCT/XCAF factual STEP observer
    assembly-integrity-bridge.ts  # digest-bound staging and receipt parser
  artifacts.ts          # process-local digest-bound export resources and handlers
  tool-errors.ts        # stable structured tool-error envelope
  tools/
    execute.ts          # execute and immutable artifact export
    assembly-integrity.ts # standalone factual assembly observation
  ui/results-viewer/    # small CAD components and resource-backed GLB viewer
  client.ts             # CadToolsClient
tests/                  # contract, wire, viewer and real build123d tests

The bridge is a subprocess speaking JSON — the same architectural choice as
@casys/constraint-solver's z3 backend: identical behaviour under Deno and
Node, no WASM, and the heavyweight dependency (Python + OCCT) stays on the
selected host or in its container.

Composing the chain

In a standalone workflow, build123d_execute's mass feeds
@casys/constraint-solver (via @casys/mcp-syson's
syson_constraint_evaluate) to check a computed mass against a SysML mass
budget — with units. A STEP artifact read from build123d_export is the entry
point for FEA meshing. Each link is a separate MCP server; the agent composes
them.

Development

deno task test     # full CAD integration cases need Python 3.10+ with build123d
deno check mod.ts server.ts

License

MIT

Yorumlar (0)

Sonuc bulunamadi