Skip to main content
Glama
hram

FreeCAD MCP

by hram

execute_code_async

Run long Python computations in FreeCAD without blocking the GUI thread, returning a job_id immediately. Use commit() to apply results safely on the GUI thread.

Instructions

Execute Python code in FreeCAD without waiting for completion.

Use this ONLY for long-running background computations that do NOT touch the
FreeCAD GUI or mutate the FreeCAD document tree directly.

This tool runs the submitted code in a background thread and returns
immediately. Because it does not run on FreeCAD's main GUI thread, the code
must NOT directly call FreeCADGui APIs, manipulate the active view or
selection, create or edit document objects, change object properties, call
doc.recompute(), or save documents. FreeCAD documents and the Coin3D
scenegraph are not thread-safe: writing to them from this thread races the
GUI thread and can wedge FreeCAD's event loop, after which the RPC server
stops responding entirely and FreeCAD must be restarted.

Every document or view write must instead be handed to the GUI thread through
the injected commit() helper:

    commit(fn, timeout=120) -> fn's return value

Scripts share a live namespace. Saved functions can use commit() in later
async calls; calling it from execute_code or a GUI callback raises immediately.
Coordinate concurrent scripts that intentionally modify the same variables.

commit() queues fn on the GUI thread, waits for it, and raises RuntimeError if
dispatch fails or times out. Example:

    fused = base.fuse(addition).removeSplitter()   # slow, safe in background

    def apply():                                   # runs on the GUI thread
        obj.Shape = fused
        doc.recompute()

    commit(apply)

For code that is not dominated by heavy geometry computation, use execute_code
instead. execute_code runs entirely on the FreeCAD GUI thread and is the safe
default for normal FreeCAD automation.

Use execute_code_async only when the heavy part is long-running OCCT geometry
(e.g. fuse/cut/loft on already-fetched shapes) or other CPU-bound computation
that would exceed execute_code's 90 s GUI-thread budget.

Typical usage pattern:
1. Fetch shapes into module-level variables first (via execute_code).
2. Run the heavy computation via execute_code_async.
3. Apply the result inside commit(), or store it in a module-level Python
   variable (not in the FreeCAD document) for a later execute_code call.

Performance note: boolean operations against shapes with many faces (e.g. a
ribbed lid) are expensive. Fuse the additions together first, then apply a
single boolean against the heavy shape, and avoid doc.recompute() unless the
dependency graph really needs it.

Args:
    code: Background-safe Python code to execute. Use commit(fn) for all
        document and view writes.

Returns:
    A message with the job_id of the started background execution.

Input Schema

NameRequiredDescriptionDefault
codeYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.9/5.0
Behavior5/5

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

With no annotations provided, the description carries the full behavioral burden and does so thoroughly: it explains the background-thread model, thread-safety hazards, the commit() bridge, shared namespace, RuntimeError behavior, and what happens if the GUI thread is wedged. This is exactly the context an agent needs before invoking a dangerous async tool.

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

Conciseness5/5

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

The description is long, but the length is justified by the tool's danger and complexity. It is front-loaded with the core behavior and constraints, then provides examples and a typical usage pattern without filler.

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

Completeness4/5

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

It thoroughly covers execution semantics, constraints, and the commit() workflow, including the returned job_id. However, it does not mention the sibling get_async_status for polling the started job, nor does it distinguish from execute_code_headless, leaving a small workflow gap for an otherwise complex async tool.

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

Parameters5/5

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

Although schema description coverage is 0% for the single code parameter, the description compensates fully by defining what code is allowed to do, what it must not do, and how document/view writes must use commit(). It also clarifies the return value as a job_id message.

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 states a specific verb and resource—execute Python code in FreeCAD—and immediately clarifies the async/background behavior. It explicitly distinguishes this from the safe default execute_code, so an agent can tell the two apart without inspecting schemas.

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

Usage Guidelines5/5

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

It gives explicit when-to-use and when-not-to-use rules: ONLY for long-running background computations that do not touch the GUI or mutate the document tree. It names execute_code as the alternative for normal automation and describes the narrow condition where execute_code_async is appropriate.

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