Skip to main content
Glama

create_object

Add 3D objects like boxes, cylinders, circles, FEM elements, or mechanical parts to FreeCAD documents with customizable properties.

Instructions

Create a new object in FreeCAD. Object type is starts with "Part::" or "Draft::" or "PartDesign::" or "Fem::".

Args:
    doc_name: The name of the document to create the object in.
    obj_type: The type of the object to create (e.g. 'Part::Box', 'Part::Cylinder', 'Draft::Circle', 'PartDesign::Body', etc.).
    obj_name: The name of the object to create.
    obj_properties: The properties of the object to create.

Returns:
    A message indicating the success or failure of the object creation and a screenshot of the object.

Examples:
    If you want to create a cylinder with a height of 30 and a radius of 10, you can use the following data.
    ```json
    {
        "doc_name": "MyCylinder",
        "obj_name": "Cylinder",
        "obj_type": "Part::Cylinder",
        "obj_properties": {
            "Height": 30,
            "Radius": 10,
            "Placement": {
                "Base": {
                    "x": 10,
                    "y": 10,
                    "z": 0
                },
                "Rotation": {
                    "Axis": {
                        "x": 0,
                        "y": 0,
                        "z": 1
                    },
                    "Angle": 45
                }
            },
            "ViewObject": {
                "ShapeColor": [0.5, 0.5, 0.5, 1.0]
            }
        }
    }
    ```

    If you want to create a circle with a radius of 10, you can use the following data.
    ```json
    {
        "doc_name": "MyCircle",
        "obj_name": "Circle",
        "obj_type": "Draft::Circle",
    }
    ```

    If you want to create a FEM analysis, you can use the following data.
    ```json
    {
        "doc_name": "MyFEMAnalysis",
        "obj_name": "FemAnalysis",
        "obj_type": "Fem::AnalysisPython",
    }
    ```

    If you want to create a FEM constraint, you can use the following data.
    ```json
    {
        "doc_name": "MyFEMConstraint",
        "obj_name": "FemConstraint",
        "obj_type": "Fem::ConstraintFixed",
        "analysis_name": "MyFEMAnalysis",
        "obj_properties": {
            "References": [
                {
                    "object_name": "MyObject",
                    "face": "Face1"
                }
            ]
        }
    }
    ```

    If you want to create a FEM mechanical material, you can use the following data.
    ```json
    {
        "doc_name": "MyFEMAnalysis",
        "obj_name": "FemMechanicalMaterial",
        "obj_type": "Fem::MaterialCommon",
        "analysis_name": "MyFEMAnalysis",
        "obj_properties": {
            "Material": {
                "Name": "MyMaterial",
                "Density": "7900 kg/m^3",
                "YoungModulus": "210 GPa",
                "PoissonRatio": 0.3
            }
        }
    }
    ```

    If you want to create a FEM mesh, you can use the following data.
    The `Part` property is required.
    ```json
    {
        "doc_name": "MyFEMMesh",
        "obj_name": "FemMesh",
        "obj_type": "Fem::FemMeshGmsh",
        "analysis_name": "MyFEMAnalysis",
        "obj_properties": {
            "Part": "MyObject",
            "ElementSizeMax": 10,
            "ElementSizeMin": 0.1,
            "MeshAlgorithm": 2
        }
    }
    ```

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
doc_nameYes
obj_typeYes
obj_nameYes
analysis_nameNo
obj_propertiesNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • MCP tool handler for 'create_object'. Registers the tool and handles the MCP call by proxying to FreeCADConnection.create_object RPC method, adding screenshot feedback.
    @mcp.tool()
    def create_object(
        ctx: Context,
        doc_name: str,
        obj_type: str,
        obj_name: str,
        analysis_name: str | None = None,
        obj_properties: dict[str, Any] = None,
    ) -> list[TextContent | ImageContent]:
        """Create a new object in FreeCAD.
        Object type is starts with "Part::" or "Draft::" or "PartDesign::" or "Fem::".
    
        Args:
            doc_name: The name of the document to create the object in.
            obj_type: The type of the object to create (e.g. 'Part::Box', 'Part::Cylinder', 'Draft::Circle', 'PartDesign::Body', etc.).
            obj_name: The name of the object to create.
            obj_properties: The properties of the object to create.
    
        Returns:
            A message indicating the success or failure of the object creation and a screenshot of the object.
    
        Examples:
            If you want to create a cylinder with a height of 30 and a radius of 10, you can use the following data.
            ```json
            {
                "doc_name": "MyCylinder",
                "obj_name": "Cylinder",
                "obj_type": "Part::Cylinder",
                "obj_properties": {
                    "Height": 30,
                    "Radius": 10,
                    "Placement": {
                        "Base": {
                            "x": 10,
                            "y": 10,
                            "z": 0
                        },
                        "Rotation": {
                            "Axis": {
                                "x": 0,
                                "y": 0,
                                "z": 1
                            },
                            "Angle": 45
                        }
                    },
                    "ViewObject": {
                        "ShapeColor": [0.5, 0.5, 0.5, 1.0]
                    }
                }
            }
            ```
    
            If you want to create a circle with a radius of 10, you can use the following data.
            ```json
            {
                "doc_name": "MyCircle",
                "obj_name": "Circle",
                "obj_type": "Draft::Circle",
            }
            ```
    
            If you want to create a FEM analysis, you can use the following data.
            ```json
            {
                "doc_name": "MyFEMAnalysis",
                "obj_name": "FemAnalysis",
                "obj_type": "Fem::AnalysisPython",
            }
            ```
    
            If you want to create a FEM constraint, you can use the following data.
            ```json
            {
                "doc_name": "MyFEMConstraint",
                "obj_name": "FemConstraint",
                "obj_type": "Fem::ConstraintFixed",
                "analysis_name": "MyFEMAnalysis",
                "obj_properties": {
                    "References": [
                        {
                            "object_name": "MyObject",
                            "face": "Face1"
                        }
                    ]
                }
            }
            ```
    
            If you want to create a FEM mechanical material, you can use the following data.
            ```json
            {
                "doc_name": "MyFEMAnalysis",
                "obj_name": "FemMechanicalMaterial",
                "obj_type": "Fem::MaterialCommon",
                "analysis_name": "MyFEMAnalysis",
                "obj_properties": {
                    "Material": {
                        "Name": "MyMaterial",
                        "Density": "7900 kg/m^3",
                        "YoungModulus": "210 GPa",
                        "PoissonRatio": 0.3
                    }
                }
            }
            ```
    
            If you want to create a FEM mesh, you can use the following data.
            The `Part` property is required.
            ```json
            {
                "doc_name": "MyFEMMesh",
                "obj_name": "FemMesh",
                "obj_type": "Fem::FemMeshGmsh",
                "analysis_name": "MyFEMAnalysis",
                "obj_properties": {
                    "Part": "MyObject",
                    "ElementSizeMax": 10,
                    "ElementSizeMin": 0.1,
                    "MeshAlgorithm": 2
                }
            }
            ```
        """
        freecad = get_freecad_connection()
        try:
            obj_data = {"Name": obj_name, "Type": obj_type, "Properties": obj_properties or {}, "Analysis": analysis_name}
            res = freecad.create_object(doc_name, obj_data)
            screenshot = freecad.get_active_screenshot()
            
            if res["success"]:
                response = [
                    TextContent(type="text", text=f"Object '{res['object_name']}' created successfully"),
                ]
                return add_screenshot_if_available(response, screenshot)
            else:
                response = [
                    TextContent(type="text", text=f"Failed to create object: {res['error']}"),
                ]
                return add_screenshot_if_available(response, screenshot)
        except Exception as e:
            logger.error(f"Failed to create object: {str(e)}")
            return [
                TextContent(type="text", text=f"Failed to create object: {str(e)}")
            ]
  • Core FreeCAD GUI-thread-safe handler for object creation. Handles special cases for FEM meshes and objects, uses doc.addObject for primitives, sets properties, and recomputes the document.
    def _create_object_gui(self, doc_name, obj: Object):
        doc = FreeCAD.getDocument(doc_name)
        if doc:
            try:
                if obj.type == "Fem::FemMeshGmsh" and obj.analysis:
                    from femmesh.gmshtools import GmshTools
                    res = getattr(doc, obj.analysis).addObject(ObjectsFem.makeMeshGmsh(doc, obj.name))[0]
                    if "Part" in obj.properties:
                        target_obj = doc.getObject(obj.properties["Part"])
                        if target_obj:
                            res.Part = target_obj
                        else:
                            raise ValueError(f"Referenced object '{obj.properties['Part']}' not found.")
                        del obj.properties["Part"]
                    else:
                        raise ValueError("'Part' property not found in properties.")
    
                    for param, value in obj.properties.items():
                        if hasattr(res, param):
                            setattr(res, param, value)
                    doc.recompute()
    
                    gmsh_tools = GmshTools(res)
                    gmsh_tools.create_mesh()
                    FreeCAD.Console.PrintMessage(
                        f"FEM Mesh '{res.Name}' generated successfully in '{doc_name}'.\n"
                    )
                elif obj.type.startswith("Fem::"):
                    fem_make_methods = {
                        "MaterialCommon": ObjectsFem.makeMaterialSolid,
                        "AnalysisPython": ObjectsFem.makeAnalysis,
                    }
                    obj_type_short = obj.type.split("::")[1]
                    method_name = "make" + obj_type_short
                    make_method = fem_make_methods.get(obj_type_short, getattr(ObjectsFem, method_name, None))
    
                    if callable(make_method):
                        res = make_method(doc, obj.name)
                        set_object_property(doc, res, obj.properties)
                        FreeCAD.Console.PrintMessage(
                            f"FEM object '{res.Name}' created with '{method_name}'.\n"
                        )
                    else:
                        raise ValueError(f"No creation method '{method_name}' found in ObjectsFem.")
                    if obj.type != "Fem::AnalysisPython" and obj.analysis:
                        getattr(doc, obj.analysis).addObject(res)
                else:
                    res = doc.addObject(obj.type, obj.name)
                    set_object_property(doc, res, obj.properties)
                    FreeCAD.Console.PrintMessage(
                        f"{res.TypeId} '{res.Name}' added to '{doc_name}' via RPC.\n"
                    )
    
                doc.recompute()
                return True
            except Exception as e:
                return str(e)
        else:
            FreeCAD.Console.PrintError(f"Document '{doc_name}' not found.\n")
            return f"Document '{doc_name}' not found.\n"
  • RPC server entry point for create_object. Parses obj_data into Object dataclass and queues the GUI-thread-safe _create_object_gui task.
    def create_object(self, doc_name, obj_data: dict[str, Any]):
        obj = Object(
            name=obj_data.get("Name", "New_Object"),
            type=obj_data["Type"],
            analysis=obj_data.get("Analysis", None),
            properties=obj_data.get("Properties", {}),
        )
        rpc_request_queue.put(lambda: self._create_object_gui(doc_name, obj))
        res = rpc_response_queue.get()
        if res is True:
            return {"success": True, "object_name": obj.name}
        else:
            return {"success": False, "error": res}
  • Helper function to set object properties, handling special FreeCAD types like Placement, Vector, References, ViewObject properties.
    def set_object_property(
        doc: FreeCAD.Document, obj: FreeCAD.DocumentObject, properties: dict[str, Any]
    ):
        for prop, val in properties.items():
            try:
                if prop in obj.PropertiesList:
                    if prop == "Placement" and isinstance(val, dict):
                        if "Base" in val:
                            pos = val["Base"]
                        elif "Position" in val:
                            pos = val["Position"]
                        else:
                            pos = {}
                        rot = val.get("Rotation", {})
                        placement = FreeCAD.Placement(
                            FreeCAD.Vector(
                                pos.get("x", 0),
                                pos.get("y", 0),
                                pos.get("z", 0),
                            ),
                            FreeCAD.Rotation(
                                FreeCAD.Vector(
                                    rot.get("Axis", {}).get("x", 0),
                                    rot.get("Axis", {}).get("y", 0),
                                    rot.get("Axis", {}).get("z", 1),
                                ),
                                rot.get("Angle", 0),
                            ),
                        )
                        setattr(obj, prop, placement)
    
                    elif isinstance(getattr(obj, prop), FreeCAD.Vector) and isinstance(
                        val, dict
                    ):
                        vector = FreeCAD.Vector(
                            val.get("x", 0), val.get("y", 0), val.get("z", 0)
                        )
                        setattr(obj, prop, vector)
    
                    elif prop in ["Base", "Tool", "Source", "Profile"] and isinstance(
                        val, str
                    ):
                        ref_obj = doc.getObject(val)
                        if ref_obj:
                            setattr(obj, prop, ref_obj)
                        else:
                            raise ValueError(f"Referenced object '{val}' not found.")
    
                    elif prop == "References" and isinstance(val, list):
                        refs = []
                        for ref_name, face in val:
                            ref_obj = doc.getObject(ref_name)
                            if ref_obj:
                                refs.append((ref_obj, face))
                            else:
                                raise ValueError(f"Referenced object '{ref_name}' not found.")
                        setattr(obj, prop, refs)
    
                    else:
                        setattr(obj, prop, val)
                # ShapeColor is a property of the ViewObject
                elif prop == "ShapeColor" and isinstance(val, (list, tuple)):
                    setattr(obj.ViewObject, prop, (float(val[0]), float(val[1]), float(val[2]), float(val[3])))
    
                elif prop == "ViewObject" and isinstance(val, dict):
                    for k, v in val.items():
                        if k == "ShapeColor":
                            setattr(obj.ViewObject, k, (float(v[0]), float(v[1]), float(v[2]), float(v[3])))
                        else:
                            setattr(obj.ViewObject, k, v)
    
                else:
                    setattr(obj, prop, val)
    
            except Exception as e:
                FreeCAD.Console.PrintError(f"Property '{prop}' assignment error: {e}\n")
  • Proxy method in FreeCADConnection class that forwards create_object calls to the XML-RPC server.
    def create_object(self, doc_name: str, obj_data: dict[str, Any]) -> dict[str, Any]:
        return self.server.create_object(doc_name, obj_data)
Behavior4/5

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

With no annotations provided, the description carries full burden. It clearly indicates this is a creation/mutation operation ('Create a new object'), describes the return format ('message indicating success or failure and a screenshot'), and provides extensive examples showing different object types and their properties. However, it doesn't mention potential side effects, permissions needed, or error handling details.

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

Conciseness2/5

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

The description is excessively long with 7 detailed examples that could be condensed. While the initial purpose statement is clear, the examples section dominates the description and includes redundant formatting. The structure could be improved by summarizing example patterns rather than listing numerous full JSON examples.

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?

Given the complexity (5 parameters, nested objects, no annotations) and the presence of an output schema, the description provides substantial context. It explains parameter usage thoroughly, shows return format, and covers multiple object categories. However, the excessive examples make it less efficient, and it could benefit from more behavioral context about mutations and dependencies.

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?

With 0% schema description coverage, the description fully compensates by explaining all 5 parameters through the 'Args' section and extensive examples. It clarifies 'doc_name' as document name, 'obj_type' with specific prefixes and examples, 'obj_name' as object name, 'analysis_name' context for FEM objects, and 'obj_properties' with detailed property structures across multiple object types.

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 states the verb 'Create' and the resource 'new object in FreeCAD', with specific examples of object types starting with 'Part::', 'Draft::', 'PartDesign::', or 'Fem::'. It distinguishes from siblings like 'create_document' (which creates documents rather than objects) and 'edit_object' (which modifies existing objects).

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

Usage Guidelines3/5

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

The description implies usage for creating various FreeCAD objects with examples, but doesn't explicitly state when to use this versus alternatives like 'create_document' for documents or 'edit_object' for modifications. It provides context through examples but lacks explicit guidance on tool selection criteria.

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/heok-yongssun/freecad-mcp'

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