Skip to content

solidworks_mcp.tools.modeling

solidworks_mcp.tools.modeling

Modeling tools for SolidWorks MCP Server.

Provides tools for creating and manipulating SolidWorks models, including parts, assemblies, drawings, and features like extrusions, revolves, etc.

Classes

AdapterResult dataclass

AdapterResult(status: AdapterResultStatus, data: T | None = None, error: str | None = None, execution_time: float | None = None, metadata: dict[str, Any] | None = None)

Result wrapper for adapter operations.

Attributes:

Name Type Description
data T | None

The data value.

error str | None

The error value.

execution_time float | None

The execution time value.

metadata dict[str, Any] | None

The metadata value.

status AdapterResultStatus

The status value.

Attributes
is_error property
is_error: bool

Check if operation had an error.

Returns:

Name Type Description
bool bool

True if error, otherwise False.

is_success property
is_success: bool

Check if operation was successful.

Returns:

Name Type Description
bool bool

True if success, otherwise False.

AddChamferInput

Bases: CompatInput

Input schema for adding a chamfer feature.

Attributes:

Name Type Description
distance float

Chamfer distance in millimeters.

edge_names list[str]

Edge names to chamfer.

angle float

Chamfer angle in degrees.

flip bool

Measure the distance along the other face.

AddFilletInput

Bases: CompatInput

Input schema for adding a fillet feature.

Attributes:

Name Type Description
edge_names list[str]

Edge names to fillet.

radius float

Fillet radius in millimeters.

AddMateInput

Bases: CompatInput

Input schema for mating two assembly components.

Attributes:

Name Type Description
component_a str

First component instance name.

component_b str

Second component instance name.

entity_a str

Named feature on the first component.

entity_b str

Named feature on the second component.

mate_type str

Mate type.

alignment str

Mate alignment.

distance float

Distance in millimetres for a distance mate.

angle float

Angle in degrees for an angle mate.

CloseModelInput

Bases: BaseModel

Input schema for closing a model.

Attributes:

Name Type Description
save bool

The save value.

CompatInput

Bases: BaseModel

Base schema allowing legacy/extra fields used by existing tests.

Attributes:

Name Type Description
model_config Any

The model config value.

CreateAssemblyInput

Bases: CompatInput

Input schema for creating a new assembly.

Attributes:

Name Type Description
name str

The name value.

template str | None

The template value.

CreateAxisInput

Bases: CompatInput

Input schema for creating a reference axis.

Attributes:

Name Type Description
reference str

Principal axis direction.

CreateCutExtrudeInput

Bases: CompatInput

Input schema for creating a cut-extrude feature.

Attributes:

Name Type Description
depth float

Cut depth in millimeters.

draft_angle float

Draft angle in degrees.

end_condition str

End condition type.

reverse_direction bool

Reverse cut direction.

both_directions bool

With "ThroughAll", cut both ways.

sketch_name str | None

Sketch to cut from.

CreateDrawingInput

Bases: CompatInput

Input schema for creating a new drawing.

Attributes:

Name Type Description
name str

The name value.

template str | None

The template value.

CreateExtrusionInput

Bases: CompatInput

Input schema for creating an extrusion feature.

Attributes:

Name Type Description
both_directions bool

The both directions value.

depth float

The depth value.

draft_angle float

The draft angle value.

end_condition str

The end condition value.

merge_result bool

The merge result value.

reverse bool | None

The reverse value.

reverse_direction bool

The reverse direction value.

sketch_name str | None

The sketch to extrude; None for the last closed.

thin_feature bool

The thin feature value.

thin_thickness float | None

The thin thickness value.

thin_side str

The side a thin wall grows on.

Methods:
model_post_init
model_post_init(__context: Any) -> None

Provide model post init support for the create extrusion input.

Parameters:

Name Type Description Default
__context Any

The context value.

required

Returns:

Name Type Description
None None

None.

Raises:

Type Description
ValueError

A non-positive depth, or a thin wall without thickness.

Source code in src/solidworks_mcp/tools/modeling.py
def model_post_init(self, __context: Any) -> None:
    """Provide model post init support for the create extrusion input.

    Args:
        __context (Any): The context value.

    Returns:
        None: None.

    Raises:
        ValueError: A non-positive depth, or a thin wall without thickness.
    """
    if self.depth <= 0:
        raise ValueError("depth must be positive")
    if self.reverse is not None:
        self.reverse_direction = self.reverse
    if self.thin_feature and not (self.thin_thickness and self.thin_thickness > 0):
        raise ValueError("thin_feature needs a positive thin_thickness (mm)")

CreateLoftInput

Bases: BaseModel

Input schema for creating a loft feature.

Attributes:

Name Type Description
end_tangent str | None

The end tangent value.

guide_curves list[str] | None

The guide curves value.

merge_result bool

The merge result value.

profiles list[str]

The profiles value.

start_tangent str | None

The start tangent value.

CreatePartInput

Bases: CompatInput

Input schema for creating a new SolidWorks part.

Attributes:

Name Type Description
material str | None

The material value.

name str

The name value.

template str | None

The template value.

units str | None

The units value.

Methods:
model_post_init
model_post_init(__context: Any) -> None

Provide model post init support for the create part input.

Parameters:

Name Type Description Default
__context Any

The context value.

required

Returns:

Name Type Description
None None

None.

Raises:

Type Description
ValueError

Name is required.

Source code in src/solidworks_mcp/tools/modeling.py
def model_post_init(self, __context: Any) -> None:
    """Provide model post init support for the create part input.

    Args:
        __context (Any): The context value.

    Returns:
        None: None.

    Raises:
        ValueError: Name is required.
    """
    if not self.name.strip():
        raise ValueError("name is required")

CreateReferencePlaneInput

Bases: CompatInput

Input schema for creating a reference plane.

Attributes:

Name Type Description
reference str

Name of the reference plane.

face_point list[float] | None

A point on a flat face to use instead.

offset float

Offset distance in millimetres.

angle float

Angle in degrees.

axis str | None

Axis to rotate about, for an angle.

flip bool

Reverse the offset or angle direction.

CreateReferencePointInput

Bases: CompatInput

Input schema for creating a reference point.

Attributes:

Name Type Description
mode str

"along_curve" or "face_center".

x float

X of a point on the target edge/face, in millimetres.

y float

Y of a point on the target edge/face, in millimetres.

z float

Z of a point on the target edge/face, in millimetres.

distance float | None

For "along_curve", offset from the edge start in millimetres.

percent float | None

For "along_curve", position as 0-100 of the edge length.

CreateRevolveInput

Bases: CompatInput

Input schema for creating a revolve feature.

Attributes:

Name Type Description
angle float

The angle value.

axis_entity str | None

A reference axis to revolve about.

both_directions bool

The both directions value.

merge_result bool

The merge result value.

reverse_direction bool

The reverse direction value.

sketch_name str | None

The sketch to revolve; None for the last closed.

thin_feature bool

The thin feature value.

thin_thickness float | None

The thin thickness value.

Methods:
model_post_init
model_post_init(__context: Any) -> None

Provide model post init support for the create revolve input.

Parameters:

Name Type Description Default
__context Any

The context value.

required

Returns:

Name Type Description
None None

None.

Raises:

Type Description
ValueError

Angle must be positive.

Source code in src/solidworks_mcp/tools/modeling.py
def model_post_init(self, __context: Any) -> None:
    """Provide model post init support for the create revolve input.

    Args:
        __context (Any): The context value.

    Returns:
        None: None.

    Raises:
        ValueError: Angle must be positive.
    """
    if self.angle <= 0:
        raise ValueError("angle must be positive")

CreateSweepInput

Bases: BaseModel

Input schema for creating a sweep feature.

Attributes:

Name Type Description
merge_result bool

The merge result value.

path str

The path value.

twist_along_path bool

The twist along path value.

twist_angle float

The twist angle value.

DeleteFeatureInput

Bases: CompatInput

Input schema for deleting a feature.

Attributes:

Name Type Description
name str

Feature or sketch name to delete.

ExtrusionParameters

Bases: BaseModel

Parameters for extrusion operations.

Attributes:

Name Type Description
auto_select bool

The auto select value.

both_directions bool

The both directions value.

depth float

The depth value.

draft_angle float

The draft angle value.

end_condition str

The end condition value.

feature_scope bool

The feature scope value.

merge_result bool

The merge result value.

reverse_direction bool

The reverse direction value.

sketch_name str | None

Explicit sketch to operate on. When set, callers (e.g. create_cut_extrude) must select exactly this sketch and fail with a clear error if it doesn't exist rather than silently falling back to some other sketch.

thin_feature bool

The thin feature value.

thin_thickness float | None

The thin thickness value.

thin_side str

Which side of the sketch a thin wall grows on: one_side, other_side or mid_plane.

up_to_surface str | None

The up to surface value.

GetDimensionInput

Bases: CompatInput

Input schema for getting a dimension value.

Attributes:

Name Type Description
dimension_name str | None

The dimension name value.

name str | None

The name value.

Methods:
model_post_init
model_post_init(__context: Any) -> None

Provide model post init support for the get dimension input.

Parameters:

Name Type Description Default
__context Any

The context value.

required

Returns:

Name Type Description
None None

None.

Raises:

Type Description
ValueError

Name is required.

Source code in src/solidworks_mcp/tools/modeling.py
def model_post_init(self, __context: Any) -> None:
    """Provide model post init support for the get dimension input.

    Args:
        __context (Any): The context value.

    Returns:
        None: None.

    Raises:
        ValueError: Name is required.
    """
    if self.name is None:
        self.name = self.dimension_name
    if not self.name:
        raise ValueError("name is required")

InsertComponentInput

Bases: CompatInput

Input schema for inserting a component into an assembly.

Attributes:

Name Type Description
file_path str

Path to the part or sub-assembly.

x float

X position in millimetres.

y float

Y position in millimetres.

z float

Z position in millimetres.

LoftParameters

Bases: BaseModel

Parameters for loft operations.

Attributes:

Name Type Description
end_tangent str | None

The end tangent value.

guide_curves list[str] | None

The guide curves value.

merge_result bool

The merge result value.

profiles list[str]

The profiles value.

start_tangent str | None

The start tangent value.

MirrorFeatureInput

Bases: CompatInput

Input schema for mirroring solid bodies or features.

Attributes:

Name Type Description
features list[str]

Body or feature names to mirror.

mirror_plane str

Plane name to mirror about.

merge bool

Merge the mirrored result with the original.

mirror_bodies bool

Mirror whole bodies rather than features.

OpenModelInput

Bases: BaseModel

Input schema for opening a SolidWorks model.

Attributes:

Name Type Description
file_path str

The file path value.

PatternCircularInput

Bases: CompatInput

Input schema for patterning features around an axis.

Attributes:

Name Type Description
features list[str]

Names of the features to pattern.

axis str

Name of the axis to rotate about.

count int

Total number of instances including the original.

angle float

Total angle in degrees to spread instances over.

equal_spacing bool

Space instances evenly across angle.

RebuildModelInput

Bases: CompatInput

Input schema for forcing a model rebuild.

Attributes:

Name Type Description
top_level_only bool

Rebuild only the top level of an assembly.

RenameFeatureInput

Bases: CompatInput

Input schema for renaming a feature.

Attributes:

Name Type Description
old_name str

Current feature name.

new_name str

New feature name.

RevolveParameters

Bases: BaseModel

Parameters for revolve operations.

Attributes:

Name Type Description
angle float

The angle value.

both_directions bool

The both directions value.

merge_result bool

The merge result value.

reverse_direction bool

The reverse direction value.

thin_feature bool

The thin feature value.

thin_thickness float | None

The thin thickness value.

sketch_name str | None

The sketch to revolve, by its tree name; None for the sketch closed last.

axis_entity str | None

A reference axis to revolve about, by its tree name; None for the sketch's own centreline.

SelectFaceEdgesInput

Bases: CompatInput

Input schema for multi-selecting every edge of one face.

Attributes:

Name Type Description
point list[float] | None

A point on the face, [x, y, z] in mm.

side str | None

Which way the face points.

plane str | None

Reference plane the face lies on.

edge_type str

Edge filter: all, linear or circular.

append bool

Add to the current selection instead of replacing it.

SelectFeatureInput

Bases: CompatInput

Input schema for selecting a named feature.

Attributes:

Name Type Description
feature_name str

Feature, sketch, plane or component name.

append bool

Add to the current selection instead of replacing it.

SetComponentStateInput

Bases: CompatInput

Input schema for fixing, floating and flexing a component.

Attributes:

Name Type Description
component str

Component instance name.

fixed bool | None

True fixes it, False floats it.

flexible bool | None

True flexible, False rigid.

SetDimensionInput

Bases: CompatInput

Input schema for setting a dimension value.

Attributes:

Name Type Description
dimension_name str | None

The dimension name value.

name str | None

The name value.

units str | None

The units value.

value float

The value value.

Methods:
model_post_init
model_post_init(__context: Any) -> None

Provide model post init support for the set dimension input.

Parameters:

Name Type Description Default
__context Any

The context value.

required

Returns:

Name Type Description
None None

None.

Raises:

Type Description
ValueError

Name is required.

Source code in src/solidworks_mcp/tools/modeling.py
def model_post_init(self, __context: Any) -> None:
    """Provide model post init support for the set dimension input.

    Args:
        __context (Any): The context value.

    Returns:
        None: None.

    Raises:
        ValueError: Name is required.
    """
    if self.name is None:
        self.name = self.dimension_name
    if not self.name:
        raise ValueError("name is required")

SetUnitsInput

Bases: CompatInput

Input schema for setting the active document's unit system.

Attributes:

Name Type Description
unit_system str

Target linear unit - mm, cm, m, in or ft (aliases such as inch / millimeters accepted).

SolidWorksAdapter

SolidWorksAdapter(config: object | None = None)

Bases: ABC

Base adapter interface for SolidWorks integration.

Parameters:

Name Type Description Default
config object | None

Configuration values for the operation. Defaults to None.

None

Attributes:

Name Type Description
_metrics Any

The metrics value.

config Any

The config value.

config_dict Any

The config dict value.

Initialize adapter with configuration.

Parameters:

Name Type Description Default
config object | None

Configuration values for the operation. Defaults to None.

None
Source code in src/solidworks_mcp/adapters/base.py
def __init__(self, config: object | None = None):
    """Initialize adapter with configuration.

    Args:
        config (object | None): Configuration values for the operation. Defaults to None.
    """
    if config is None:
        normalized_config: dict[str, Any] = {}
    elif isinstance(config, Mapping):
        normalized_config = dict(config)
    elif hasattr(config, "model_dump"):
        normalized_config = dict(config.model_dump())
    else:
        normalized_config = {}

    # Preserve original config object for compatibility with tests and
    # call sites that compare object identity/equality.
    self.config = config
    # Keep a normalized mapping for adapter internals.
    self.config_dict = normalized_config
    self._metrics = {
        "operations_count": 0,
        "errors_count": 0,
        "average_response_time": 0.0,
    }
    # SolidWorks-as-Code session logging. Set soc_session_id to enable
    # automatic ToolCallRecord writes for every adapter operation.
    self.soc_session_id: str | None = None
    self.soc_db_path: Path | None = None
Methods:
activate_document async
activate_document(title_or_path: str) -> AdapterResult[dict[str, Any]]

Make an already-open document the active one.

Parameters:

Name Type Description Default
title_or_path str

Title, full path, or file name of an open document.

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: What was activated, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def activate_document(
    self, title_or_path: str
) -> AdapterResult[dict[str, Any]]:
    """Make an already-open document the active one.

    Args:
        title_or_path (str): Title, full path, or file name of an open
            document.

    Returns:
        AdapterResult[dict[str, Any]]: What was activated, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="activate_document is not implemented by this adapter",
    )
add_arc async
add_arc(center_x: float, center_y: float, start_x: float, start_y: float, end_x: float, end_y: float) -> AdapterResult[str]

Add an arc to the current sketch.

Parameters:

Name Type Description Default
center_x float

The center x value.

required
center_y float

The center y value.

required
start_x float

The start x value.

required
start_y float

The start y value.

required
end_x float

The end x value.

required
end_y float

The end y value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_arc(
    self,
    center_x: float,
    center_y: float,
    start_x: float,
    start_y: float,
    end_x: float,
    end_y: float,
) -> AdapterResult[str]:
    """Add an arc to the current sketch.

    Args:
        center_x (float): The center x value.
        center_y (float): The center y value.
        start_x (float): The start x value.
        start_y (float): The start y value.
        end_x (float): The end x value.
        end_y (float): The end y value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_arc is not implemented by this adapter",
    )
add_centerline async
add_centerline(x1: float, y1: float, x2: float, y2: float) -> AdapterResult[str]

Add a centerline to the current sketch.

Parameters:

Name Type Description Default
x1 float

The x1 value.

required
y1 float

The y1 value.

required
x2 float

The x2 value.

required
y2 float

The y2 value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_centerline(
    self, x1: float, y1: float, x2: float, y2: float
) -> AdapterResult[str]:
    """Add a centerline to the current sketch.

    Args:
        x1 (float): The x1 value.
        y1 (float): The y1 value.
        x2 (float): The x2 value.
        y2 (float): The y2 value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_centerline is not implemented by this adapter",
    )
add_chamfer async
add_chamfer(distance: float, edge_names: list[str], angle: float = 45.0, flip: bool = False) -> AdapterResult[Any]

Add an angle-distance chamfer to the named or selected edges.

At the default 45 degrees both legs equal distance.

Parameters:

Name Type Description Default
distance float

Chamfer distance in millimeters, along one face.

required
edge_names list[str]

List of edge names to chamfer.

required
angle float

Chamfer angle in degrees. Defaults to 45.

45.0
flip bool

Measure distance along the other face.

False

Returns:

Name Type Description
AdapterResult AdapterResult[Any]

Feature result or error.

Source code in src/solidworks_mcp/adapters/base.py
async def add_chamfer(
    self,
    distance: float,
    edge_names: list[str],
    angle: float = 45.0,
    flip: bool = False,
) -> AdapterResult[Any]:
    """Add an angle-distance chamfer to the named or selected edges.

    At the default 45 degrees both legs equal ``distance``.

    Args:
        distance (float): Chamfer distance in millimeters, along one face.
        edge_names (list[str]): List of edge names to chamfer.
        angle (float): Chamfer angle in degrees. Defaults to 45.
        flip (bool): Measure ``distance`` along the other face.

    Returns:
        AdapterResult: Feature result or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_chamfer is not implemented by this adapter",
    )
add_circle abstractmethod async
add_circle(center_x: float, center_y: float, radius: float) -> AdapterResult[str]

Add a circle to the current sketch.

Parameters:

Name Type Description Default
center_x float

The center x value.

required
center_y float

The center y value.

required
radius float

The radius value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def add_circle(
    self, center_x: float, center_y: float, radius: float
) -> AdapterResult[str]:
    """Add a circle to the current sketch.

    Args:
        center_x (float): The center x value.
        center_y (float): The center y value.
        radius (float): The radius value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    pass
add_datum_tag async
add_datum_tag(label: str, attach_at_mm: tuple[float, float], x_mm: float, y_mm: float) -> AdapterResult[dict[str, Any]]

Add a datum feature symbol on a drawing edge.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def add_datum_tag(
    self,
    label: str,
    attach_at_mm: tuple[float, float],
    x_mm: float,
    y_mm: float,
) -> AdapterResult[dict[str, Any]]:
    """Add a datum feature symbol on a drawing edge.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_datum_tag is not implemented by this adapter",
    )
add_drawing_view async
add_drawing_view(payload: Any = None) -> AdapterResult[dict[str, Any]]

Add a view of a model to the active drawing sheet.

Parameters:

Name Type Description Default
payload Any

Tool payload carrying the model path, orientation, position in millimetres and optional view scale.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The new view's details, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def add_drawing_view(
    self, payload: Any = None
) -> AdapterResult[dict[str, Any]]:
    """Add a view of a model to the active drawing sheet.

    Args:
        payload (Any): Tool payload carrying the model path, orientation,
            position in millimetres and optional view scale.

    Returns:
        AdapterResult[dict[str, Any]]: The new view's details, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_drawing_view is not implemented by this adapter",
    )
add_ellipse async
add_ellipse(center_x: float, center_y: float, major_axis: float, minor_axis: float) -> AdapterResult[str]

Add an ellipse to the current sketch.

Parameters:

Name Type Description Default
center_x float

The center x value.

required
center_y float

The center y value.

required
major_axis float

The major axis value.

required
minor_axis float

The minor axis value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_ellipse(
    self,
    center_x: float,
    center_y: float,
    major_axis: float,
    minor_axis: float,
) -> AdapterResult[str]:
    """Add an ellipse to the current sketch.

    Args:
        center_x (float): The center x value.
        center_y (float): The center y value.
        major_axis (float): The major axis value.
        minor_axis (float): The minor axis value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_ellipse is not implemented by this adapter",
    )
add_fillet async
add_fillet(radius: float, edge_names: list[str]) -> AdapterResult[Any]

Add a fillet feature to selected edges.

Rounds the selected edges of the current solid body with the given radius.

Parameters:

Name Type Description Default
radius float

Fillet radius in millimeters.

required
edge_names list[str]

List of edge names to fillet.

required

Returns:

Name Type Description
AdapterResult AdapterResult[Any]

Feature result or error.

Source code in src/solidworks_mcp/adapters/base.py
async def add_fillet(
    self, radius: float, edge_names: list[str]
) -> AdapterResult[Any]:
    """Add a fillet feature to selected edges.

    Rounds the selected edges of the current solid body with the given radius.

    Args:
        radius (float): Fillet radius in millimeters.
        edge_names (list[str]): List of edge names to fillet.

    Returns:
        AdapterResult: Feature result or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_fillet is not implemented by this adapter",
    )
add_gtol async
add_gtol(characteristic: str, tolerance: float, x_mm: float, y_mm: float, diameter_zone: bool = False, material_condition: str = 'none', datums: list[str] | None = None, attach_at_mm: tuple[float, float] | None = None, dimension: tuple[str, str] | None = None) -> AdapterResult[dict[str, Any]]

Add a GD&T feature control frame to the active drawing.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def add_gtol(
    self,
    characteristic: str,
    tolerance: float,
    x_mm: float,
    y_mm: float,
    diameter_zone: bool = False,
    material_condition: str = "none",
    datums: list[str] | None = None,
    attach_at_mm: tuple[float, float] | None = None,
    dimension: tuple[str, str] | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Add a GD&T feature control frame to the active drawing.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_gtol is not implemented by this adapter",
    )
add_line abstractmethod async
add_line(x1: float, y1: float, x2: float, y2: float) -> AdapterResult[str]

Add a line to the current sketch.

Parameters:

Name Type Description Default
x1 float

The x1 value.

required
y1 float

The y1 value.

required
x2 float

The x2 value.

required
y2 float

The y2 value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def add_line(
    self, x1: float, y1: float, x2: float, y2: float
) -> AdapterResult[str]:
    """Add a line to the current sketch.

    Args:
        x1 (float): The x1 value.
        y1 (float): The y1 value.
        x2 (float): The x2 value.
        y2 (float): The y2 value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    pass
add_mate async
add_mate(component_a: str, component_b: str, entity_a: str = 'Front Plane', entity_b: str = 'Front Plane', mate_type: str = 'coincident', alignment: str = 'aligned', distance: float = 0.0, angle: float = 0.0, face_a: list[float] | None = None, face_b: list[float] | None = None) -> AdapterResult[dict[str, Any]]

Mate two components together in the active assembly.

Parameters:

Name Type Description Default
component_a str

First component instance name.

required
component_b str

Second component instance name.

required
entity_a str

Named feature on the first component. Defaults to "Front Plane".

'Front Plane'
entity_b str

Named feature on the second component. Defaults to "Front Plane".

'Front Plane'
mate_type str

Mate type, e.g. coincident. Defaults to "coincident".

'coincident'
alignment str

aligned, anti_aligned or closest. Defaults to "aligned".

'aligned'
distance float

Distance in millimetres, for a distance mate. Defaults to 0.0.

0.0
angle float

Angle in degrees, for an angle mate. Defaults to 0.0.

0.0
face_a list[float] | None

A point on a face of the first component, in its part coordinates (mm), used instead of entity_a.

None
face_b list[float] | None

The same for the second component.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Mate details, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def add_mate(
    self,
    component_a: str,
    component_b: str,
    entity_a: str = "Front Plane",
    entity_b: str = "Front Plane",
    mate_type: str = "coincident",
    alignment: str = "aligned",
    distance: float = 0.0,
    angle: float = 0.0,
    face_a: list[float] | None = None,
    face_b: list[float] | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Mate two components together in the active assembly.

    Args:
        component_a (str): First component instance name.
        component_b (str): Second component instance name.
        entity_a (str): Named feature on the first component. Defaults to
            "Front Plane".
        entity_b (str): Named feature on the second component. Defaults to
            "Front Plane".
        mate_type (str): Mate type, e.g. ``coincident``. Defaults to
            "coincident".
        alignment (str): ``aligned``, ``anti_aligned`` or ``closest``.
            Defaults to "aligned".
        distance (float): Distance in millimetres, for a distance mate.
            Defaults to 0.0.
        angle (float): Angle in degrees, for an angle mate. Defaults to 0.0.
        face_a (list[float] | None): A point on a face of the first
            component, in its part coordinates (mm), used instead of
            ``entity_a``.
        face_b (list[float] | None): The same for the second component.

    Returns:
        AdapterResult[dict[str, Any]]: Mate details, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_mate is not implemented by this adapter",
    )
add_note async
add_note(payload: Any = None) -> AdapterResult[dict[str, Any]]

Place a text note on the active drawing sheet.

Parameters:

Name Type Description Default
payload Any

Tool payload carrying the note text, its position in millimetres and an optional font size in points.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The note's details, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def add_note(self, payload: Any = None) -> AdapterResult[dict[str, Any]]:
    """Place a text note on the active drawing sheet.

    Args:
        payload (Any): Tool payload carrying the note text, its position in
            millimetres and an optional font size in points.

    Returns:
        AdapterResult[dict[str, Any]]: The note's details, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_note is not implemented by this adapter",
    )
add_polygon async
add_polygon(center_x: float, center_y: float, radius: float, sides: int) -> AdapterResult[str]

Add a regular polygon to the current sketch.

Parameters:

Name Type Description Default
center_x float

The center x value.

required
center_y float

The center y value.

required
radius float

The radius value.

required
sides int

The sides value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_polygon(
    self, center_x: float, center_y: float, radius: float, sides: int
) -> AdapterResult[str]:
    """Add a regular polygon to the current sketch.

    Args:
        center_x (float): The center x value.
        center_y (float): The center y value.
        radius (float): The radius value.
        sides (int): The sides value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_polygon is not implemented by this adapter",
    )
add_rectangle abstractmethod async
add_rectangle(x1: float, y1: float, x2: float, y2: float) -> AdapterResult[str]

Add a rectangle to the current sketch.

Parameters:

Name Type Description Default
x1 float

The x1 value.

required
y1 float

The y1 value.

required
x2 float

The x2 value.

required
y2 float

The y2 value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def add_rectangle(
    self, x1: float, y1: float, x2: float, y2: float
) -> AdapterResult[str]:
    """Add a rectangle to the current sketch.

    Args:
        x1 (float): The x1 value.
        y1 (float): The y1 value.
        x2 (float): The x2 value.
        y2 (float): The y2 value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    pass
add_sketch_circle async
add_sketch_circle(center_x: float, center_y: float, radius: float, construction: bool = False) -> AdapterResult[str]

Alias for add_circle used by some tool flows.

Parameters:

Name Type Description Default
center_x float

The center x value.

required
center_y float

The center y value.

required
radius float

The radius value.

required
construction bool

The construction value. Defaults to False.

False

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_sketch_circle(
    self,
    center_x: float,
    center_y: float,
    radius: float,
    construction: bool = False,
) -> AdapterResult[str]:
    """Alias for add_circle used by some tool flows.

    Args:
        center_x (float): The center x value.
        center_y (float): The center y value.
        radius (float): The radius value.
        construction (bool): The construction value. Defaults to False.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return await self.add_circle(center_x, center_y, radius)
add_sketch_constraint async
add_sketch_constraint(entity1: str, entity2: str | None, relation_type: str, entity3: str | None = None) -> AdapterResult[str]

Apply a geometric constraint between sketch entities.

Parameters:

Name Type Description Default
entity1 str

The entity1 value.

required
entity2 str | None

The entity2 value.

required
relation_type str

The relation type value.

required
entity3 str | None

Third entity ID — only used by the symmetric relation (the centerline of symmetry). All other relation types reject a non-null entity3.

None

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_sketch_constraint(
    self,
    entity1: str,
    entity2: str | None,
    relation_type: str,
    entity3: str | None = None,
) -> AdapterResult[str]:
    """Apply a geometric constraint between sketch entities.

    Args:
        entity1 (str): The entity1 value.
        entity2 (str | None): The entity2 value.
        relation_type (str): The relation type value.
        entity3 (str | None): Third entity ID — only used by the
            ``symmetric`` relation (the centerline of symmetry). All
            other relation types reject a non-null ``entity3``.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_sketch_constraint is not implemented by this adapter",
    )
add_sketch_dimension async
add_sketch_dimension(entity1: str, entity2: str | None, dimension_type: str, value: float) -> AdapterResult[str]

Add a sketch dimension.

Parameters:

Name Type Description Default
entity1 str

The entity1 value.

required
entity2 str | None

The entity2 value.

required
dimension_type str

The dimension type value.

required
value float

The value value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_sketch_dimension(
    self,
    entity1: str,
    entity2: str | None,
    dimension_type: str,
    value: float,
) -> AdapterResult[str]:
    """Add a sketch dimension.

    Args:
        entity1 (str): The entity1 value.
        entity2 (str | None): The entity2 value.
        dimension_type (str): The dimension type value.
        value (float): The value value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_sketch_dimension is not implemented by this adapter",
    )
add_spline async
add_spline(points: list[dict[str, float]]) -> AdapterResult[str]

Add a spline through the provided points.

Parameters:

Name Type Description Default
points list[dict[str, float]]

The points value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def add_spline(self, points: list[dict[str, float]]) -> AdapterResult[str]:
    """Add a spline through the provided points.

    Args:
        points (list[dict[str, float]]): The points value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="add_spline is not implemented by this adapter",
    )
arrange_dimensions async
arrange_dimensions(view_name: str | None = None) -> AdapterResult[dict[str, Any]]

Move drawing dimensions so none overlaps, then verify.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def arrange_dimensions(
    self,
    view_name: str | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Move drawing dimensions so none overlaps, then verify.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="arrange_dimensions is not implemented by this adapter",
    )
auto_center_marks async
auto_center_marks(view_name: str, mark_holes: bool = True, mark_fillets: bool = False, mark_slots: bool = True) -> AdapterResult[dict[str, Any]]

Auto-insert centre marks on circular features in a drawing view.

Parameters:

Name Type Description Default
view_name str

Name of a view on the active drawing.

required
mark_holes bool

Mark holes / bores.

True
mark_fillets bool

Mark fillets.

False
mark_slots bool

Mark slots.

True

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The view and before/after centre-mark

AdapterResult[dict[str, Any]]

counts, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def auto_center_marks(
    self,
    view_name: str,
    mark_holes: bool = True,
    mark_fillets: bool = False,
    mark_slots: bool = True,
) -> AdapterResult[dict[str, Any]]:
    """Auto-insert centre marks on circular features in a drawing view.

    Args:
        view_name (str): Name of a view on the active drawing.
        mark_holes (bool): Mark holes / bores.
        mark_fillets (bool): Mark fillets.
        mark_slots (bool): Mark slots.

    Returns:
        AdapterResult[dict[str, Any]]: The view and before/after centre-mark
        counts, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="auto_center_marks is not implemented by this adapter",
    )
check_interference async
check_interference(params: Any = None) -> AdapterResult[dict[str, Any]]

Check the active assembly for interfering components.

Parameters:

Name Type Description Default
params Any

Optional settings; coincident, components.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Interference details, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def check_interference(
    self, params: Any = None
) -> AdapterResult[dict[str, Any]]:
    """Check the active assembly for interfering components.

    Args:
        params (Any): Optional settings; ``coincident``, ``components``.

    Returns:
        AdapterResult[dict[str, Any]]: Interference details, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="check_interference is not implemented by this adapter",
    )
check_sketch_fully_defined async
check_sketch_fully_defined(sketch_name: str | None = None) -> AdapterResult[dict[str, Any]]

Check whether a sketch is fully defined.

Parameters:

Name Type Description Default
sketch_name str | None

Optional sketch name to inspect. Defaults to None.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Definition status payload.

Source code in src/solidworks_mcp/adapters/base.py
async def check_sketch_fully_defined(
    self, sketch_name: str | None = None
) -> AdapterResult[dict[str, Any]]:
    """Check whether a sketch is fully defined.

    Args:
        sketch_name (str | None): Optional sketch name to inspect. Defaults to None.

    Returns:
        AdapterResult[dict[str, Any]]: Definition status payload.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="check_sketch_fully_defined is not implemented by this adapter",
    )
close_model abstractmethod async
close_model(save: bool = False) -> AdapterResult[None]

Close the current model.

Parameters:

Name Type Description Default
save bool

The save value. Defaults to False.

False

Returns:

Type Description
AdapterResult[None]

AdapterResult[None]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def close_model(self, save: bool = False) -> AdapterResult[None]:
    """Close the current model.

    Args:
        save (bool): The save value. Defaults to False.

    Returns:
        AdapterResult[None]: The result produced by the operation.
    """
    pass
connect abstractmethod async
connect() -> None

Connect to SolidWorks application.

Returns:

Name Type Description
None None

None.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def connect(self) -> None:
    """Connect to SolidWorks application.

    Returns:
        None: None.
    """
    pass
create_assembly abstractmethod async
create_assembly(name: str | None = None, template: str | None = None) -> AdapterResult[SolidWorksModel]

Create a new assembly document.

Parameters:

Name Type Description Default
name str | None

The name value. Defaults to None.

None
template str | None

Template file path. Defaults to None.

None

Returns:

Type Description
AdapterResult[SolidWorksModel]

AdapterResult[SolidWorksModel]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_assembly(
    self, name: str | None = None, template: str | None = None
) -> AdapterResult[SolidWorksModel]:
    """Create a new assembly document.

    Args:
        name (str | None): The name value. Defaults to None.
        template (str | None): Template file path. Defaults to None.

    Returns:
        AdapterResult[SolidWorksModel]: The result produced by the operation.
    """
    pass
create_axis async
create_axis(reference: str) -> AdapterResult[dict[str, Any]]

Create a reference axis along a principal direction.

Parameters:

Name Type Description Default
reference str

"x", "y" or "z" (case-insensitive, leading ± stripped).

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The plane pair used and feature counts, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def create_axis(self, reference: str) -> AdapterResult[dict[str, Any]]:
    """Create a reference axis along a principal direction.

    Args:
        reference (str): "x", "y" or "z" (case-insensitive, leading +/- stripped).

    Returns:
        AdapterResult[dict[str, Any]]: The plane pair used and feature counts, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_axis is not implemented by this adapter",
    )
create_cut async
create_cut(sketch_name: str, depth: float) -> AdapterResult[str]

Create a cut feature from an existing sketch.

Parameters:

Name Type Description Default
sketch_name str

The sketch name value.

required
depth float

The depth value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def create_cut(self, sketch_name: str, depth: float) -> AdapterResult[str]:
    """Create a cut feature from an existing sketch.

    Args:
        sketch_name (str): The sketch name value.
        depth (float): The depth value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_cut is not implemented by this adapter",
    )
create_cut_extrude async
create_cut_extrude(params: ExtrusionParameters) -> AdapterResult[Any]

Create a cut-extrude feature from the active sketch.

Cuts material from the current solid body using the active sketch profile. Equivalent to SolidWorks Insert > Cut > Extrude.

Parameters:

Name Type Description Default
params ExtrusionParameters

Depth and direction parameters.

required

Returns:

Name Type Description
AdapterResult AdapterResult[Any]

Feature result or error.

Source code in src/solidworks_mcp/adapters/base.py
async def create_cut_extrude(
    self, params: ExtrusionParameters
) -> AdapterResult[Any]:
    """Create a cut-extrude feature from the active sketch.

    Cuts material from the current solid body using the active sketch profile.
    Equivalent to SolidWorks Insert > Cut > Extrude.

    Args:
        params (ExtrusionParameters): Depth and direction parameters.

    Returns:
        AdapterResult: Feature result or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_cut_extrude is not implemented by this adapter",
    )
create_drawing abstractmethod async
create_drawing(name: str | None = None, template: str | None = None) -> AdapterResult[SolidWorksModel]

Create a new drawing document.

Parameters:

Name Type Description Default
name str | None

The name value. Defaults to None.

None
template str | None

Template file path. Defaults to None.

None

Returns:

Type Description
AdapterResult[SolidWorksModel]

AdapterResult[SolidWorksModel]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_drawing(
    self, name: str | None = None, template: str | None = None
) -> AdapterResult[SolidWorksModel]:
    """Create a new drawing document.

    Args:
        name (str | None): The name value. Defaults to None.
        template (str | None): Template file path. Defaults to None.

    Returns:
        AdapterResult[SolidWorksModel]: The result produced by the operation.
    """
    pass
create_drawing_view async
create_drawing_view(payload: Any = None) -> AdapterResult[dict[str, Any]]

Place a view of a model on the active drawing sheet.

Parameters:

Name Type Description Default
payload Any

Tool payload carrying the model path, orientation, position in millimetres and optional view scale.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The new view's details, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def create_drawing_view(
    self, payload: Any = None
) -> AdapterResult[dict[str, Any]]:
    """Place a view of a model on the active drawing sheet.

    Args:
        payload (Any): Tool payload carrying the model path, orientation,
            position in millimetres and optional view scale.

    Returns:
        AdapterResult[dict[str, Any]]: The new view's details, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_drawing_view is not implemented by this adapter",
    )
create_extrusion abstractmethod async
create_extrusion(params: ExtrusionParameters) -> AdapterResult[SolidWorksFeature]

Create an extrusion feature.

Parameters:

Name Type Description Default
params ExtrusionParameters

The params value.

required

Returns:

Type Description
AdapterResult[SolidWorksFeature]

AdapterResult[SolidWorksFeature]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_extrusion(
    self, params: ExtrusionParameters
) -> AdapterResult[SolidWorksFeature]:
    """Create an extrusion feature.

    Args:
        params (ExtrusionParameters): The params value.

    Returns:
        AdapterResult[SolidWorksFeature]: The result produced by the operation.
    """
    pass
create_loft abstractmethod async
create_loft(params: LoftParameters) -> AdapterResult[SolidWorksFeature]

Create a loft feature.

Parameters:

Name Type Description Default
params LoftParameters

The params value.

required

Returns:

Type Description
AdapterResult[SolidWorksFeature]

AdapterResult[SolidWorksFeature]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_loft(
    self, params: LoftParameters
) -> AdapterResult[SolidWorksFeature]:
    """Create a loft feature.

    Args:
        params (LoftParameters): The params value.

    Returns:
        AdapterResult[SolidWorksFeature]: The result produced by the operation.
    """
    pass
create_part abstractmethod async
create_part(name: str | None = None, units: str | None = None, template: str | None = None) -> AdapterResult[SolidWorksModel]

Create a new part document.

Parameters:

Name Type Description Default
name str | None

The name value. Defaults to None.

None
units str | None

The units value. Defaults to None.

None
template str | None

Template file path. Defaults to None.

None

Returns:

Type Description
AdapterResult[SolidWorksModel]

AdapterResult[SolidWorksModel]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_part(
    self,
    name: str | None = None,
    units: str | None = None,
    template: str | None = None,
) -> AdapterResult[SolidWorksModel]:
    """Create a new part document.

    Args:
        name (str | None): The name value. Defaults to None.
        units (str | None): The units value. Defaults to None.
        template (str | None): Template file path. Defaults to None.

    Returns:
        AdapterResult[SolidWorksModel]: The result produced by the operation.
    """
    pass
create_reference_plane async
create_reference_plane(reference: str, offset: float = 0.0, angle: float = 0.0, flip: bool = False, axis: str | None = None, face_point: list[float] | None = None) -> AdapterResult[dict[str, Any]]

Create a reference plane offset from, angled to, or on a plane or face.

Parameters:

Name Type Description Default
reference str

Name of the reference plane.

required
offset float

Offset distance in millimetres. Defaults to 0.0.

0.0
angle float

Angle in degrees about axis. Defaults to 0.0.

0.0
flip bool

Reverse the offset or angle direction. Defaults to False.

False
axis str | None

Named axis to rotate about; needed with angle.

None
face_point list[float] | None

[x, y, z] mm on a flat face to use as the reference instead of reference.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The new plane's name and parameters, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def create_reference_plane(
    self,
    reference: str,
    offset: float = 0.0,
    angle: float = 0.0,
    flip: bool = False,
    axis: str | None = None,
    face_point: list[float] | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Create a reference plane offset from, angled to, or on a plane or face.

    Args:
        reference (str): Name of the reference plane.
        offset (float): Offset distance in millimetres. Defaults to 0.0.
        angle (float): Angle in degrees about ``axis``. Defaults to 0.0.
        flip (bool): Reverse the offset or angle direction. Defaults to False.
        axis (str | None): Named axis to rotate about; needed with ``angle``.
        face_point (list[float] | None): ``[x, y, z]`` mm on a flat face to
            use as the reference instead of ``reference``.

    Returns:
        AdapterResult[dict[str, Any]]: The new plane's name and parameters, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_reference_plane is not implemented by this adapter",
    )
create_reference_point async
create_reference_point(mode: str, x: float, y: float, z: float, distance: float | None = None, percent: float | None = None) -> AdapterResult[dict[str, Any]]

Create a reference point on the active part.

Parameters:

Name Type Description Default
mode str

"along_curve" or "face_center".

required
x float

X of a point on the target edge/face, in millimetres.

required
y float

Y of a point on the target edge/face, in millimetres.

required
z float

Z of a point on the target edge/face, in millimetres.

required
distance float | None

For "along_curve", offset from the edge start in millimetres.

None
percent float | None

For "along_curve", position as 0-100 of the edge length.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The mode and feature counts, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def create_reference_point(
    self,
    mode: str,
    x: float,
    y: float,
    z: float,
    distance: float | None = None,
    percent: float | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Create a reference point on the active part.

    Args:
        mode (str): "along_curve" or "face_center".
        x (float): X of a point on the target edge/face, in millimetres.
        y (float): Y of a point on the target edge/face, in millimetres.
        z (float): Z of a point on the target edge/face, in millimetres.
        distance (float | None): For "along_curve", offset from the edge
            start in millimetres.
        percent (float | None): For "along_curve", position as 0-100 of
            the edge length.

    Returns:
        AdapterResult[dict[str, Any]]: The mode and feature counts, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_reference_point is not implemented by this adapter",
    )
create_revolve abstractmethod async
create_revolve(params: RevolveParameters) -> AdapterResult[SolidWorksFeature]

Create a revolve feature.

Parameters:

Name Type Description Default
params RevolveParameters

The params value.

required

Returns:

Type Description
AdapterResult[SolidWorksFeature]

AdapterResult[SolidWorksFeature]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_revolve(
    self, params: RevolveParameters
) -> AdapterResult[SolidWorksFeature]:
    """Create a revolve feature.

    Args:
        params (RevolveParameters): The params value.

    Returns:
        AdapterResult[SolidWorksFeature]: The result produced by the operation.
    """
    pass
create_sketch abstractmethod async
create_sketch(plane: str) -> AdapterResult[str]

Create a new sketch on the specified plane.

Parameters:

Name Type Description Default
plane str

The plane value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_sketch(self, plane: str) -> AdapterResult[str]:
    """Create a new sketch on the specified plane.

    Args:
        plane (str): The plane value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    pass
create_standard_drawing async
create_standard_drawing(model_path: str, output_dir: str | None = None, title: str | None = None, subtitle: str | None = None, drawing_number: str | None = None, author: str = '', revision: str = 'A', company: str = '', drawn_date: str | None = None, notes: list[str] | None = None, include_isometric: bool = True, write_model_properties: bool = True, title_block_text_height_mm: float | None = None, include_bom: bool = False) -> AdapterResult[dict[str, Any]]

Create a complete standard A3 drawing.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def create_standard_drawing(
    self,
    model_path: str,
    output_dir: str | None = None,
    title: str | None = None,
    subtitle: str | None = None,
    drawing_number: str | None = None,
    author: str = "",
    revision: str = "A",
    company: str = "",
    drawn_date: str | None = None,
    notes: list[str] | None = None,
    include_isometric: bool = True,
    write_model_properties: bool = True,
    title_block_text_height_mm: float | None = None,
    include_bom: bool = False,
) -> AdapterResult[dict[str, Any]]:
    """Create a complete standard A3 drawing.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_standard_drawing is not implemented by this adapter",
    )
create_sweep abstractmethod async
create_sweep(params: SweepParameters) -> AdapterResult[SolidWorksFeature]

Create a sweep feature.

Parameters:

Name Type Description Default
params SweepParameters

The params value.

required

Returns:

Type Description
AdapterResult[SolidWorksFeature]

AdapterResult[SolidWorksFeature]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def create_sweep(
    self, params: SweepParameters
) -> AdapterResult[SolidWorksFeature]:
    """Create a sweep feature.

    Args:
        params (SweepParameters): The params value.

    Returns:
        AdapterResult[SolidWorksFeature]: The result produced by the operation.
    """
    pass
create_technical_drawing async
create_technical_drawing(payload: Any = None) -> AdapterResult[dict[str, Any]]

Lay out the standard views of a model on the active sheet.

Parameters:

Name Type Description Default
payload Any

Tool payload carrying the model path and the projection angle.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The view names created, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def create_technical_drawing(
    self, payload: Any = None
) -> AdapterResult[dict[str, Any]]:
    """Lay out the standard views of a model on the active sheet.

    Args:
        payload (Any): Tool payload carrying the model path and the
            projection angle.

    Returns:
        AdapterResult[dict[str, Any]]: The view names created, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="create_technical_drawing is not implemented by this adapter",
    )
delete_feature async
delete_feature(name: str) -> AdapterResult[dict[str, Any]]

Delete a named feature or sketch from the active model.

Parameters:

Name Type Description Default
name str

Feature or sketch name.

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: What was deleted, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def delete_feature(self, name: str) -> AdapterResult[dict[str, Any]]:
    """Delete a named feature or sketch from the active model.

    Args:
        name (str): Feature or sketch name.

    Returns:
        AdapterResult[dict[str, Any]]: What was deleted, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="delete_feature is not implemented by this adapter",
    )
disconnect abstractmethod async
disconnect() -> None

Disconnect from SolidWorks application.

Returns:

Name Type Description
None None

None.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def disconnect(self) -> None:
    """Disconnect from SolidWorks application.

    Returns:
        None: None.
    """
    pass
exit_sketch abstractmethod async
exit_sketch() -> AdapterResult[None]

Exit sketch editing mode.

Returns:

Type Description
AdapterResult[None]

AdapterResult[None]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def exit_sketch(self) -> AdapterResult[None]:
    """Exit sketch editing mode.

    Returns:
        AdapterResult[None]: The result produced by the operation.
    """
    pass
export_file abstractmethod async
export_file(file_path: str, format_type: str) -> AdapterResult[None]

Export the current model to a file.

Parameters:

Name Type Description Default
file_path str

Path to the target file.

required
format_type str

The format type value.

required

Returns:

Type Description
AdapterResult[None]

AdapterResult[None]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def export_file(
    self, file_path: str, format_type: str
) -> AdapterResult[None]:
    """Export the current model to a file.

    Args:
        file_path (str): Path to the target file.
        format_type (str): The format type value.

    Returns:
        AdapterResult[None]: The result produced by the operation.
    """
    pass
export_flat_pattern async
export_flat_pattern(file_path: str) -> AdapterResult[dict[str, Any]]

Export the active sheet-metal part's flat pattern.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def export_flat_pattern(
    self,
    file_path: str,
) -> AdapterResult[dict[str, Any]]:
    """Export the active sheet-metal part's flat pattern.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="export_flat_pattern is not implemented by this adapter",
    )
export_image abstractmethod async
export_image(payload: dict) -> AdapterResult[dict]

Export a viewport screenshot (PNG/JPG) of the current model.

Payload keys: file_path (str): Absolute output path. width (int): Image width in pixels. height (int): Image height in pixels. view_orientation (str): One of "isometric", "front", "top", "right", "back", "bottom", "current".

Parameters:

Name Type Description Default
payload dict

The payload value.

required

Returns:

Type Description
AdapterResult[dict]

AdapterResult[dict]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def export_image(self, payload: dict) -> AdapterResult[dict]:
    """Export a viewport screenshot (PNG/JPG) of the current model.

    Payload keys: file_path (str): Absolute output path. width (int): Image width in pixels.
    height (int): Image height in pixels. view_orientation (str): One of "isometric",
    "front", "top", "right", "back", "bottom", "current".

    Args:
        payload (dict): The payload value.

    Returns:
        AdapterResult[dict]: The result produced by the operation.
    """
    pass
get_application_info async
get_application_info() -> AdapterResult[dict[str, Any]]

Describe the connected SolidWorks without changing anything.

Only file names leave the adapter, never full paths, so the result can be pasted into a public report. A value that cannot be read is None, never guessed.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: revision (e.g. "34.4.0"),

AdapterResult[dict[str, Any]]

language (e.g. "english") and templates: for each of

AdapterResult[dict[str, Any]]

part, assembly and drawing, the default template's

AdapterResult[dict[str, Any]]

file_name and whether the file exists.

Source code in src/solidworks_mcp/adapters/base.py
async def get_application_info(self) -> AdapterResult[dict[str, Any]]:
    """Describe the connected SolidWorks without changing anything.

    Only file names leave the adapter, never full paths, so the result
    can be pasted into a public report. A value that cannot be read is
    ``None``, never guessed.

    Returns:
        AdapterResult[dict[str, Any]]: ``revision`` (e.g. ``"34.4.0"``),
        ``language`` (e.g. ``"english"``) and ``templates``: for each of
        ``part``, ``assembly`` and ``drawing``, the default template's
        ``file_name`` and whether the file ``exists``.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="get_application_info is not implemented by this adapter",
    )
get_custom_properties async
get_custom_properties(configuration: str | None = None) -> AdapterResult[dict[str, Any]]

Read the custom properties of the active document.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def get_custom_properties(
    self,
    configuration: str | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Read the custom properties of the active document.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="get_custom_properties is not implemented by this adapter",
    )
get_dimension abstractmethod async
get_dimension(name: str) -> AdapterResult[dict[str, Any]]

Get the value of a dimension.

Parameters:

Name Type Description Default
name str

The name value.

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: value and units (mm, deg or None).

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def get_dimension(self, name: str) -> AdapterResult[dict[str, Any]]:
    """Get the value of a dimension.

    Args:
        name (str): The name value.

    Returns:
        AdapterResult[dict[str, Any]]: ``value`` and ``units`` (mm, deg or None).
    """
    pass
get_mass_properties abstractmethod async
get_mass_properties() -> AdapterResult[MassProperties]

Get mass properties of the current model.

Returns:

Type Description
AdapterResult[MassProperties]

AdapterResult[MassProperties]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def get_mass_properties(self) -> AdapterResult[MassProperties]:
    """Get mass properties of the current model.

    Returns:
        AdapterResult[MassProperties]: The result produced by the operation.
    """
    pass
get_material async
get_material(configuration: str | None = None) -> AdapterResult[dict[str, Any]]

Read the material assigned to the active part.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def get_material(
    self,
    configuration: str | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Read the material assigned to the active part.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="get_material is not implemented by this adapter",
    )
get_metrics
get_metrics() -> dict[str, Any]

Get adapter metrics.

Returns:

Type Description
dict[str, Any]

dict[str, Any]: A dictionary containing the resulting values.

Source code in src/solidworks_mcp/adapters/base.py
def get_metrics(self) -> dict[str, Any]:
    """Get adapter metrics.

    Returns:
        dict[str, Any]: A dictionary containing the resulting values.
    """
    return self._metrics.copy()
get_model_geometry_summary async
get_model_geometry_summary() -> AdapterResult[dict[str, Any]]

Summarise the active part or assembly without changing it.

Must not rebuild the model, modify it, or clear the selection, so callers can read it around a feature call. Values the adapter cannot determine are None, never guessed.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: document_type ("part" or

AdapterResult[dict[str, Any]]

"assembly"), volume_mm3, bounding_box_mm (min,

AdapterResult[dict[str, Any]]

max and size as [x, y, z]), bounding_box_method,

AdapterResult[dict[str, Any]]

solid_body_count, and for assemblies component_count and

AdapterResult[dict[str, Any]]

mate_count. Error when there is no active part or assembly.

Source code in src/solidworks_mcp/adapters/base.py
async def get_model_geometry_summary(self) -> AdapterResult[dict[str, Any]]:
    """Summarise the active part or assembly without changing it.

    Must not rebuild the model, modify it, or clear the selection, so
    callers can read it around a feature call. Values the adapter cannot
    determine are ``None``, never guessed.

    Returns:
        AdapterResult[dict[str, Any]]: ``document_type`` (``"part"`` or
        ``"assembly"``), ``volume_mm3``, ``bounding_box_mm`` (``min``,
        ``max`` and ``size`` as ``[x, y, z]``), ``bounding_box_method``,
        ``solid_body_count``, and for assemblies ``component_count`` and
        ``mate_count``. Error when there is no active part or assembly.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="get_model_geometry_summary is not implemented by this adapter",
    )
get_model_info abstractmethod async
get_model_info() -> AdapterResult[dict[str, Any]]

Get metadata for the active model.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def get_model_info(self) -> AdapterResult[dict[str, Any]]:
    """Get metadata for the active model.

    Returns:
        AdapterResult[dict[str, Any]]: The result produced by the operation.
    """
    pass
get_selected_entities async
get_selected_entities() -> AdapterResult[list[dict[str, Any]]]

Report the faces/edges/vertices currently selected in the live UI.

Lets an agent see exactly what the user has clicked on in SolidWorks (e.g. "chamfer THIS face") instead of inferring it from a screenshot.

Returns:

Type Description
AdapterResult[list[dict[str, Any]]]

AdapterResult[list[dict[str, Any]]]: One descriptor per selected

AdapterResult[list[dict[str, Any]]]

entity. See the PyWin32 adapter's implementation for the field

AdapterResult[list[dict[str, Any]]]

set (varies by entity type).

Source code in src/solidworks_mcp/adapters/base.py
async def get_selected_entities(self) -> AdapterResult[list[dict[str, Any]]]:
    """Report the faces/edges/vertices currently selected in the live UI.

    Lets an agent see exactly what the user has clicked on in SolidWorks
    (e.g. "chamfer THIS face") instead of inferring it from a screenshot.

    Returns:
        AdapterResult[list[dict[str, Any]]]: One descriptor per selected
        entity. See the PyWin32 adapter's implementation for the field
        set (varies by entity type).
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="get_selected_entities is not implemented by this adapter",
    )
health_check abstractmethod async
health_check() -> AdapterHealth

Get adapter health status.

Returns:

Name Type Description
AdapterHealth AdapterHealth

The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def health_check(self) -> AdapterHealth:
    """Get adapter health status.

    Returns:
        AdapterHealth: The result produced by the operation.
    """
    pass
insert_bom_table async
insert_bom_table(view_name: str, template_path: str | None = None, bom_type: str = 'top_level_only', x_mm: float | None = None, y_mm: float | None = None) -> AdapterResult[dict[str, Any]]

Insert a BOM table anchored to an assembly drawing view.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def insert_bom_table(
    self,
    view_name: str,
    template_path: str | None = None,
    bom_type: str = "top_level_only",
    x_mm: float | None = None,
    y_mm: float | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Insert a BOM table anchored to an assembly drawing view.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="insert_bom_table is not implemented by this adapter",
    )
insert_component async
insert_component(file_path: str, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> AdapterResult[dict[str, Any]]

Insert a part or sub-assembly into the active assembly.

Parameters:

Name Type Description Default
file_path str

Absolute path to the .sldprt or .sldasm.

required
x float

X position in millimetres. Defaults to 0.0.

0.0
y float

Y position in millimetres. Defaults to 0.0.

0.0
z float

Z position in millimetres. Defaults to 0.0.

0.0

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Component name and counts, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def insert_component(
    self, file_path: str, x: float = 0.0, y: float = 0.0, z: float = 0.0
) -> AdapterResult[dict[str, Any]]:
    """Insert a part or sub-assembly into the active assembly.

    Args:
        file_path (str): Absolute path to the ``.sldprt`` or ``.sldasm``.
        x (float): X position in millimetres. Defaults to 0.0.
        y (float): Y position in millimetres. Defaults to 0.0.
        z (float): Z position in millimetres. Defaults to 0.0.

    Returns:
        AdapterResult[dict[str, Any]]: Component name and counts, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="insert_component is not implemented by this adapter",
    )
insert_model_dimensions async
insert_model_dimensions(view_name: str | None = None, include_hole_wizard: bool = True) -> AdapterResult[dict[str, Any]]

Bring model dimensions into drawing views.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def insert_model_dimensions(
    self,
    view_name: str | None = None,
    include_hole_wizard: bool = True,
) -> AdapterResult[dict[str, Any]]:
    """Bring model dimensions into drawing views.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="insert_model_dimensions is not implemented by this adapter",
    )
is_connected abstractmethod
is_connected() -> bool

Check if connected to SolidWorks.

Returns:

Name Type Description
bool bool

True if connected, otherwise False.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
def is_connected(self) -> bool:
    """Check if connected to SolidWorks.

    Returns:
        bool: True if connected, otherwise False.
    """
    pass
list_available_materials async
list_available_materials(search: str | None = None) -> AdapterResult[list[dict[str, str]]]

List materials from the configured material libraries.

Returns:

Type Description
AdapterResult[list[dict[str, str]]]

AdapterResult[list[dict[str, str]]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def list_available_materials(
    self,
    search: str | None = None,
) -> AdapterResult[list[dict[str, str]]]:
    """List materials from the configured material libraries.

    Returns:
        AdapterResult[list[dict[str, str]]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="list_available_materials is not implemented by this adapter",
    )
list_components async
list_components() -> AdapterResult[list[str]]

List the top-level components of the active assembly.

Returns:

Type Description
AdapterResult[list[str]]

AdapterResult[list[str]]: Component instance names, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def list_components(self) -> AdapterResult[list[str]]:
    """List the top-level components of the active assembly.

    Returns:
        AdapterResult[list[str]]: Component instance names, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="list_components is not implemented by this adapter",
    )
list_configurations abstractmethod async
list_configurations() -> AdapterResult[list[str]]

List configuration names for the active model.

Returns:

Type Description
AdapterResult[list[str]]

AdapterResult[list[str]]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def list_configurations(self) -> AdapterResult[list[str]]:
    """List configuration names for the active model.

    Returns:
        AdapterResult[list[str]]: The result produced by the operation.
    """
    pass
list_drawing_views async
list_drawing_views() -> AdapterResult[list[str]]

List the views on the active drawing.

Returns:

Type Description
AdapterResult[list[str]]

AdapterResult[list[str]]: View names, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def list_drawing_views(self) -> AdapterResult[list[str]]:
    """List the views on the active drawing.

    Returns:
        AdapterResult[list[str]]: View names, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="list_drawing_views is not implemented by this adapter",
    )
list_features abstractmethod async
list_features(include_suppressed: bool = False, max_assembly_depth: int = 2) -> AdapterResult[list[dict[str, Any]]]

List model features from the feature tree.

For a Part document, returns that document's own feature list, unchanged from prior behavior. For an Assembly document, returns a single flat list containing the assembly's own top-level features plus every resolved component's features, recursing into sub-assemblies up to max_assembly_depth. Every descriptor gains component, component_path, and component_parent keys: None for a document's own features (Part features, or an Assembly's top-level features), or the owning component's name/path for a component-derived feature. component_parent is the immediate parent component name when the component is nested inside a sub-assembly, otherwise None. A component that cannot be resolved (suppressed, lightweight-and-unloaded, missing file) is represented by one descriptor with type: "UnresolvedComponent" instead of being silently dropped.

Parameters:

Name Type Description Default
include_suppressed bool

The include suppressed value. Defaults to False. Applied independently to the assembly's own features and to each component's features.

False
max_assembly_depth int

How many levels of sub-assembly to recurse into. Defaults to 2. Ignored for Part documents. A component beyond the configured depth still appears in the result as a single descriptor (name + path), not expanded.

2

Returns:

Type Description
AdapterResult[list[dict[str, Any]]]

AdapterResult[list[dict[str, Any]]]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def list_features(
    self, include_suppressed: bool = False, max_assembly_depth: int = 2
) -> AdapterResult[list[dict[str, Any]]]:
    """List model features from the feature tree.

    For a Part document, returns that document's own feature list,
    unchanged from prior behavior. For an Assembly document, returns a
    single flat list containing the assembly's own top-level features
    plus every resolved component's features, recursing into
    sub-assemblies up to ``max_assembly_depth``. Every descriptor gains
    ``component``, ``component_path``, and ``component_parent`` keys:
    ``None`` for a document's own features (Part features, or an Assembly's
    top-level features), or the owning component's name/path for a
    component-derived feature. ``component_parent`` is the immediate parent
    component name when the component is nested inside a sub-assembly,
    otherwise ``None``. A component that cannot be resolved (suppressed,
    lightweight-and-unloaded, missing file) is represented by one descriptor
    with ``type: "UnresolvedComponent"`` instead of being silently dropped.

    Args:
        include_suppressed (bool): The include suppressed value. Defaults to False.
            Applied independently to the assembly's own features and to
            each component's features.
        max_assembly_depth (int): How many levels of sub-assembly to
            recurse into. Defaults to 2. Ignored for Part documents. A
            component beyond the configured depth still appears in the
            result as a single descriptor (name + path), not expanded.

    Returns:
        AdapterResult[list[dict[str, Any]]]: The result produced by the operation.
    """
    pass
list_model_dimensions async
list_model_dimensions(feature_name: str | None = None) -> AdapterResult[list[dict[str, Any]]]

List every dimension in the active part or assembly.

Returns:

Type Description
AdapterResult[list[dict[str, Any]]]

AdapterResult[list[dict[str, Any]]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def list_model_dimensions(
    self,
    feature_name: str | None = None,
) -> AdapterResult[list[dict[str, Any]]]:
    """List every dimension in the active part or assembly.

    Returns:
        AdapterResult[list[dict[str, Any]]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="list_model_dimensions is not implemented by this adapter",
    )
list_open_documents async
list_open_documents() -> AdapterResult[list[dict[str, Any]]]

Enumerate every document currently open in SolidWorks.

Returns:

Type Description
AdapterResult[list[dict[str, Any]]]

AdapterResult[list[dict[str, Any]]]: One entry per open document

AdapterResult[list[dict[str, Any]]]

(title, path, type, is_active), or error.

Source code in src/solidworks_mcp/adapters/base.py
async def list_open_documents(self) -> AdapterResult[list[dict[str, Any]]]:
    """Enumerate every document currently open in SolidWorks.

    Returns:
        AdapterResult[list[dict[str, Any]]]: One entry per open document
        (``title``, ``path``, ``type``, ``is_active``), or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="list_open_documents is not implemented by this adapter",
    )
measure_entities async
measure_entities(entities: list[str]) -> AdapterResult[dict[str, Any]]

Measure one or two selected entities.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def measure_entities(
    self,
    entities: list[str],
) -> AdapterResult[dict[str, Any]]:
    """Measure one or two selected entities.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="measure_entities is not implemented by this adapter",
    )
mirror_feature async
mirror_feature(features: list[str], mirror_plane: str, merge: bool = True, mirror_bodies: bool = True) -> AdapterResult[dict[str, Any]]

Mirror solid bodies or features about a plane.

Parameters:

Name Type Description Default
features list[str]

Body or feature names to mirror.

required
mirror_plane str

Plane name to mirror about.

required
merge bool

Merge the mirrored result with the original. Defaults to True.

True
mirror_bodies bool

Mirror whole bodies rather than features. Defaults to True.

True

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The mirror feature's name, inputs and volume

AdapterResult[dict[str, Any]]

before/after, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def mirror_feature(
    self,
    features: list[str],
    mirror_plane: str,
    merge: bool = True,
    mirror_bodies: bool = True,
) -> AdapterResult[dict[str, Any]]:
    """Mirror solid bodies or features about a plane.

    Args:
        features (list[str]): Body or feature names to mirror.
        mirror_plane (str): Plane name to mirror about.
        merge (bool): Merge the mirrored result with the original. Defaults to True.
        mirror_bodies (bool): Mirror whole bodies rather than features. Defaults to True.

    Returns:
        AdapterResult[dict[str, Any]]: The mirror feature's name, inputs and volume
        before/after, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="mirror_feature is not implemented by this adapter",
    )
open_model abstractmethod async
open_model(file_path: str) -> AdapterResult[SolidWorksModel]

Open a SolidWorks model (part, assembly, or drawing).

Parameters:

Name Type Description Default
file_path str

Path to the target file.

required

Returns:

Type Description
AdapterResult[SolidWorksModel]

AdapterResult[SolidWorksModel]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def open_model(self, file_path: str) -> AdapterResult[SolidWorksModel]:
    """Open a SolidWorks model (part, assembly, or drawing).

    Args:
        file_path (str): Path to the target file.

    Returns:
        AdapterResult[SolidWorksModel]: The result produced by the operation.
    """
    pass
pattern_circular async
pattern_circular(features: list[str], axis: str, count: int, angle: float = 360.0, equal_spacing: bool = True) -> AdapterResult[dict[str, Any]]

Pattern features around an axis.

Parameters:

Name Type Description Default
features list[str]

Names of the features to pattern.

required
axis str

Name of the axis to rotate about.

required
count int

Total number of instances including the original.

required
angle float

Total angle in degrees to spread them over. Defaults to 360.0.

360.0
equal_spacing bool

Space instances evenly across angle. Defaults to True.

True

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: What was patterned and the volume

AdapterResult[dict[str, Any]]

before/after, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def pattern_circular(
    self,
    features: list[str],
    axis: str,
    count: int,
    angle: float = 360.0,
    equal_spacing: bool = True,
) -> AdapterResult[dict[str, Any]]:
    """Pattern features around an axis.

    Args:
        features (list[str]): Names of the features to pattern.
        axis (str): Name of the axis to rotate about.
        count (int): Total number of instances including the original.
        angle (float): Total angle in degrees to spread them over. Defaults to 360.0.
        equal_spacing (bool): Space instances evenly across ``angle``. Defaults to True.

    Returns:
        AdapterResult[dict[str, Any]]: What was patterned and the volume
        before/after, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="pattern_circular is not implemented by this adapter",
    )
rebuild_model async
rebuild_model(top_level_only: bool = False) -> AdapterResult[dict[str, Any]]

Force a rebuild and report per-feature rebuild errors.

Parameters:

Name Type Description Default
top_level_only bool

Rebuild only the top level of an assembly. Defaults to False (full rebuild).

False

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: rebuilt, top_level_only,

AdapterResult[dict[str, Any]]

errors (one entry per failing feature with feature,

AdapterResult[dict[str, Any]]

type, code, code_name, severity, description,

AdapterResult[dict[str, Any]]

parents, hint), error_count and warning_count.

AdapterResult[dict[str, Any]]

ERROR (still carrying data) when any error-severity entry

AdapterResult[dict[str, Any]]

remains.

Source code in src/solidworks_mcp/adapters/base.py
async def rebuild_model(
    self, top_level_only: bool = False
) -> AdapterResult[dict[str, Any]]:
    """Force a rebuild and report per-feature rebuild errors.

    Args:
        top_level_only (bool): Rebuild only the top level of an assembly.
            Defaults to False (full rebuild).

    Returns:
        AdapterResult[dict[str, Any]]: ``rebuilt``, ``top_level_only``,
        ``errors`` (one entry per failing feature with ``feature``,
        ``type``, ``code``, ``code_name``, ``severity``, ``description``,
        ``parents``, ``hint``), ``error_count`` and ``warning_count``.
        ERROR (still carrying ``data``) when any error-severity entry
        remains.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="rebuild_model is not implemented by this adapter",
    )
rename_feature async
rename_feature(old_name: str, new_name: str) -> AdapterResult[dict[str, Any]]

Rename an existing feature on the feature tree.

Parameters:

Name Type Description Default
old_name str

Current feature name.

required
new_name str

New feature name.

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The old and new names, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def rename_feature(
    self, old_name: str, new_name: str
) -> AdapterResult[dict[str, Any]]:
    """Rename an existing feature on the feature tree.

    Args:
        old_name (str): Current feature name.
        new_name (str): New feature name.

    Returns:
        AdapterResult[dict[str, Any]]: The old and new names, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="rename_feature is not implemented by this adapter",
    )
reset_circuit_breakers async
reset_circuit_breakers(operation: str | None = None) -> AdapterResult[dict[str, list[str]]]

Re-open operations a circuit breaker paused.

An adapter without a circuit breaker has nothing paused; the breaker and the connection pool override this.

Parameters:

Name Type Description Default
operation str | None

The operation to reset; None resets every one.

None

Returns:

Type Description
AdapterResult[dict[str, list[str]]]

AdapterResult[dict[str, list[str]]]: reset, the operations that were paused.

Source code in src/solidworks_mcp/adapters/base.py
async def reset_circuit_breakers(
    self, operation: str | None = None
) -> AdapterResult[dict[str, list[str]]]:
    """Re-open operations a circuit breaker paused.

    An adapter without a circuit breaker has nothing paused; the breaker
    and the connection pool override this.

    Args:
        operation: The operation to reset; ``None`` resets every one.

    Returns:
        AdapterResult[dict[str, list[str]]]: ``reset``, the operations that were paused.
    """
    return AdapterResult(status=AdapterResultStatus.SUCCESS, data={"reset": []})
save_body_as_part async
save_body_as_part(body_name: str, file_path: str) -> AdapterResult[dict[str, Any]]

Extract one solid body from the active multibody part to a new file.

Parameters:

Name Type Description Default
body_name str

Name of a solid body in the active part.

required
file_path str

Absolute path for the new .sldprt.

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The body, the written path, and the

AdapterResult[dict[str, Any]]

solid-body names found, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def save_body_as_part(
    self, body_name: str, file_path: str
) -> AdapterResult[dict[str, Any]]:
    """Extract one solid body from the active multibody part to a new file.

    Args:
        body_name (str): Name of a solid body in the active part.
        file_path (str): Absolute path for the new ``.sldprt``.

    Returns:
        AdapterResult[dict[str, Any]]: The body, the written path, and the
        solid-body names found, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="save_body_as_part is not implemented by this adapter",
    )
save_file async
save_file(file_path: str | None = None) -> AdapterResult[Any]

Save the active model to the existing path or the provided path.

Parameters:

Name Type Description Default
file_path str | None

Path to the target file. Defaults to None.

None

Returns:

Type Description
AdapterResult[Any]

AdapterResult[Any]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def save_file(self, file_path: str | None = None) -> AdapterResult[Any]:
    """Save the active model to the existing path or the provided path.

    Args:
        file_path (str | None): Path to the target file. Defaults to None.

    Returns:
        AdapterResult[Any]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="save_file is not implemented by this adapter",
    )
select_face_edges async
select_face_edges(point: list[float] | None = None, side: str | None = None, plane: str | None = None, edge_type: str = 'all', append: bool = False) -> AdapterResult[dict[str, Any]]

Multi-select every edge bounding one face of the active part.

Exactly one of point/side/plane identifies the face.

Parameters:

Name Type Description Default
point list[float] | None

[x, y, z] in mm on the face.

None
side str | None

+X..-Z or top/bottom/front/back/ right/left; the furthest planar face facing that way.

None
plane str | None

Reference plane name; the body face(s) lying on it.

None
edge_type str

all, linear or circular.

'all'
append bool

Add to the current selection. Defaults to False.

False

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: face (or faces), edges

AdapterResult[dict[str, Any]]

(one descriptor per selected edge) and selection_count.

Source code in src/solidworks_mcp/adapters/base.py
async def select_face_edges(
    self,
    point: list[float] | None = None,
    side: str | None = None,
    plane: str | None = None,
    edge_type: str = "all",
    append: bool = False,
) -> AdapterResult[dict[str, Any]]:
    """Multi-select every edge bounding one face of the active part.

    Exactly one of ``point``/``side``/``plane`` identifies the face.

    Args:
        point (list[float] | None): ``[x, y, z]`` in mm on the face.
        side (str | None): ``+X``..``-Z`` or ``top/bottom/front/back/
            right/left``; the furthest planar face facing that way.
        plane (str | None): Reference plane name; the body face(s) lying
            on it.
        edge_type (str): ``all``, ``linear`` or ``circular``.
        append (bool): Add to the current selection. Defaults to False.

    Returns:
        AdapterResult[dict[str, Any]]: ``face`` (or ``faces``), ``edges``
        (one descriptor per selected edge) and ``selection_count``.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="select_face_edges is not implemented by this adapter",
    )
select_feature async
select_feature(feature_name: str, append: bool = False) -> AdapterResult[dict[str, Any]]

Select a named feature, sketch, plane or component.

Parameters:

Name Type Description Default
feature_name str

The feature name, optionally @document qualified.

required
append bool

Add to the current selection instead of replacing it. Defaults to False.

False

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: On success selected (True),

AdapterResult[dict[str, Any]]

feature_name, selected_name, entity_type and

AdapterResult[dict[str, Any]]

selection_count. ERROR when nothing could be selected - never

AdapterResult[dict[str, Any]]

SUCCESS with selected: False.

Source code in src/solidworks_mcp/adapters/base.py
async def select_feature(
    self, feature_name: str, append: bool = False
) -> AdapterResult[dict[str, Any]]:
    """Select a named feature, sketch, plane or component.

    Args:
        feature_name (str): The feature name, optionally ``@document``
            qualified.
        append (bool): Add to the current selection instead of replacing
            it. Defaults to False.

    Returns:
        AdapterResult[dict[str, Any]]: On success ``selected`` (True),
        ``feature_name``, ``selected_name``, ``entity_type`` and
        ``selection_count``. ERROR when nothing could be selected - never
        SUCCESS with ``selected: False``.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="select_feature is not implemented by this adapter",
    )
set_component_state async
set_component_state(component: str, fixed: bool | None = None, flexible: bool | None = None) -> AdapterResult[dict[str, Any]]

Fix or float a component, and make a sub-assembly rigid or flexible.

Parameters:

Name Type Description Default
component str

Instance name, as list_components reports it.

required
fixed bool | None

True fixes it, False floats it.

None
flexible bool | None

True flexible, False rigid.

None

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The state before and after, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def set_component_state(
    self,
    component: str,
    fixed: bool | None = None,
    flexible: bool | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Fix or float a component, and make a sub-assembly rigid or flexible.

    Args:
        component (str): Instance name, as ``list_components`` reports it.
        fixed (bool | None): True fixes it, False floats it.
        flexible (bool | None): True flexible, False rigid.

    Returns:
        AdapterResult[dict[str, Any]]: The state before and after, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="set_component_state is not implemented by this adapter",
    )
set_custom_property async
set_custom_property(name: str, value: str, configuration: str | None = None) -> AdapterResult[dict[str, Any]]

Create or overwrite one custom property.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def set_custom_property(
    self,
    name: str,
    value: str,
    configuration: str | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Create or overwrite one custom property.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="set_custom_property is not implemented by this adapter",
    )
set_dimension abstractmethod async
set_dimension(name: str, value: float) -> AdapterResult[None]

Set the value of a dimension.

Parameters:

Name Type Description Default
name str

The name value.

required
value float

The value value.

required

Returns:

Type Description
AdapterResult[None]

AdapterResult[None]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
@abstractmethod
async def set_dimension(self, name: str, value: float) -> AdapterResult[None]:
    """Set the value of a dimension.

    Args:
        name (str): The name value.
        value (float): The value value.

    Returns:
        AdapterResult[None]: The result produced by the operation.
    """
    pass
set_material async
set_material(material_name: str, database: str | None = None, configuration: str | None = None) -> AdapterResult[dict[str, Any]]

Assign a material to the active part.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def set_material(
    self,
    material_name: str,
    database: str | None = None,
    configuration: str | None = None,
) -> AdapterResult[dict[str, Any]]:
    """Assign a material to the active part.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="set_material is not implemented by this adapter",
    )
set_sheet_scale async
set_sheet_scale(numerator: float, denominator: float) -> AdapterResult[dict[str, Any]]

Set the active drawing sheet's scale.

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Error unless the adapter implements it.

Source code in src/solidworks_mcp/adapters/base.py
async def set_sheet_scale(
    self,
    numerator: float,
    denominator: float,
) -> AdapterResult[dict[str, Any]]:
    """Set the active drawing sheet's scale.

    Returns:
        AdapterResult[dict[str, Any]]: Error unless the adapter implements it.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="set_sheet_scale is not implemented by this adapter",
    )
set_units async
set_units(unit_system: str) -> AdapterResult[dict[str, Any]]

Set the active document's linear unit system.

Parameters:

Name Type Description Default
unit_system str

One of mm, cm, m, in, ft.

required

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: What was applied, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def set_units(self, unit_system: str) -> AdapterResult[dict[str, Any]]:
    """Set the active document's linear unit system.

    Args:
        unit_system (str): One of ``mm``, ``cm``, ``m``, ``in``, ``ft``.

    Returns:
        AdapterResult[dict[str, Any]]: What was applied, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="set_units is not implemented by this adapter",
    )
sketch_circular_pattern async
sketch_circular_pattern(entities: list[str], angle: float, count: int) -> AdapterResult[str]

Create a circular pattern of sketch entities around the sketch origin.

The rotation axis is always the sketch origin — SW's CreateCircularSketchStepAndRepeat has no pattern-centre parameter and derives the axis from the seed's geometry. Place the seed entity at the desired radius from the origin.

Parameters:

Name Type Description Default
entities list[str]

The entities value.

required
angle float

The angle value.

required
count int

The count value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def sketch_circular_pattern(
    self,
    entities: list[str],
    angle: float,
    count: int,
) -> AdapterResult[str]:
    """Create a circular pattern of sketch entities around the sketch origin.

    The rotation axis is always the sketch origin — SW's
    ``CreateCircularSketchStepAndRepeat`` has no pattern-centre
    parameter and derives the axis from the seed's geometry. Place
    the seed entity at the desired radius from the origin.

    Args:
        entities (list[str]): The entities value.
        angle (float): The angle value.
        count (int): The count value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="sketch_circular_pattern is not implemented by this adapter",
    )
sketch_linear_pattern async
sketch_linear_pattern(entities: list[str], direction_x: float, direction_y: float, spacing: float, count: int) -> AdapterResult[str]

Create a linear pattern of sketch entities.

Parameters:

Name Type Description Default
entities list[str]

The entities value.

required
direction_x float

The direction x value.

required
direction_y float

The direction y value.

required
spacing float

The spacing value.

required
count int

The count value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def sketch_linear_pattern(
    self,
    entities: list[str],
    direction_x: float,
    direction_y: float,
    spacing: float,
    count: int,
) -> AdapterResult[str]:
    """Create a linear pattern of sketch entities.

    Args:
        entities (list[str]): The entities value.
        direction_x (float): The direction x value.
        direction_y (float): The direction y value.
        spacing (float): The spacing value.
        count (int): The count value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="sketch_linear_pattern is not implemented by this adapter",
    )
sketch_mirror async
sketch_mirror(entities: list[str], mirror_line: str) -> AdapterResult[str]

Mirror sketch entities about a mirror line.

Parameters:

Name Type Description Default
entities list[str]

The entities value.

required
mirror_line str

The mirror line value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def sketch_mirror(
    self, entities: list[str], mirror_line: str
) -> AdapterResult[str]:
    """Mirror sketch entities about a mirror line.

    Args:
        entities (list[str]): The entities value.
        mirror_line (str): The mirror line value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="sketch_mirror is not implemented by this adapter",
    )
sketch_offset async
sketch_offset(entities: list[str], offset_distance: float, reverse_direction: bool) -> AdapterResult[str]

Offset sketch entities.

Parameters:

Name Type Description Default
entities list[str]

The entities value.

required
offset_distance float

The offset distance value.

required
reverse_direction bool

The reverse direction value.

required

Returns:

Type Description
AdapterResult[str]

AdapterResult[str]: The result produced by the operation.

Source code in src/solidworks_mcp/adapters/base.py
async def sketch_offset(
    self,
    entities: list[str],
    offset_distance: float,
    reverse_direction: bool,
) -> AdapterResult[str]:
    """Offset sketch entities.

    Args:
        entities (list[str]): The entities value.
        offset_distance (float): The offset distance value.
        reverse_direction (bool): The reverse direction value.

    Returns:
        AdapterResult[str]: The result produced by the operation.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="sketch_offset is not implemented by this adapter",
    )
suppress_feature async
suppress_feature(name: str, suppress: bool = True) -> AdapterResult[dict[str, Any]]

Suppress or unsuppress a named feature.

Parameters:

Name Type Description Default
name str

Feature name.

required
suppress bool

True to suppress, False to unsuppress.

True

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: The resulting state, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def suppress_feature(
    self, name: str, suppress: bool = True
) -> AdapterResult[dict[str, Any]]:
    """Suppress or unsuppress a named feature.

    Args:
        name (str): Feature name.
        suppress (bool): True to suppress, False to unsuppress.

    Returns:
        AdapterResult[dict[str, Any]]: The resulting state, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="suppress_feature is not implemented by this adapter",
    )
undo async
undo(count: int = 1) -> AdapterResult[dict[str, Any]]

Undo the last operations in the active model.

Parameters:

Name Type Description Default
count int

Number of steps to undo.

1

Returns:

Type Description
AdapterResult[dict[str, Any]]

AdapterResult[dict[str, Any]]: Whether the tree changed, or error.

Source code in src/solidworks_mcp/adapters/base.py
async def undo(self, count: int = 1) -> AdapterResult[dict[str, Any]]:
    """Undo the last operations in the active model.

    Args:
        count (int): Number of steps to undo.

    Returns:
        AdapterResult[dict[str, Any]]: Whether the tree changed, or error.
    """
    return AdapterResult(
        status=AdapterResultStatus.ERROR,
        error="undo is not implemented by this adapter",
    )
update_metrics
update_metrics(operation_time: float, success: bool) -> None

Update adapter metrics.

Parameters:

Name Type Description Default
operation_time float

The operation time value.

required
success bool

The success value.

required

Returns:

Name Type Description
None None

None.

Source code in src/solidworks_mcp/adapters/base.py
def update_metrics(self, operation_time: float, success: bool) -> None:
    """Update adapter metrics.

    Args:
        operation_time (float): The operation time value.
        success (bool): The success value.

    Returns:
        None: None.
    """
    self._metrics["operations_count"] += 1
    if not success:
        self._metrics["errors_count"] += 1

    # Update average response time
    current_avg = self._metrics["average_response_time"]
    count = self._metrics["operations_count"]
    self._metrics["average_response_time"] = (
        current_avg * (count - 1) + operation_time
    ) / count

SuppressFeatureInput

Bases: CompatInput

Input schema for suppressing or unsuppressing a feature.

Attributes:

Name Type Description
name str

Feature name to toggle.

suppress bool

True to suppress, False to unsuppress.

SweepParameters

Bases: BaseModel

Parameters for sweep operations.

Attributes:

Name Type Description
merge_result bool

The merge result value.

path str

The path value.

twist_along_path bool

The twist along path value.

twist_angle float

The twist angle value.

UndoInput

Bases: CompatInput

Input schema for undoing model operations.

Attributes:

Name Type Description
count int

Number of operations to undo.

Functions:

_attach_measured_change

_attach_measured_change(reply: dict[str, Any], before: AdapterResult[dict[str, Any]] | None, after: AdapterResult[dict[str, Any]] | None) -> dict[str, Any]

Add the feature's measured volume and size change to its reply.

Best-effort: when the "before" read failed (or the adapter has none) the reply is returned unchanged; anything else unmeasurable is None with a note. A feature that succeeded without changing the volume gets a warning, since that is how SolidWorks reports a silent no-op.

Parameters:

Name Type Description Default
reply dict[str, Any]

The feature tool's success reply.

required
before AdapterResult[dict[str, Any]] | None

Summary read before the feature.

required
after AdapterResult[dict[str, Any]] | None

Summary read after the feature.

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: reply, with measured_change when measurable.

Source code in src/solidworks_mcp/tools/modeling.py
def _attach_measured_change(
    reply: dict[str, Any],
    before: AdapterResult[dict[str, Any]] | None,
    after: AdapterResult[dict[str, Any]] | None,
) -> dict[str, Any]:
    """Add the feature's measured volume and size change to its reply.

    Best-effort: when the "before" read failed (or the adapter has none) the
    reply is returned unchanged; anything else unmeasurable is ``None`` with a
    ``note``. A feature that succeeded without changing the volume gets a
    ``warning``, since that is how SolidWorks reports a silent no-op.

    Args:
        reply: The feature tool's success reply.
        before: Summary read before the feature.
        after: Summary read after the feature.

    Returns:
        dict[str, Any]: ``reply``, with ``measured_change`` when measurable.
    """
    if before is None or not before.is_success:
        return reply
    old = before.data or {}
    new = (after.data or {}) if after is not None and after.is_success else None
    volume_before = old.get("volume_mm3")
    volume_after = new.get("volume_mm3") if new is not None else None
    numbers = (int, float)
    delta = (
        round(volume_after - volume_before, 4)
        if isinstance(volume_before, numbers) and isinstance(volume_after, numbers)
        else None
    )
    change: dict[str, Any] = {
        "volume_before_mm3": volume_before,
        "volume_after_mm3": volume_after,
        "volume_delta_mm3": delta,
        "bounding_box_before_mm": _box_size(old),
        "bounding_box_after_mm": _box_size(new) if new is not None else None,
        "solid_body_count_before": old.get("solid_body_count"),
        "solid_body_count_after": (
            new.get("solid_body_count") if new is not None else None
        ),
    }
    if new is None:
        error = after.error if after is not None else None
        change["note"] = f"Could not read the model after the feature: {error}"
    elif delta is None:
        change["note"] = "Volume is not determinable with the active adapter"
    reply["measured_change"] = change
    if delta == 0:
        reply["warning"] = (
            "The feature reported success but changed no volume; SolidWorks "
            "may have accepted it without doing anything. Check the sketch, "
            "the direction and the depth."
        )
    return reply

_box_size

_box_size(summary: dict[str, Any]) -> Any

Return a summary's bounding-box size [x, y, z], or None.

Source code in src/solidworks_mcp/tools/modeling.py
def _box_size(summary: dict[str, Any]) -> Any:
    """Return a summary's bounding-box size ``[x, y, z]``, or ``None``."""
    box = summary.get("bounding_box_mm")
    return box.get("size") if isinstance(box, dict) else None

_read_summary async

_read_summary(adapter: Any) -> AdapterResult[dict[str, Any]] | None

Read the geometry summary, or None if the adapter has no such read.

Parameters:

Name Type Description Default
adapter Any

The active adapter.

required

Returns:

Type Description
AdapterResult[dict[str, Any]] | None

AdapterResult[dict[str, Any]] | None: The summary result.

Source code in src/solidworks_mcp/tools/modeling.py
async def _read_summary(adapter: Any) -> AdapterResult[dict[str, Any]] | None:
    """Read the geometry summary, or ``None`` if the adapter has no such read.

    Args:
        adapter: The active adapter.

    Returns:
        AdapterResult[dict[str, Any]] | None: The summary result.
    """
    reader = getattr(adapter, "get_model_geometry_summary", None)
    if reader is None:
        return None
    result: AdapterResult[dict[str, Any]] = await reader()
    return result

_result_value

_result_value(data: Any, *keys: str, default: Any = None) -> Any

Build internal result value.

Parameters:

Name Type Description Default
data Any

The data value.

required
*keys str

Additional positional arguments forwarded to the call.

()
default Any

Fallback value returned when the operation fails. Defaults to None.

None

Returns:

Name Type Description
Any Any

The result produced by the operation.

Source code in src/solidworks_mcp/tools/modeling.py
def _result_value(data: Any, *keys: str, default: Any = None) -> Any:
    """Build internal result value.

    Args:
        data (Any): The data value.
        *keys (str): Additional positional arguments forwarded to the call.
        default (Any): Fallback value returned when the operation fails. Defaults to None.

    Returns:
        Any: The result produced by the operation.
    """
    if isinstance(data, dict):
        for key in keys:
            if key in data and data[key] is not None:
                return data[key]
        return default

    for key in keys:
        if hasattr(data, key):
            value = getattr(data, key)
            if value is not None:
                return value
    return default

normalize_input

normalize_input(input_data: Any, model_type: type[TModel]) -> TModel

Validate input_data as model_type.

Parameters:

Name Type Description Default
input_data Any

A model_type instance, a mapping of its fields, another pydantic model (converted through model_dump), or None for a tool whose fields all have defaults.

required
model_type type[TModel]

The tool's pydantic input model.

required

Returns:

Name Type Description
TModel TModel

The validated model.

Raises:

Type Description
InvalidInputError

Naming the offending field(s).

Source code in src/solidworks_mcp/tools/tool_boundary.py
def normalize_input[TModel: BaseModel](
    input_data: Any, model_type: type[TModel]
) -> TModel:
    """Validate ``input_data`` as ``model_type``.

    Args:
        input_data: A ``model_type`` instance, a mapping of its fields, another
            pydantic model (converted through ``model_dump``), or ``None`` for
            a tool whose fields all have defaults.
        model_type: The tool's pydantic input model.

    Returns:
        TModel: The validated model.

    Raises:
        InvalidInputError: Naming the offending field(s).
    """
    if isinstance(input_data, model_type):
        return input_data
    if input_data is None:
        input_data = {}
    elif not isinstance(input_data, dict) and hasattr(input_data, "model_dump"):
        input_data = input_data.model_dump()
    try:
        return model_type.model_validate(input_data)
    except ValidationError as exc:  # also wraps ValueErrors from validators
        raise InvalidInputError(describe_validation_error(exc)) from exc

register_modeling_tools async

register_modeling_tools(mcp: FastMCP, adapter: SolidWorksAdapter, config: dict[str, Any]) -> int

Register modeling tools with FastMCP.

Registers comprehensive modeling tools for SolidWorks automation including model creation, feature creation, and model management operations.

Parameters:

Name Type Description Default
mcp FastMCP

The mcp value.

required
adapter SolidWorksAdapter

Adapter instance used for the operation.

required
config dict[str, Any]

Configuration values for the operation.

required

Returns:

Name Type Description
int int

The computed numeric result.

Example
from solidworks_mcp.tools.modeling import register_modeling_tools

tool_count = await register_modeling_tools(mcp, adapter, config)
print(f"Registered {tool_count} modeling tools")
Source code in src/solidworks_mcp/tools/modeling.py
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
async def register_modeling_tools(
    mcp: FastMCP, adapter: SolidWorksAdapter, config: dict[str, Any]
) -> int:
    """Register modeling tools with FastMCP.

    Registers comprehensive modeling tools for SolidWorks automation including model
    creation, feature creation, and model management operations.

    Args:
        mcp (FastMCP): The mcp value.
        adapter (SolidWorksAdapter): Adapter instance used for the operation.
        config (dict[str, Any]): Configuration values for the operation.

    Returns:
        int: The computed numeric result.

    Example:
                        ```python
                        from solidworks_mcp.tools.modeling import register_modeling_tools

                        tool_count = await register_modeling_tools(mcp, adapter, config)
                        print(f"Registered {tool_count} modeling tools")
                        ```
    """
    mcp = with_tool_boundary(mcp)
    tool_count = 0

    @mcp.tool()
    async def open_model(input_data: OpenModelInput) -> dict[str, Any]:
        """Open a part, assembly or drawing from disk and make it the active document.

        Use it to start work on an existing file. To switch to a document that is
        already open, use `activate_document`. Needs: the file on disk (a vault file
        must be checked out). Changes: opens the document; nothing is written. Returns:
        `model` with `title`, `type`, `path` and `configuration`.

        Args:
            input_data: The file. `file_path` (.sldprt, .sldasm or .slddrw) is
                required.

        Returns:
            dict[str, Any]: The opened document.
        """
        input_data = normalize_input(input_data, OpenModelInput)
        result = await adapter.open_model(input_data.file_path)

        require_success(result, context="Failed to open model")
        model = result.data
        title = _result_value(model, "title", "name", default=input_data.file_path)
        model_type = _result_value(model, "type", default="Part")
        path = _result_value(model, "path", "file_path", default=input_data.file_path)
        configuration = _result_value(model, "configuration", default="Default")
        return {
            "status": "success",
            "message": f"Opened {model_type}: {title}",
            "model": {
                "title": title,
                "name": title,
                "type": model_type,
                "path": path,
                "configuration": configuration,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_part(input_data: CreatePartInput) -> dict[str, Any]:
        """Create a new, empty part document and make it active, ready for `create_sketch`.

        Uses `template` (a .prtdot) or the default part template, then sets `units` if
        given, and assigns `material` if given. The part is not saved until
        `save_part`. Needs: SolidWorks running. Changes: opens a new part document.
        Returns: `part` with `name`, `units`, `template` and `material` (the one
        assigned, or null), plus a `warning` when the material couldn't be assigned;
        the part is created either way.

        Args:
            input_data: The part. `name` is required but only a label: the reply
                gives SolidWorks' own name (Part1, ...); `template`, `units` (mm, cm, m, in, ft) and
                `material` (a name from `list_available_materials`) are optional.

        Returns:
            dict[str, Any]: The new part.
        """
        input_data = normalize_input(input_data, CreatePartInput)
        result = await adapter.create_part(
            input_data.name, input_data.units, input_data.template
        )

        require_success(result, context="Failed to create part")
        model = result.data
        part_name = _result_value(model, "name", default=input_data.name)
        units = _result_value(model, "units", default=input_data.units or "mm")
        material = None
        warning = None
        if input_data.material:
            assigned = await adapter.set_material(input_data.material)
            if assigned.is_success:
                material = input_data.material
            else:
                warning = (
                    f"The part was created without a material: "
                    f"'{input_data.material}' could not be assigned "
                    f"({assigned.error}). Use list_available_materials, then "
                    "set_material."
                )
        reply: dict[str, Any] = {
            "status": "success",
            "message": f"Created new part: {part_name}",
            "part": {
                "name": part_name,
                "units": units,
                "material": material,
                "template": input_data.template,
            },
            "execution_time": result.execution_time,
        }
        if warning:
            reply["warning"] = warning
        return reply

    @mcp.tool()
    async def create_assembly(input_data: CreateAssemblyInput) -> dict[str, Any]:
        """Create a new, empty assembly document and make it active, ready for `insert_component`.

        Uses `template` (an .asmdot) or the default assembly template. It is not saved
        until `save_assembly`. Needs: SolidWorks running. Changes: opens a new assembly
        document. Returns: `assembly` with `name` and `template`. Then call
        `insert_component` for each part.

        Args:
            input_data: The assembly. `name` is required but only a label: the
                reply gives SolidWorks' own name (Assem1, ...); `template` has a
                default.

        Returns:
            dict[str, Any]: The new assembly.
        """
        input_data = normalize_input(input_data, CreateAssemblyInput)
        result = await adapter.create_assembly(input_data.name, input_data.template)

        require_success(result, context="Failed to create assembly")
        model = result.data
        assembly_name = _result_value(model, "name", default=input_data.name)
        return {
            "status": "success",
            "message": f"Created new assembly: {assembly_name}",
            "assembly": {
                "name": assembly_name,
                "template": input_data.template,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_drawing(input_data: CreateDrawingInput) -> dict[str, Any]:
        """Create a new, empty drawing document and make it active.

        Uses `template` (a .drwdot) or the default drawing template. Then place views
        with `create_drawing_view`; for a whole drawing from a model in one call, use
        `generate_drawing_package` instead. Needs: SolidWorks running. Changes: opens a
        new drawing document. Returns: `drawing` with `name` and `template`.

        Args:
            input_data: The drawing. `name` is required but only a label: the
                reply gives SolidWorks' own name (Draw1, ...); `template` has a
                default.

        Returns:
            dict[str, Any]: The new drawing.
        """
        input_data = normalize_input(input_data, CreateDrawingInput)
        result = await adapter.create_drawing(input_data.name, input_data.template)

        require_success(result, context="Failed to create drawing")
        model = result.data
        drawing_name = _result_value(model, "name", default=input_data.name)
        return {
            "status": "success",
            "message": f"Created new drawing: {drawing_name}",
            "drawing": {
                "name": drawing_name,
                "template": input_data.template,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def close_model(input_data: CloseModelInput) -> dict[str, Any]:
        """Close the active document, saving it first only if asked.

        Use it when you are done with a document. Unsaved changes are lost unless `save`
        is on. Needs: an open, active document. Changes: closes the document, and with
        `save` writes it first. Returns: `saved`, whether a save was asked for.

        Args:
            input_data: The close. Nothing is required: `save` is off.

        Returns:
            dict[str, Any]: The close result.
        """
        input_data = normalize_input(input_data, CloseModelInput)
        result = await adapter.close_model(input_data.save)

        require_success(result, context="Failed to close model")
        return {
            "status": "success",
            "message": "Model closed successfully",
            "saved": input_data.save,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_extrusion(input_data: CreateExtrusionInput) -> dict[str, Any]:
        """Extrude the sketch you just closed into a solid boss, added to the active part.

        Use it after `exit_sketch`; to remove material, use `create_cut_extrude`. It
        extrudes the sketch `sketch_name` names, or the one `exit_sketch` closed last;
        a name that isn't in the feature tree fails before anything is built. End
        conditions: Blind (default), MidPlane, ThroughAll, UpToNext; `both_directions`
        means MidPlane. With `thin_feature` and `thin_thickness` it makes a wall from the
        sketch's outline, and an open chain works (a bent plate from its centreline).
        Needs: an open part and a closed profile (open is fine when thin). Changes:
        adds a Boss-Extrude feature. Returns: `extrusion` (`name`, `sketch` when one
        was named, `depth`, the `end_condition` SolidWorks used, `both_directions`,
        and `thin` when thin) and
        `measured_change` (volume, bounding box and solid-body count before and after;
        left out when the model can't be read).

        Args:
            input_data: The extrusion. `depth` (mm) is required; `sketch_name`,
                `end_condition`, `both_directions`, `reverse_direction`,
                `draft_angle`, `thin_feature`/`thin_thickness` and `merge_result`
                have defaults.

        Returns:
            dict[str, Any]: The created feature.
        """
        input_data = normalize_input(input_data, CreateExtrusionInput)
        # Convert input to ExtrusionParameters
        params = ExtrusionParameters(
            depth=input_data.depth,
            draft_angle=input_data.draft_angle,
            reverse_direction=input_data.reverse_direction,
            both_directions=input_data.both_directions,
            thin_feature=input_data.thin_feature,
            thin_thickness=input_data.thin_thickness,
            thin_side=input_data.thin_side,
            end_condition=input_data.end_condition,
            merge_result=input_data.merge_result,
            feature_scope=False,
            auto_select=True,
            sketch_name=input_data.sketch_name,
        )

        before = await _read_summary(adapter)
        result = await adapter.create_extrusion(params)

        require_success(result, context="Failed to create extrusion")
        after = await _read_summary(adapter) if before is not None else None
        feature = result.data
        name = _result_value(feature, "feature_name", "name", default="Extrusion")
        applied = _result_value(feature, "parameters", default=None) or {}
        extrusion: dict[str, Any] = {
            "name": name,
            "sketch": applied.get("sketch_name"),
            "depth": input_data.depth,
            "end_condition": applied.get("end_condition")
            or ("MidPlane" if input_data.both_directions else input_data.end_condition),
            "both_directions": input_data.both_directions,
        }
        if input_data.thin_feature:
            extrusion["thin"] = {
                "thickness": input_data.thin_thickness,
                "side": input_data.thin_side,
            }
        reply = {
            "status": "success",
            "message": f"Created extrusion: {name}",
            "extrusion": extrusion,
            "execution_time": result.execution_time,
        }
        return _attach_measured_change(reply, before, after)

    @mcp.tool()
    async def create_revolve(input_data: CreateRevolveInput) -> dict[str, Any]:
        """Revolve a closed sketch around an axis, adding a solid to the active part.

        Use it for turned shapes (shafts, knobs). It revolves the sketch `sketch_name`
        names, or the one `exit_sketch` closed last, about the reference axis
        `axis_entity` names (from `create_axis`), or about the centreline drawn in the
        sketch with `add_centerline`. A sketch or axis that isn't in the model fails
        before anything is built. Needs: an open part and a closed profile with a
        centreline or a reference axis. Changes: adds a Revolve feature. Returns:
        `revolve` (`name`, `sketch` and `axis_entity` when named, `angle`) and
        `measured_change` (volume, bounding box and solid-body count before and
        after; left out when the model can't be read).

        Args:
            input_data: The revolve. `angle` (degrees, 360 for a full turn) is
                required; `sketch_name`, `axis_entity`, `both_directions`,
                `reverse_direction`, `thin_feature` and `merge_result` have defaults.

        Returns:
            dict[str, Any]: The created feature.
        """
        input_data = normalize_input(input_data, CreateRevolveInput)
        # Convert input to RevolveParameters
        params = RevolveParameters(
            angle=input_data.angle,
            reverse_direction=input_data.reverse_direction,
            both_directions=input_data.both_directions,
            thin_feature=input_data.thin_feature,
            thin_thickness=input_data.thin_thickness,
            merge_result=input_data.merge_result,
            sketch_name=input_data.sketch_name,
            axis_entity=input_data.axis_entity,
        )

        before = await _read_summary(adapter)
        result = await adapter.create_revolve(params)

        require_success(result, context="Failed to create revolve")
        after = await _read_summary(adapter) if before is not None else None
        feature = result.data
        name = _result_value(feature, "feature_name", "name", default="Revolve")
        applied = _result_value(feature, "parameters", default=None) or {}
        reply = {
            "status": "success",
            "message": f"Created revolve: {name}",
            "revolve": {
                "name": name,
                "sketch": applied.get("sketch_name"),
                "axis_entity": applied.get("axis_entity"),
                "angle": input_data.angle,
            },
            "execution_time": result.execution_time,
        }
        return _attach_measured_change(reply, before, after)

    @mcp.tool()
    async def get_dimension(input_data: GetDimensionInput) -> dict[str, Any]:
        """Read one dimension of the active model by its full name, e.g. "D1@Sketch1".

        Find names with `list_model_dimensions`. Needs: an open part or assembly.
        Read-only. Returns: `dimension` with `name`, `value` and `units`: "mm" for a
        length, "deg" for an angle, and null for a count (such as a pattern's
        instance count).

        Args:
            input_data: The dimension. Give `name` (or `dimension_name`), e.g.
                "D1@Boss-Extrude1".

        Returns:
            dict[str, Any]: The dimension's value.
        """
        input_data = normalize_input(input_data, GetDimensionInput)
        result = await adapter.get_dimension(input_data.name)

        require_success(result, context="Failed to get dimension")
        reading = result.data or {}
        dimension_value = reading.get("value")
        dimension_units = reading.get("units")
        unit_text = f" {dimension_units}" if dimension_units else ""
        return {
            "status": "success",
            "message": f"Dimension {input_data.name} = {dimension_value}{unit_text}",
            "dimension": {
                "name": input_data.name,
                "value": dimension_value,
                "units": dimension_units,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def set_dimension(input_data: SetDimensionInput) -> dict[str, Any]:
        """Change one length dimension of the active model, in mm, and rebuild.

        Use it to resize an existing model; find the full name with
        `list_model_dimensions` and check the result with `rebuild_model` or
        `verify_model`. The value is always millimetres. Needs: an open part or
        assembly. Changes: the dimension and the geometry it drives. Returns:
        `dimension_update` with `name`, `old_value` and `new_value`.

        Args:
            input_data: The change. `value` (mm) is required, with `name` (or
                `dimension_name`) such as "D1@Sketch1"; `units` is not used.

        Returns:
            dict[str, Any]: The old and new values.
        """
        input_data = normalize_input(input_data, SetDimensionInput)
        result = await adapter.set_dimension(input_data.name, input_data.value)

        require_success(result, context="Failed to set dimension")
        payload = result.data
        return {
            "status": "success",
            "message": f"Set dimension {input_data.name} = {input_data.value} mm",
            "dimension_update": {
                "name": input_data.name,
                "old_value": _result_value(payload, "old_value"),
                "new_value": _result_value(
                    payload, "new_value", default=input_data.value
                ),
                "units": input_data.units or "mm",
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def set_units(input_data: SetUnitsInput) -> dict[str, Any]:
        """Set the active document's length units: mm, cm, m, in or ft.

        Use it on a new part before sketching if you want other than the template's
        units. Aliases such as "inch" are accepted. The setting is read back, so success
        means it applied. Tool inputs stay in mm whatever the document shows. Needs: an
        open, active document. Changes: the document's unit system. Returns: `data` with
        `unit_system`, the values applied and observed, and `verified`.

        Args:
            input_data: The units. `unit_system` (mm, cm, m, in or ft) is
                required.

        Returns:
            dict[str, Any]: The units set.
        """
        input_data = normalize_input(input_data, SetUnitsInput)
        result = await adapter.set_units(input_data.unit_system)
        require_success(result, context="Failed to set units")
        data = result.data if isinstance(result.data, dict) else {}
        applied = data.get("unit_system", input_data.unit_system)
        message = f"Set document units to {applied}"
        if data.get("verified") is None:
            message += " (could not be read back to confirm)"
        return {
            "status": "success",
            "message": message,
            "data": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_cut_extrude(input_data: CreateCutExtrudeInput) -> dict[str, Any]:
        """Cut material from the active part with a closed sketch profile: holes, slots, windows.

        Use it after `exit_sketch`. Pass `sketch_name` unless the sketch you just closed
        is the one: with no name only that sketch is used, and any doubt is an error
        naming the sketches found. A one-way cut that finds no material is retried the
        other way (`direction_flipped`). For a sketch inside the body, use
        ThroughAllBoth. Needs: an open part with a solid body. Changes: adds a
        Cut-Extrude feature. Returns: `cut_extrude` (`name`, `sketch_name`,
        `direction_flipped`) and `measured_change` (volume, bounding box and solid-body
        count before and after; left out when the model can't be read).

        Args:
            input_data: The cut. `depth` (mm) is required; `sketch_name`,
                `end_condition` (Blind, ThroughAll, ThroughAllBoth),
                `both_directions`, `reverse_direction` and `draft_angle` have
                defaults.

        Returns:
            dict[str, Any]: The created cut.
        """
        input_data = normalize_input(input_data, CreateCutExtrudeInput)
        params = ExtrusionParameters(
            depth=input_data.depth,
            draft_angle=input_data.draft_angle,
            reverse_direction=input_data.reverse_direction,
            both_directions=input_data.both_directions,
            thin_feature=False,
            thin_thickness=None,
            end_condition=input_data.end_condition,
            merge_result=False,
            feature_scope=False,
            auto_select=True,
            sketch_name=input_data.sketch_name,
        )
        before = await _read_summary(adapter)
        result = await adapter.create_cut_extrude(params)
        require_success(result, context="Failed to create cut-extrude")
        after = await _read_summary(adapter) if before is not None else None
        feature = result.data
        feature_params = _result_value(feature, "parameters", default={})
        sketch_used = (
            feature_params.get("sketch_name")
            if isinstance(feature_params, dict)
            else None
        ) or input_data.sketch_name
        flipped = bool(
            isinstance(feature_params, dict) and feature_params.get("direction_flipped")
        )
        name = _result_value(feature, "feature_name", "name", default="Cut-Extrude")
        message = f"Created cut-extrude: {name}"
        if flipped:
            message += (
                " (the requested direction found no material, so it cut the other way)"
            )
        reply = {
            "status": "success",
            "message": message,
            "cut_extrude": {
                "name": name,
                "depth": input_data.depth,
                "sketch_name": sketch_used,
                "direction_flipped": flipped,
            },
            "execution_time": result.execution_time,
        }
        return _attach_measured_change(reply, before, after)

    @mcp.tool()
    async def add_fillet(input_data: AddFilletInput) -> dict[str, Any]:
        """Round edges of the active part with a constant-radius fillet.

        Name the edges as "Edge<1>", a point "x,y,z" (metres) or "face:x,y,z" for every
        edge of a face; or leave `edge_names` empty to use the current selection (e.g.
        from `select_face_edges`). A fillet that leaves the volume unchanged is an
        error. Needs: an open part with a solid body. Changes: adds a Fillet feature.
        Returns: `fillet` with `name`, `radius` and `edges`.

        Args:
            input_data: The fillet. `radius` (mm) is required; `edge_names`
                defaults to the current selection.

        Returns:
            dict[str, Any]: The created fillet.
        """
        input_data = normalize_input(input_data, AddFilletInput)
        result = await adapter.add_fillet(input_data.radius, input_data.edge_names)
        require_success(result, context="Failed to add fillet")
        feature = result.data
        return {
            "status": "success",
            "message": f"Created fillet: {_result_value(feature, 'feature_name', 'name', default='Fillet')}",
            "fillet": {
                "name": _result_value(
                    feature, "feature_name", "name", default="Fillet"
                ),
                "radius": input_data.radius,
                "edges": input_data.edge_names,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def add_chamfer(input_data: AddChamferInput) -> dict[str, Any]:
        """Bevel edges of the active part with a chamfer: `distance` along one face at `angle` (45 by default).

        Name the edges as "Edge<1>", a point "x,y,z" (metres) or "face:x,y,z" for every
        edge of a face; or leave `edge_names` empty to use the current selection (e.g.
        from `select_face_edges`). At 45 degrees both legs equal `distance`; at another
        angle, `flip` swaps which face `distance` is measured on. Needs: an open part
        with a solid body. Changes: adds a Chamfer feature. Returns: `chamfer` with
        `name`, `distance`, `angle`, `flip` and `edges`.

        Args:
            input_data: The chamfer. `distance` (mm) is required; `edge_names`
                defaults to the current selection.

        Returns:
            dict[str, Any]: The created chamfer.
        """
        input_data = normalize_input(input_data, AddChamferInput)
        result = await adapter.add_chamfer(
            input_data.distance,
            input_data.edge_names,
            input_data.angle,
            input_data.flip,
        )
        require_success(result, context="Failed to add chamfer")
        feature = result.data
        return {
            "status": "success",
            "message": f"Created chamfer: {_result_value(feature, 'feature_name', 'name', default='Chamfer')}",
            "chamfer": {
                "name": _result_value(
                    feature, "feature_name", "name", default="Chamfer"
                ),
                "distance": input_data.distance,
                "angle": input_data.angle,
                "flip": input_data.flip,
                "edges": input_data.edge_names,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_sweep(input_data: CreateSweepInput) -> dict[str, Any]:
        """Sweep a closed profile sketch along a path sketch to make a solid (Insert > Boss/Base > Sweep).

        Draw the closed profile and the open path as two sketches first. The profile is
        the sketch you closed last that isn't the path. Needs: an open part with both
        sketches. Changes: adds a Sweep feature. Returns: `sweep` with `name`, `path`,
        `twist_along_path` and `twist_angle`.

        Args:
            input_data: The sweep. `path` (the path sketch's name) is required;
                `twist_along_path`, `twist_angle` (degrees) and `merge_result` have
                defaults.

        Returns:
            dict[str, Any]: The created sweep.
        """
        input_data = normalize_input(input_data, CreateSweepInput)
        params = SweepParameters(
            path=input_data.path,
            twist_along_path=input_data.twist_along_path,
            twist_angle=input_data.twist_angle,
            merge_result=input_data.merge_result,
        )
        result = await adapter.create_sweep(params)
        require_success(result, context="Failed to create sweep")
        feature = result.data
        return {
            "status": "success",
            "message": f"Created sweep: {_result_value(feature, 'feature_name', 'name', default='Sweep')}",
            "sweep": {
                "name": _result_value(feature, "feature_name", "name", default="Sweep"),
                "path": input_data.path,
                "twist_along_path": input_data.twist_along_path,
                "twist_angle": input_data.twist_angle,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_loft(input_data: CreateLoftInput) -> dict[str, Any]:
        """Loft a solid through two or more closed profile sketches, in order (Insert > Boss/Base > Loft).

        Use it for shapes that change section, such as a wing or a transition duct. Put
        each profile on its own plane (see `create_reference_plane`). Needs: an open
        part with the profile sketches. Changes: adds a Loft feature. Returns: `loft`
        with `name`, `profiles` and `guide_curves`.

        Args:
            input_data: The loft. `profiles` (sketch names, in order) is required;
                `guide_curves`, `start_tangent`, `end_tangent` and `merge_result`
                have defaults.

        Returns:
            dict[str, Any]: The created loft.
        """
        input_data = normalize_input(input_data, CreateLoftInput)
        params = LoftParameters(
            profiles=input_data.profiles,
            guide_curves=input_data.guide_curves,
            start_tangent=input_data.start_tangent,
            end_tangent=input_data.end_tangent,
            merge_result=input_data.merge_result,
        )
        result = await adapter.create_loft(params)
        require_success(result, context="Failed to create loft")
        feature = result.data
        return {
            "status": "success",
            "message": f"Created loft: {_result_value(feature, 'feature_name', 'name', default='Loft')}",
            "loft": {
                "name": _result_value(feature, "feature_name", "name", default="Loft"),
                "profiles": input_data.profiles,
                "guide_curves": input_data.guide_curves,
            },
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def insert_component(input_data: InsertComponentInput) -> dict[str, Any]:
        """Insert a part or sub-assembly file into the active assembly at a position in mm.

        Use it after `create_assembly`, then position components with `add_mate`. The
        file must contain solid geometry; an empty or missing file is an error. Needs:
        an open, active assembly and the file on disk. Changes: adds a component.
        Returns: `component` with its instance name (`component`, which `add_mate`
        takes), `file_path`, `position` and the counts before and after.

        Args:
            input_data: The component. `file_path` is required; `x`, `y`, `z` (mm
                from the assembly origin) default to 0.

        Returns:
            dict[str, Any]: The inserted component.
        """
        input_data = normalize_input(input_data, InsertComponentInput)
        result = await adapter.insert_component(
            input_data.file_path, input_data.x, input_data.y, input_data.z
        )
        require_success(result, context="Failed to insert component")
        data = result.data if isinstance(result.data, dict) else {}
        return {
            "status": "success",
            "message": f"Inserted {data.get('component', 'component')}",
            "component": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def add_mate(input_data: AddMateInput) -> dict[str, Any]:
        """Mate two components of the active assembly: coincident, concentric, parallel, perpendicular, tangent, distance or angle.

        Each side is a named reference plane or axis (`entity_a`, e.g. "Front Plane"),
        or a face given by a point on it (`face_a`, mm, in that part's own coordinates):
        a pin's round face and a hole's face make a concentric mate. Get instance names
        from `list_components`. Needs: an open assembly with both components. Changes:
        adds a mate and may move components. Returns: `mate` with `mate_type`,
        `components`, `entities`, `geometry_moved` and `moved_components`.

        Args:
            input_data: The mate. `component_a` and `component_b` are required;
                each side takes `entity_*` or `face_*` (default "Front Plane");
                `mate_type` (coincident), `alignment`, `distance` (mm) and `angle`
                (degrees) have defaults.

        Returns:
            dict[str, Any]: The mate added.
        """
        input_data = normalize_input(input_data, AddMateInput)
        result = await adapter.add_mate(
            input_data.component_a,
            input_data.component_b,
            input_data.entity_a or "Front Plane",
            input_data.entity_b or "Front Plane",
            input_data.mate_type,
            input_data.alignment,
            input_data.distance,
            input_data.angle,
            input_data.face_a,
            input_data.face_b,
        )
        require_success(result, context="Failed to add mate")
        data = result.data if isinstance(result.data, dict) else {}
        message = (
            f"Added {input_data.mate_type} mate between "
            f"{input_data.component_a} and {input_data.component_b}"
        )
        # SolidWorks accepts a mate whose constraint is already
        # satisfied and moves nothing. That is a real success, but
        # saying so plainly beats leaving the caller to infer it.
        if data.get("geometry_moved") is False:
            message += " (no component moved - the constraint was already satisfied)"
        return {
            "status": "success",
            "message": message,
            "mate": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def set_component_state(input_data: SetComponentStateInput) -> dict[str, Any]:
        """Fix or float a component of the active assembly, or make a sub-assembly rigid or flexible.

        Float a part so mates can position it (the first part inserted is fixed); fix
        one to hold it still. Make a sub-assembly flexible so its own mates move in
        this assembly (a crank whose knob turns). Only what you pass changes: the
        component's suppression, visibility and configuration are kept. Needs: an
        open assembly. Changes: the component's fixed or solving state. Returns:
        `state` with `component`, `before` and `after` (`fixed`, `flexible` and the
        properties kept).

        Args:
            input_data: The component and what to change: `fixed`, `flexible` or
                both.

        Returns:
            dict[str, Any]: The state before and after.
        """
        input_data = normalize_input(input_data, SetComponentStateInput)
        result = await adapter.set_component_state(
            input_data.component, input_data.fixed, input_data.flexible
        )
        require_success(result, context="Failed to set the component state")
        data = result.data if isinstance(result.data, dict) else {}
        after = data.get("after", {})
        words = []
        if input_data.fixed is not None:
            words.append("fixed" if after.get("fixed") else "floating")
        if input_data.flexible is not None:
            words.append("flexible" if after.get("flexible") else "rigid")
        return {
            "status": "success",
            "message": f"{input_data.component} is now {' and '.join(words)}",
            "state": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def list_components() -> dict[str, Any]:
        """List the top-level components of the active assembly by instance name, e.g. "bracket-1".

        Use it before `add_mate`, which takes these names. Needs: an open, active
        assembly. Read-only. Returns: `components` (instance names).
        """
        result = await adapter.list_components()
        require_success(result, context="Failed to list components")
        components = result.data if isinstance(result.data, list) else []
        return {
            "status": "success",
            "message": f"{len(components)} component(s) in the assembly",
            "components": components,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def delete_feature(input_data: DeleteFeatureInput) -> dict[str, Any]:
        """Delete a feature or sketch from the active model, along with the features that depend on it.

        Ask the user before you call it: deleting a sketch also deletes every feature
        built from it (a cut, a boss), and deleting a feature deletes everything that
        depends on it. Use `suppress_feature` instead when you might want it back. Find
        names and dependents with `list_features`. Needs: an open part or assembly.
        Changes: removes the feature and its dependents (`undo` can restore them).
        Returns: `data` with `deleted`, `removed_features` (every feature that went,
        dependents included), `features_before` and `features_after`; the message names
        the dependents, and a `warning` says so whenever more than the named feature
        went: tell the user.

        Args:
            input_data: The feature. `name` (e.g. "Fillet1") is required.

        Returns:
            dict[str, Any]: What was deleted.
        """
        input_data = normalize_input(input_data, DeleteFeatureInput)
        result = await adapter.delete_feature(input_data.name)
        require_success(result, context="Failed to delete feature")
        data = result.data if isinstance(result.data, dict) else {}
        removed = data.get("removed_features") or [input_data.name]
        dependents = [n for n in removed if n != input_data.name.split("@", 1)[0]]
        reply: dict[str, Any] = {
            "status": "success",
            "message": (
                f"Deleted {input_data.name}"
                + (
                    f" and its dependents: {', '.join(dependents)}"
                    if dependents
                    else ""
                )
            ),
            "data": data,
            "execution_time": result.execution_time,
        }
        if dependents:
            reply["warning"] = (
                f"Deleting {input_data.name} also deleted {', '.join(dependents)}. "
                "Tell the user; `undo` restores them."
            )
        return reply

    @mcp.tool()
    async def suppress_feature(input_data: SuppressFeatureInput) -> dict[str, Any]:
        """Suppress or unsuppress a feature of the active model; suppressed features stay in the tree but are not built.

        Use it to turn off a feature that breaks the rebuild without deleting it. Needs:
        an open part or assembly. Changes: the feature's suppression state, and its
        children's. Returns: `data` with `feature`, `requested`, `suppressed` (read
        back; null when unreadable) and `was_suppressed`.

        Args:
            input_data: The feature. `name` is required; `suppress` defaults to on
                (pass false to unsuppress).

        Returns:
            dict[str, Any]: The new state.
        """
        input_data = normalize_input(input_data, SuppressFeatureInput)
        result = await adapter.suppress_feature(input_data.name, input_data.suppress)
        require_success(result, context="Failed to suppress feature")
        data = result.data if isinstance(result.data, dict) else {}
        verb = "Suppressed" if input_data.suppress else "Unsuppressed"
        message = f"{verb} {input_data.name}"
        if data.get("suppressed") is None:
            message += " (state could not be read back)"
        return {
            "status": "success",
            "message": message,
            "data": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def rename_feature(input_data: RenameFeatureInput) -> dict[str, Any]:
        """Rename a feature in the active model's feature tree.

        Use it to give features meaningful names (e.g. "MountingHoles"). The new name is
        read back: a name another feature already uses is an error. Renaming to the
        current name succeeds with no change. Needs: an open part or assembly. Changes:
        the feature's name. Returns: `data` with `old_name`, `new_name`, `renamed` and,
        when unchanged, `reason`.

        Args:
            input_data: The rename. `old_name` and `new_name` are required.

        Returns:
            dict[str, Any]: The rename.
        """
        input_data = normalize_input(input_data, RenameFeatureInput)
        result = await adapter.rename_feature(input_data.old_name, input_data.new_name)
        require_success(result, context="Failed to rename feature")
        data = result.data if isinstance(result.data, dict) else {}
        if data.get("renamed") is False:
            return {
                "status": "success",
                "message": (
                    f"{input_data.old_name} unchanged: "
                    + str(data.get("reason") or "no change")
                ),
                "data": data,
                "execution_time": result.execution_time,
            }
        return {
            "status": "success",
            "message": (
                f"Renamed {data.get('old_name', input_data.old_name)} to "
                f"{data.get('new_name', input_data.new_name)}"
            ),
            "data": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def select_feature(input_data: SelectFeatureInput) -> dict[str, Any]:
        """Select a feature, sketch, plane or component by name in the active document.

        Use it to set up a selection that the next SolidWorks operation acts on.
        `append` adds to the selection instead of replacing it. A name that can't be
        selected is an error. Needs: an open document. Changes: the selection only.
        Returns: `data` with `selected_name` and `selection_count`.

        Args:
            input_data: The selection. `feature_name` is required; `append` is off.

        Returns:
            dict[str, Any]: The selection.
        """
        input_data = normalize_input(input_data, SelectFeatureInput)
        result = await adapter.select_feature(
            input_data.feature_name, input_data.append
        )
        require_success(result)
        data = result.data if isinstance(result.data, dict) else {}
        return {
            "status": "success",
            "message": (
                f"Selected {data.get('selected_name', input_data.feature_name)} "
                f"({data.get('selection_count', '?')} selected)"
            ),
            "data": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def select_face_edges(input_data: SelectFaceEdgesInput) -> dict[str, Any]:
        """Select every edge of one face of the active part, ready for `add_fillet` or `add_chamfer` with no edge names.

        Pick the face with one of `point` (a point on it, mm), `side` (top, bottom,
        front, back, right, left or +X..-Z; the furthest flat face that way) or `plane`
        (the face lying on that plane). `edge_type` narrows to linear or circular edges
        (hole rims). Needs: an open part. Changes: the selection only. Returns: `data`
        with `face`, `edges`, `selected_edges` and `selection_count`.

        Args:
            input_data: The face. Give exactly one of `point`, `side` or `plane`;
                `edge_type` (all) and `append` (off) have defaults.

        Returns:
            dict[str, Any]: The edges selected.
        """
        input_data = normalize_input(input_data, SelectFaceEdgesInput)
        result = await adapter.select_face_edges(
            input_data.point,
            input_data.side,
            input_data.plane,
            input_data.edge_type,
            input_data.append,
        )
        require_success(result)
        data = result.data if isinstance(result.data, dict) else {}
        kinds = sorted({e.get("curve", "other") for e in data.get("edges", [])})
        return {
            "status": "success",
            "message": (
                f"Selected {data.get('selected_edges', 0)} edge(s) "
                f"({', '.join(kinds)}) on the face at "
                f"{data.get('face', {}).get('center_mm')} mm"
            ),
            "data": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def rebuild_model(
        input_data: RebuildModelInput | None = None,
    ) -> dict[str, Any]:
        """Rebuild the active model and report each feature that fails, with the reason and a fix.

        Use it after `set_dimension` or other edits to confirm the model is sound.
        Failing features make the call an error whose `data.errors` names each one, its
        SolidWorks error, what it depends on and a `hint`; warnings alone still succeed.
        Needs: an open part or assembly. Changes: rebuilds the model. Returns: `data`
        with `rebuilt`, `errors`, `error_count`, `warning_count` and `summary`.

        Args:
            input_data: Nothing is required: `top_level_only` is off (a full
                rebuild).

        Returns:
            dict[str, Any]: The rebuild report.
        """
        input_data = normalize_input(input_data or {}, RebuildModelInput)
        result = require_success(
            await adapter.rebuild_model(input_data.top_level_only), with_data=True
        )
        data = result.data if isinstance(result.data, dict) else None
        response: dict[str, Any] = {
            "status": "success",
            "message": (data or {}).get("summary") or "Rebuilt",
            "execution_time": result.execution_time,
        }
        if data is not None:
            response["data"] = data
        return response

    @mcp.tool()
    async def undo(input_data: UndoInput | None = None) -> dict[str, Any]:
        """Undo the last operations in the active model (Edit > Undo).

        Use it to step back after a feature went wrong. SolidWorks accepts an undo with
        nothing to undo, so the reply says whether the feature tree changed. Needs: an
        open document. Changes: reverts the last `count` operations. Returns: `data`
        with `requested_steps`, `features_before`, `features_after` and `tree_changed`.

        Args:
            input_data: Nothing is required: `count` defaults to 1.

        Returns:
            dict[str, Any]: What changed.
        """
        input_data = normalize_input(input_data or UndoInput(), UndoInput)
        result = await adapter.undo(input_data.count)
        require_success(result, context="Failed to undo")
        data = result.data if isinstance(result.data, dict) else {}
        changed = data.get("tree_changed")
        if changed is False:
            message = (
                f"Undo of {input_data.count} step(s) left the feature "
                "tree unchanged - there was nothing to undo"
            )
        else:
            message = f"Undid {input_data.count} step(s)"
        return {
            "status": "success",
            "message": message,
            "data": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_reference_plane(
        input_data: CreateReferencePlaneInput,
    ) -> dict[str, Any]:
        """Add a reference plane offset from, at an angle to, or on a plane or flat face.

        Use it to sketch somewhere other than the three default planes: pass the new
        plane's name to `create_sketch`. Offset: `reference` and a non-zero `offset`
        (mm). Angle: `reference`, `angle` (degrees) and `axis`, an axis lying in the
        reference (make one with `create_axis`). Face: `face_point`, a point on a flat
        face (sloped or not), with an `offset` or 0 for a plane on the face. Needs: an
        open part. Changes: adds a plane feature. Returns: `plane` with `name` and the
        inputs used.

        Args:
            input_data: The plane. Exactly one of `reference` and `face_point`;
                then `offset`, or `angle` with `axis`; `flip` is off.

        Returns:
            dict[str, Any]: The new plane.
        """
        input_data = normalize_input(input_data, CreateReferencePlaneInput)
        result = await adapter.create_reference_plane(
            input_data.reference,
            input_data.offset,
            input_data.angle,
            input_data.flip,
            input_data.axis,
            input_data.face_point,
        )
        require_success(result, context="Failed to create reference plane")
        data = result.data if isinstance(result.data, dict) else {}
        return {
            "status": "success",
            "message": f"Created reference plane: {data.get('name', 'Plane')}",
            "plane": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_axis(input_data: CreateAxisInput) -> dict[str, Any]:
        """Add a reference axis along the model's x, y or z direction, through the origin.

        Use it before `pattern_circular`, which rotates features about an axis. It is
        built where two default planes meet. Needs: an open part. Changes: adds an axis
        feature. Returns: `axis` with `name` (e.g. "Axis1", for
        `create_reference_plane`'s `axis`), `reference`, `planes` and the feature counts.

        Args:
            input_data: The axis. `reference` ("x", "y" or "z") is required.

        Returns:
            dict[str, Any]: The new axis.
        """
        input_data = normalize_input(input_data, CreateAxisInput)
        result = await adapter.create_axis(input_data.reference)
        require_success(result, context="Failed to create axis")
        data = result.data if isinstance(result.data, dict) else {}
        axis_name = data.get("reference", input_data.reference)
        return {
            "status": "success",
            "message": f"Created {axis_name} axis",
            "axis": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def create_reference_point(
        input_data: CreateReferencePointInput,
    ) -> dict[str, Any]:
        """Add a reference point on an edge (at a distance or percentage along it) or at the centre of a face.

        Use it to mark a position for a later feature or measurement. Pick the edge or
        face with a point on it in mm. Needs: an open part with that edge or face.
        Changes: adds a point feature. Returns: `point` with `mode`, `at_mm`,
        `distance_mm` or `percent`, and the feature counts.

        Args:
            input_data: The point. `mode` (along_curve or face_center) and `x`,
                `y`, `z` (mm) are required; for along_curve give one of `distance`
                (mm) or `percent`.

        Returns:
            dict[str, Any]: The new point.
        """
        input_data = normalize_input(input_data, CreateReferencePointInput)
        result = await adapter.create_reference_point(
            input_data.mode,
            input_data.x,
            input_data.y,
            input_data.z,
            input_data.distance,
            input_data.percent,
        )
        require_success(result, context="Failed to create reference point")
        data = result.data if isinstance(result.data, dict) else {}
        where = (
            f"{data.get('percent')}% along a curve"
            if data.get("percent") is not None
            else (
                f"{data.get('distance_mm')} mm along a curve"
                if data.get("distance_mm") is not None
                else "a face centre"
            )
        )
        return {
            "status": "success",
            "message": f"Created a reference point at {where}",
            "point": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def mirror_feature(input_data: MirrorFeatureInput) -> dict[str, Any]:
        """Mirror solid bodies or features of the active part about a plane.

        Use it for symmetric parts: model one half, then mirror. Body mirroring (the
        default) is what works for lofts and sweeps; to mirror a cut, name the cut and
        set `mirror_bodies` off. It fails when the volume doesn't change, which means
        nothing was mirrored. Needs: an open part with the named bodies or features.
        Changes: adds a Mirror feature. Returns: `mirror` with `name`, `mirrored`,
        `mirror_plane`, `merge`, `mirror_bodies`, and `volume_before`,
        `volume_after` and `volume_change` (mm³, negative for a cut).

        Args:
            input_data: The mirror. `features` (at least one name) and
                `mirror_plane` (e.g. "Right Plane") are required; `merge` and
                `mirror_bodies` are on.

        Returns:
            dict[str, Any]: The mirror created.
        """
        input_data = normalize_input(input_data, MirrorFeatureInput)
        result = await adapter.mirror_feature(
            input_data.features,
            input_data.mirror_plane,
            input_data.merge,
            input_data.mirror_bodies,
        )
        require_success(result, context="Failed to mirror feature")
        data = result.data if isinstance(result.data, dict) else {}
        return {
            "status": "success",
            "message": f"Mirrored {', '.join(input_data.features)} "
            f"about {input_data.mirror_plane}",
            "mirror": data,
            "execution_time": result.execution_time,
        }

    @mcp.tool()
    async def pattern_circular(input_data: PatternCircularInput) -> dict[str, Any]:
        """Repeat features of the active part around an axis, e.g. a ring of bosses or ribs.

        Create the axis first with `create_axis`. Bosses and cuts both work (a ring of
        holes is a patterned cut). It fails when the volume doesn't change, which
        means no instance landed on the part. Needs: an open part with the named
        features and axis. Changes: adds a circular pattern feature. Returns:
        `pattern` with `name`, `patterned`, `axis`, `count`, `angle`,
        `equal_spacing`, and `volume_before`, `volume_after` and `volume_change`
        (mm³, negative for cuts).

        Args:
            input_data: The pattern. `features` (at least one), `axis` and `count`
                (2 or more, the original included) are required; `angle` (360) and
                `equal_spacing` (on) have defaults.

        Returns:
            dict[str, Any]: The pattern created.
        """
        input_data = normalize_input(input_data, PatternCircularInput)
        result = await adapter.pattern_circular(
            input_data.features,
            input_data.axis,
            input_data.count,
            input_data.angle,
            input_data.equal_spacing,
        )
        require_success(result, context="Failed to pattern feature")
        data = result.data if isinstance(result.data, dict) else {}
        return {
            "status": "success",
            "message": f"Patterned {', '.join(input_data.features)} "
            f"around {input_data.axis} ({input_data.count} instances)",
            "pattern": data,
            "execution_time": result.execution_time,
        }

    # Counted from the registry rather than hand-maintained. The literal that
    # used to live here had drifted: it read 15 while 16 tools were actually
    # registered, so the function misreported its own work and the test
    # enshrined the wrong number.
    tool_count = len(await mcp.list_tools())
    return tool_count

require_success

require_success(result: AdapterResult[TResult], failure_message: str = 'Operation failed', *, context: str | None = None, with_data: bool = False) -> AdapterResult[TResult]

Return result when it succeeded; raise otherwise.

Mirrors the if result.is_success: ... else: error the tools used before the boundary, so anything that is not a success - including a warning - is reported as a failure. Tools that treat a warning as success check result.status themselves before calling this.

Parameters:

Name Type Description Default
result AdapterResult[TResult]

The adapter result to check.

required
failure_message str

Message used when the adapter gave none.

'Operation failed'
context str | None

Prefix naming what failed, e.g. "Failed to create part", giving "<context>: <adapter error>".

None
with_data bool

Return the adapter's data with the error, for tools whose failure data is the diagnosis (e.g. rebuild_model).

False

Raises:

Type Description
ToolOperationError

Carrying the adapter's message and timing.

Source code in src/solidworks_mcp/tools/tool_boundary.py
def require_success[TResult](
    result: AdapterResult[TResult],
    failure_message: str = "Operation failed",
    *,
    context: str | None = None,
    with_data: bool = False,
) -> AdapterResult[TResult]:
    """Return ``result`` when it succeeded; raise otherwise.

    Mirrors the ``if result.is_success: ... else: error`` the tools used before
    the boundary, so anything that is not a success - including a warning - is
    reported as a failure. Tools that treat a warning as success check
    ``result.status`` themselves before calling this.

    Args:
        result: The adapter result to check.
        failure_message: Message used when the adapter gave none.
        context: Prefix naming what failed, e.g. ``"Failed to create part"``,
            giving ``"<context>: <adapter error>"``.
        with_data: Return the adapter's ``data`` with the error, for tools whose
            failure data is the diagnosis (e.g. ``rebuild_model``).

    Raises:
        ToolOperationError: Carrying the adapter's message and timing.
    """
    if not result.is_success:
        message = str(result.error or failure_message)
        raise ToolOperationError(
            f"{context}: {message}" if context else message,
            result.execution_time,
            result.data if with_data else None,
        )
    return result

with_tool_boundary

with_tool_boundary(mcp: TServer) -> TServer

Return mcp wrapped in a :class:ToolRegistrar (typed as mcp).

The registrar duck-types the FastMCP surface the tool modules use (tool() plus attribute forwarding), so modules keep their annotations.

Source code in src/solidworks_mcp/tools/tool_boundary.py
def with_tool_boundary[TServer](mcp: TServer) -> TServer:
    """Return ``mcp`` wrapped in a :class:`ToolRegistrar` (typed as ``mcp``).

    The registrar duck-types the FastMCP surface the tool modules use
    (``tool()`` plus attribute forwarding), so modules keep their annotations.
    """
    return cast(TServer, ToolRegistrar.of(mcp))