Skip to main content
Glama
pzfreo

build123d-mcp

repair_hints

Analyze error messages from build123d and return specific repair hints for common issues like wrong Location syntax, missing .part, and degenerate booleans.

Instructions

Given an error message from execute(), return targeted fix suggestions for common build123d mistakes: wrong Location syntax, missing .part, CadQuery idioms, blocked imports, degenerate boolean results, fillet edge selection, and more. Pass the full error string from execute() or last_error().

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
error_textYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The core handler function. Takes an error_text string, matches it against patterns in _HINTS, and returns a JSON string of fix suggestions.
    def repair_hints(error_text: str) -> str:
        matches = []
        for patterns, hint in _HINTS:
            if any(re.search(p, error_text) for p in patterns):
                matches.append(hint)
    
        if not matches:
            matches.append(
                "No specific hint matched. Call last_error() for the exact line and "
                "exception, then check: (1) shapes are non-None before boolean ops, "
                "(2) `from build123d import *` is in scope, "
                "(3) Location uses a tuple argument."
            )
    
        return json.dumps({"hints": matches}, indent=2)
  • MCP tool registration using the @mcp.tool() decorator. Delegates to the handler function in src/build123d_mcp/tools/repair_hints.py.
    @mcp.tool()
    def repair_hints(error_text: str) -> str:
        """Given an error message from execute(), return targeted fix suggestions for common build123d mistakes: wrong Location syntax, missing .part, CadQuery idioms, blocked imports, degenerate boolean results, fillet edge selection, and more. Pass the full error string from execute() or last_error()."""
        from build123d_mcp.tools.repair_hints import repair_hints as _repair_hints
        return _repair_hints(error_text)
  • A list of (pattern_list, hint_text) tuples defining all the error patterns and their associated fix hints. Used by the handler to match error messages.
    _HINTS: list[tuple[list[str], str]] = [
        (
            [r"NoneType.*has no attribute", r"AttributeError.*None"],
            "Shape is None. If you used BuildPart context manager, access the result with "
            "`.part` (e.g. `result = bp.part`). In algebra mode, assign directly: "
            "`result = Box(10,10,10) - Cylinder(3,12)`.",
        ),
        (
            [r"None context requested", r"No context.*requested"],
            "build123d algebra mode requires no context manager — create shapes directly "
            "and assign to `result` or call `show()`. Remove `with BuildPart()` wrappers "
            "if you're using operator-based construction.",
        ),
        (
            [r"cq\.", r"Workplane", r"CadQuery"],
            "CadQuery syntax detected. build123d uses a different API: "
            "`Box(w,h,d)` not `cq.Workplane().box(w,h,d)`. "
            "Replace `.translate()` with `.move(Location((x,y,z)))`, "
            "`.rotate()` with `.rotate(Axis.Z, angle)`, "
            "and `.union()`/`.cut()` with `+`/`-` operators.",
        ),
        (
            [r"TypeError.*Location", r"Location.*argument"],
            "Location syntax: pass a tuple — `Location((x, y, z))` not `Location(x, y, z)`. "
            "For combined translation + rotation: `Location((x,y,z), (rx,ry,rz))`.",
        ),
        (
            [r"[Ff]illet.*edge", r"[Ee]dge.*fillet", r"ValueError.*edges.*fillet"],
            "Fillet edge selection: edges must be non-tangent and the radius must be smaller "
            "than the adjacent wall thickness. Select edges with "
            "`shape.edges().filter_by(Axis.Z)` or index them with `shape.edges()[0]`. "
            "Avoid `shape.edges()` (all edges) on complex shapes — pick specific ones.",
        ),
        (
            [r"NameError.*\b(Box|Cylinder|Sphere|Cone|Torus|Extrude|BuildPart|"
             r"BuildSketch|Align|Axis|Location|Plane|Vector|Color|Compound|Shell|"
             r"Fillet|Chamfer|extrude|loft|sweep)\b"],
            "build123d name not in scope. Add `from build123d import *` at the top of "
            "the execute() call. If it was imported in a previous call, re-run that import "
            "or include it in this snippet.",
        ),
        (
            [r"ImportError", r"SecurityError", r"not allowed.*import", r"import.*not allowed"],
            "Import blocked. Allowed modules: build123d, bd_warehouse, math, numpy, decimal, "
            "fractions, statistics, numbers, random, collections, itertools, functools, copy, "
            "operator, struct, typing, abc, dataclasses, enum, re, string, textwrap, pprint, "
            "json, base64, hashlib, io, warnings, contextlib. "
            "Remove os, sys, pathlib, subprocess, socket, and network imports. "
            "Start the server with --allow-all-imports to disable this check entirely.",
        ),
        (
            [r"Constraint failed", r"AssertionError"],
            "Constraint failed — a dimension is physically impossible. Common causes: "
            "fillet radius larger than the adjacent face, hole diameter larger than "
            "the wall, or zero/negative dimensions. Check all numeric parameters.",
        ),
        (
            [r"empty.*[Ss]hape", r"[Ss]hape.*empty", r"degenerate", r"no.*solid"],
            "Degenerate or empty shape after boolean operation. The cutter probably doesn't "
            "overlap the base, or the result has zero volume. Verify positions with "
            "measure(bounding_box) on both shapes before the boolean.",
        ),
        (
            [r"ExecutionTimeout"],
            "Execution timed out. Likely causes: very high-resolution mesh "
            "(lower angular_deflection), deeply nested boolean operations, or an "
            "infinite loop. Simplify the geometry or break it into smaller steps.",
        ),
        (
            [r"\.part\b"],
            "If you see an error referencing `.part`: in BuildPart context manager usage "
            "you must explicitly read `context.part` to get the Shape. "
            "In algebra mode (recommended) you don't need `.part` at all.",
        ),
    ]
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description bears full responsibility for behavioral disclosure. It only states that it returns 'targeted fix suggestions' but does not mention potential side effects, limitations (e.g., only works for known patterns), performance characteristics, or error handling. This is insufficient for a tool that might be part of a workflow.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that efficiently conveys purpose and input requirements. The enumeration of mistake types adds value but makes it slightly long. It front-loads the core action and then provides examples, which is effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that an output schema exists, the description does not need to detail return values. It covers the input source and scope of suggestions. However, it lacks details about edge cases (e.g., empty error) or whether the tool requires network access. It is adequate but not comprehensive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has low coverage (0% description for error_text), but the description adds essential semantics: it specifies that the parameter should be the full error string from execute() or last_error(). This clarifies the expected format and source, going beyond the schema title.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool's function: given an error message from execute(), it returns targeted fix suggestions for common build123d mistakes. It lists specific categories of mistakes (e.g., wrong Location syntax, missing .part), differentiating it from sibling tools like last_error which only returns the error string.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies exactly when to use the tool: 'Pass the full error string from execute() or last_error().' This gives clear context. However, it does not explicitly state when not to use it or mention alternatives, but the use case is well-defined.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pzfreo/build123d-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server