Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
10c2beb
Fix absolute `from sw_core import` inside tool functions
denglobert Sep 3, 2026
4831e37
Read the assigned material back in the shapes older builds return it
denglobert Sep 3, 2026
d07a29b
Fall back to earlier API method variants on releases that lack the ne…
denglobert Sep 3, 2026
8a14c1c
修正兼容方法的全局缓存误判并补充安装包与材质回归测试
Slacker-LLC Oct 7, 2026
c48ed7a
新增二十八个多实体曲面配置属性方程与组件管理工具
Slacker-LLC Oct 7, 2026
808a140
扩展钣金焊件曲面及官方 Motion 算例工具并记录覆盖缺口
Slacker-LLC Oct 7, 2026
1e513a7
补齐直接编辑参考点坐标系和曲线工具并验证原生几何
Slacker-LLC Oct 7, 2026
92f2eca
补充旋转曲面放样曲面与指定实体曲面切除
Slacker-LLC Oct 7, 2026
bb4c6f7
补充曲面拓扑选择延伸与解除修剪并核验百分比语义
Slacker-LLC Oct 7, 2026
435def2
补充填充和直纹曲面并核验原生连续性方向与锥角
Slacker-LLC Oct 7, 2026
db5e8e1
补充选择性删除曲面孔并验证新旧原生接口
Slacker-LLC Oct 7, 2026
cc0157d
补充扫描曲面并核验扭转导引与扫描方向
Slacker-LLC Oct 7, 2026
36a0c53
补充中面创建与原生面配对厚度位置检查
Slacker-LLC Oct 7, 2026
2d05199
补充曲面修剪预览创建检查与已有实例选择
Slacker-LLC Oct 7, 2026
1ea7712
补充边界曲面及原生定义检查并核验几何连续性
Slacker-LLC Oct 8, 2026
9ddf34e
补充包覆创建与原生定义查询并验证体积及面分割
Slacker-LLC Oct 8, 2026
2b910de
修正样条包覆几何读回的浮点比较容差
Slacker-LLC Oct 8, 2026
d9024a7
扩展多面包覆及方向选择并新增原生参数修改
Slacker-LLC Oct 8, 2026
5a5df09
补充包覆源草图替换并核验原生目标面引用
Slacker-LLC Oct 8, 2026
90d0b3d
新增原生圆顶工具并核验形状和参数修改
Slacker-LLC Oct 8, 2026
dc0f138
扩展圆顶点草图约束并核验控制清除与方向几何
Slacker-LLC Oct 8, 2026
c94a4c3
补充三维草图生命周期与 XYZ 几何并核验持久引用
Slacker-LLC Oct 8, 2026
faa516f
避免原生圆创建受自动推断影响并核验圆心半径
Slacker-LLC Oct 8, 2026
b446ccb
复用局部推断控制并读回实际线端点
Slacker-LLC Oct 8, 2026
ad510ba
补充三维构造线与三点圆弧并核验原生空间几何
Slacker-LLC Oct 8, 2026
a076b58
核验椭圆创建与空间曲线转换的实际几何对应
Slacker-LLC Oct 8, 2026
c6d0a70
按持久引用识别转换新增曲线并覆盖已有几何场景
Slacker-LLC Oct 8, 2026
bd750fc
新增三维轴向尺寸并核验求解几何与编辑恢复
Slacker-LLC Oct 8, 2026
9392ae6
核验轴向尺寸选择引用并修正驱动状态读取
Slacker-LLC Oct 8, 2026
d5effba
新增 Motion 求解与动画工具并修正零件运动元素与插入组件后的活动文档
Slacker-LLC Oct 13, 2026
ff50276
新增 Motion 载荷工具并修正运动特征识别与端点选择
Slacker-LLC Oct 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
342 changes: 342 additions & 0 deletions COVERAGE.md

Large diffs are not rendered by default.

149 changes: 145 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ It does not launch SOLIDWORKS, register an add-in, execute arbitrary code, or
touch the network. It attaches to a session you already have open and calls the
documented API — so if a tool can't do something, neither could a macro.

92 tools: sketching with real relations and driving dimensions, the solid
192 tools: sketching with real relations and driving dimensions, the solid
features you actually reach for, reference geometry, assemblies and mates, and —
importantly — a feedback channel, including screenshots returned as images so
the model can see what it just built.

覆盖范围包含 SolidWorks 本体与官方自带、随附模块,排除嘉立创等第三方插件。
当前仍未全覆盖;功能域、完成判据和缺口记录见 [COVERAGE.md](COVERAGE.md)。

A sibling server, [`autocad-mcp`](https://github.com/limuzi013/autocad-mcp),
does the same for AutoCAD.

Expand Down Expand Up @@ -131,9 +134,39 @@ late-bound Python cannot QueryInterface a `Face2` to `IEntity`.
`list_reference_planes`, `create_plane` (offset / angle / midplane / three points /
parallel-through-point), `create_axis`.

`create_reference_points` / `list_reference_points` 支持圆心、直线中点、面中心、
距离/百分比分布、均匀分布、交点、投影及草图点,读回模型坐标。
`create_coordinate_system` / `list_coordinate_systems` 创建与查询坐标系,
原点单位为 mm,输入角度为度;数值坐标系创建需要 SolidWorks 2022+。
参考点投影当前支持模型面,基准面投影仍是覆盖缺口。

`create_curve_through_points` / `get_curve_points` / `set_curve_points` 创建、
读取和修改通过 XYZ 点的原生参考曲线,输入和输出坐标均为 mm。
`composite_curve` 将相连的草图、边或参考曲线生成组合曲线。

### Sketching
`create_sketch` (on a plane **or a model face**), `edit_sketch`, `close_sketch`,
`list_sketches`, `list_sketch_segments`, `get_sketch_status`.
`create_sketch` (on a plane **or a model face**), `create_3d_sketch`, `edit_sketch`, `close_sketch`,
`list_sketches`, `list_sketch_segments`, `list_sketch_points`, `get_sketch_status`.

`create_3d_sketch` 在零件或装配体中创建原生 3D 草图;`draw_line` 支持 `z1_mm/z2_mm`,
`draw_point` 和 `draw_spline` 支持 `z_mm`。3D 坐标以模型坐标为准,单位为 mm;
2D 草图拒绝非零 Z,避免原生接口忽略坐标。编辑与关闭根据原生 `Is3D` 选用对应接口,
编辑时核验持久引用;读取较早草图时不误报为最新草图名称。
`list_sketch_points` 包含内部点与用户点,返回选择索引、类型和草图/模型坐标。
`draw_centerline` 支持 XYZ 构造线,并核验端点与构造属性;`draw_3point_arc` 支持
三点 XYZ 圆弧,核验半径、弧长、端点和点到曲线距离,共线/重合输入在创建前拒绝。
重叠/共端点圆弧原生结果曾偏离输入,返回未确认状态。圆/椭圆可在 2D 平面草图创建后
用 `convert_entities` 转换成空间曲线;转换逐点比较源曲线经坐标变换后的采样点与输出,
并读取实际类型,椭圆在本机变为样条。`draw_ellipse` 核验理论点和周长,直接 3D 创建会
产生无有效曲线的原生对象,因此在修改前拒绝。模型边/面与部分圆弧等输入的完整对应
几何核验仍未覆盖;返回的 `geometry_correspondence_confirmed` 明确区分已核验与未核验。
其他 3D 曲线、工作平面、完整约束/尺寸与更多建模组合仍有缺口。
`add_3d_dimension` 用两个原生点索引创建 X/Y/Z 投影尺寸;重建求解后恢复原草图编辑,
核验线性尺寸、点的持久引用及实际轴向距离。零件 XYZ 和装配体 XY 实测通过;
本机装配体 Z 接口返回空,明确失败并保留缺口。
含 3D 圆/椭圆转换的零件中,后续 X 尺寸也出现原生拒绝,仍为缺口;原生点选择前
验证持久引用,避免把选择成功当成选中了正确点。`list_dimensions` 保留原生状态值:
0 未知、1 从动、2 驱动,并修正 `driven` 标记。

Geometry: `draw_line`, `draw_centerline`, `draw_circle`, `draw_rectangle`,
`draw_arc`, `draw_3point_arc`, `draw_ellipse`, `draw_polygon`, `draw_slot`,
Expand All @@ -158,9 +191,98 @@ Parametrics: `add_relation`, `add_dimension`, `set_dimension`, `list_dimensions`
| `check_errors` | What SOLIDWORKS thinks is wrong — see below. |
| `set_view` | Named view plus zoom-to-fit. |

### 直接编辑

| 工具 | 功能 |
| --- | --- |
| `move_faces` | 面偏移、按 XYZ 平移或绕指定原点旋转;长度为 mm、角度为度。 |
| `delete_faces` | 删除面,可选择修补、填充或相切填充;仅删除可能将实体变成曲面。 |
| `replace_faces` | 用指定曲面替换模型面,目标面与替换曲面分别使用原生选择标记。 |

拓扑改变后重新查询面和边。删除与修补、替换面已通过实机体积/面积检查;
删除面的填充及相切填充模式仍待专项验证。

### Assemblies
`list_components`, `insert_component`, `add_mate`, `list_mates`,
`set_component_fixed`.
`set_component_fixed`, `set_component_visibility`, `set_component_suppression`,
`set_component_configuration`.

### 多实体、曲面与螺旋线

| 工具 | 功能 |
| --- | --- |
| `scale_bodies` | 选定实体等比例或按 X/Y/Z 缩放,支持质心与原点。 |
| `move_copy_bodies` | 实体平移、旋转或复制;平移和旋转分两次调用,长度为 mm、角度为度。 |
| `combine_bodies` | 多实体并集、差集与交集;差集的第一个实体为保留的主体。 |
| `delete_bodies` | 创建删除/保留实体特征。 |
| `mid_surface` / `get_mid_surface_data` | 原生自动中面与只读检查;读取面配对、厚度、面积、位置和缝合结果。非零位置未生效时返回失败。 |
| `preview_surface_trim` / `trim_surface` / `get_surface_trim_data` | 标准与相互曲面修剪;预览区域面积、边界与选择点,按区域索引保留或删除,并读取原生特征数据。 |
| `boundary_surface` / `get_boundary_feature_data` | 单/双方向有序曲线的边界曲面、按方向修剪、原生形成实体选项及只读检查;相切/曲率控制按边界采样核验几何,未确认时保留特征并返回失败。 |
| `wrap_sketch` / `get_wrap_data` / `set_wrap_parameters` | 单/多实体面的包覆三模式、解析/样条方法、三类方向及厚度/模式/方向/源草图修改;读回原生 `Face` 字段的前置几何。以体积、面分割、原生定义和持久引用快照验证。方法/网格不可读回;反向、清除方向及目标面修改未确认时返回失败。 |
| `dome` / `get_dome_data` / `set_dome_parameters` | 原生圆顶创建、定义与几何读取、高度/凹凸/椭球模式修改、目标面替换、单点/整体点草图约束和方向边。每个显式草图点转换到模型坐标,检查实际曲面距离;纯曲线草图不作为隐含点约束。清除约束/方向核验引用是否实际消失,本机请求被忽略时返回失败并保留特征。另以体积、中心高度、24 点椭球采样及持久引用核验。 |
| `surface_sweep` | 开口/闭合草图或圆截面扫描;导引线、法向控制、扭转、第一/第二/双向扫描,读回原生参数。要求 SW 2018+。 |
| `delete_surface_holes` | 删除选定曲面孔边界,保留未选孔;支持单孔与多孔。 |
| `surface_extrude` / `planar_surface` | 从草图生成拉伸曲面或平面曲面。 |
| `offset_surface` / `knit_surfaces` / `thicken_surface` | 偏移面、缝合曲面和曲面加厚;读取实际曲面或实体结果。 |
| `list_surface_bodies` | 查询曲面体及其面积,面积单位为 mm²。 |
| `create_helix` | 从圆草图按螺距和圈数生成螺旋线,读取实际螺距、圈数及高度。 |

实体操作沿用 `selection`,例如 `{"selection": {"bodies": [0, 1]}}`。
索引取自 `list_bodies`,几何变化后需重新查询。曲面体索引与实体索引独立,
曲面选择使用 `surface_bodies`,索引取自 `list_surface_bodies`。

修剪先调用 `preview_surface_trim`,再把返回的区域索引传给 `trim_surface`。
标准修剪指定一个 `trim_selection`;相互修剪设置 `mode=mutual`,只指定目标曲面体。
区域索引按目标顺序、包围盒和面积排序,几何变化后必须重新预览。
复杂区域可用 `picked_points_mm` 指定实际落在区域上的选择点。
相互修剪在本机即使 `knit=false` 仍会合并相接曲面;工具返回失败并保留特征信息。
实体形成选项、更多复杂曲面组合和旧版软件尚待覆盖或实测。

边界曲面的 `direction1`、`direction2` 是有序曲线列表,每项包含一个 `selection`。
曲线需先全部选择,再设置条件;创建后读取实际曲线数量、影响范围、相切类型和实体类型。
`create_solid=true` 使用原生 `InsertNetBlend2` 的形成实体选项,旧接口不支持该选项。
相切/曲率连续性检查使用输入面边界的几何采样和输出曲面的法向、第二基本形式,
参数读回正确而几何不符时仍返回失败。本机圆端面案例的法向差为 90°,该细项尚未完成。
方向向量、中心线、控制柄编辑和更多复杂边界条件仍待覆盖。

### 钣金与焊件

| 工具 | 功能 |
| --- | --- |
| `sheet_metal_base_flange` | 创建基体法兰,设置板厚、折弯半径与 K 因子。 |
| `list_sheet_metal_features` / `get_sheet_metal_parameters` / `set_sheet_metal_parameters` | 读取和修改钣金参数;默认操作原生模板参数,可指定实体钣金特征。 |
| `set_flat_pattern` / `export_flat_pattern` | 展开、折叠与 DXF 导出;导出要求零件已保存。 |
| `create_weldment` | 创建焊件特征。 |
| `list_weldment_profiles` / `get_weldment_profile_configurations` | 查询本机轮廓与规格配置。 |
| `insert_structural_member` | 按草图线段组、轮廓配置和角度创建结构构件。 |
| `list_cut_list` / `update_cut_list` | 读取和更新切割清单,返回实体与解析属性。 |

### 官方 Motion 算例

`list_motion_studies`、`create_motion_study`、`activate_motion_study`、
`duplicate_motion_study`、`delete_motion_study`、`set_motion_study_type`、
`set_motion_study_timing`。

时间单位为秒。零件与装配体均支持基础算例管理;工具读取实际支持的类型位掩码,
无法使用的 Basic Motion 或 Motion Analysis 会返回失败,不自动加载模块。
算例管理已验证,动力学求解、载荷、接触、结果曲线与动画输出仍待覆盖。

### 文档、配置、属性与方程

| 工具 | 功能 |
| --- | --- |
| `list_open_documents` / `activate_document` / `close_document` | 查询、切换和关闭已有文档;关闭有未保存修改的文档需显式传入 `discard_changes=true`。 |
| `list_solidworks_sessions` / `select_solidworks_session` | 查询已经运行的实例及其文档,按 `process_id` 明确选择后续 MCP 调用连接的实例。 |
| `list_configurations` / `create_configuration` / `activate_configuration` / `delete_configuration` | 查询、创建、激活和删除配置;不能删除活动配置。 |
| `list_custom_properties` / `get_custom_property` / `set_custom_property` / `delete_custom_property` | 查询和编辑文档级或配置级自定义属性,包括原始值、解析值与类型。 |
| `list_equations` / `add_equation` / `set_equation` / `delete_equation` / `evaluate_equations` | 查询和编辑方程与全局变量,使用 SOLIDWORKS 方程语法,例如 `"Width" = 25mm`。 |
| `list_materials` | 搜索实际配置的材质库,返回可传给 `set_material` 的准确名称与数据库路径。 |

`configuration` 为空时操作文档级属性,非空时必须是已存在的配置名称。
实例选择只作用于当前 MCP 服务进程;`process_id=0` 恢复默认 COM 注册。
可通过 `SW_MCP_SESSION_PID` 指定启动时连接的已有实例;显式工具选择优先。
实例退出后调用会失败,不会自动切换到另一个实例。查询可读不代表建模命令正常。
方程里的单位由 SOLIDWORKS 语法解释,应明确写出 `mm` 等单位;方程索引在删除后变化。

### Engineering drawings
`create_drawing`, `list_sheets`, `add_sheet`, `activate_sheet`,
Expand Down Expand Up @@ -297,6 +419,22 @@ ring, swept rod and lofted cone match their closed-form volumes; a 5-degree
under its profile; `through_all_both` removes the full cylinder rather than half
of it. The limitations above are what survived that pass.

新增 28 个工具使用 `tests/live_expansion_regression.py` 验证。该脚本只修改新建测试文档,
结束时关闭它们并恢复原活动文档;装配体引用的测试零件保存在输出根目录下
`.expansion-tests/<uuid>/`。验证包括缩放体积、旋转包围盒、布尔运算体积、
曲面面积、螺旋线高度、配置、属性、方程以及组件状态的读取结果。

```powershell
python tests/live_expansion_regression.py
```

The original 92 tools were also exercised on SOLIDWORKS 2016 SP3 with a German
install. The 28 expansion tools have been checked on SOLIDWORKS 2026 SP3.2;
their behaviour on older releases has not yet been verified. Where a release lacks the newest
numbered method (`FeatureCut4`, `FeatureLinearPattern5`, `CreateDetailViewAt4`,
...) the tool falls back to the earlier variant with the arguments it takes; on
newer releases the newest name is always tried first, so nothing changes there.

## Layout

| Module | Contents |
Expand All @@ -310,6 +448,9 @@ of it. The limitations above are what survived that pass.
| `sw_assembly.py` | Components and mates |
| `sw_drawing.py` | Sheets, views, model items, dimensions, center marks, notes |
| `sw_demo.py` | Basketball demo, opt-in via `SW_MCP_DEMO_TOOLS` |
| `sw_manage.py` | 文档切换、配置、自定义属性、方程、材质库搜索 |
| `sw_multibody.py` | 多实体操作、曲面、螺旋线和曲面面积查询 |
| `tests/live_expansion_regression.py` | 新增工具的实机回归与测试文档清理 |
| `tests/live_p0_regression.py` | Live regression checks for the confirmed P0 part/sketch defects |
| `tools/tlb_probe.py` | Reads signatures and enums straight off your installed type library |
| `server.py` | Registry assembly and stdio dispatch |
Expand Down
9 changes: 9 additions & 0 deletions solidworks_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@
from . import sw_assembly # noqa: F401
from . import sw_drawing # noqa: F401
from . import sw_demo # noqa: F401
from . import sw_manage # noqa: F401
from . import sw_multibody # noqa: F401
from . import sw_boundary # noqa: F401
from . import sw_wrap # noqa: F401
from . import sw_dome # noqa: F401
from . import sw_sheetmetal # noqa: F401
from . import sw_weldment # noqa: F401
from . import sw_motion # noqa: F401
from . import sw_geometry # noqa: F401


server = Server("solidworks-mcp")
Expand Down
71 changes: 68 additions & 3 deletions solidworks_mcp/sw_assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
clear_selection,
component_transform,
document_info,
flag_methods,
iter_components,
logger,
mm_point,
Expand All @@ -47,6 +48,7 @@
to_mm,
tool,
value,
whats_wrong,
)


Expand Down Expand Up @@ -120,11 +122,22 @@ def insert_component(args: dict[str, Any]) -> dict[str, Any]:
if component is None:
return result(False, f"SOLIDWORKS did not insert {path.name} into the assembly.")
rebuild(doc)
# The silent OpenDoc6 above activates the referenced part, so the assembly is
# no longer the active document and every follow-up assembly tool would fail
# its own document check. Put the assembly back and report the readback.
title = str(value(doc, "GetTitle"))
active = app.ActiveDoc
if active is None or str(value(active, "GetTitle")) != title:
app.ActivateDoc3(title, False, 0, byref_long(0))
active = app.ActiveDoc
active_title = str(value(active, "GetTitle")) if active is not None else None
return result(
True,
f"Inserted {path.name}.",
active_title == title,
f"Inserted {path.name}." if active_title == title else
f"Inserted {path.name}, but SOLIDWORKS left another document active.",
component=str(safe(component, "Name2", "")),
path=str(path),
active_document=active_title,
)


Expand Down Expand Up @@ -193,7 +206,7 @@ def add_mate(args: dict[str, Any]) -> dict[str, Any]:
{},
)
def list_mates(args: dict[str, Any]) -> dict[str, Any]:
from sw_core import as_list, feature_property, iter_feature_objects
from .sw_core import as_list, feature_property, iter_feature_objects

_, doc = require_assembly()
reverse_types = {v: k for k, v in MATE_TYPES.items()}
Expand Down Expand Up @@ -240,3 +253,55 @@ def set_component_fixed(args: dict[str, Any]) -> dict[str, Any]:
clear_selection(doc)
rebuild(doc)
return result(True, f"Set fixed={args.get('fixed', True)} on {len(names)} components.", components=names)


def _named_component(doc: Any, name: str) -> Any:
for component in iter_components(doc):
if str(safe(component, "Name2", "")) == name:
return component
raise RuntimeError(f"No component named '{name}'. Use list_components first.")


def _component_result(doc: Any, ok: bool, message: str, **data: Any) -> dict[str, Any]:
rebuild(doc)
problems = whats_wrong(doc)
return result(ok and not problems, message, problems=problems, **data)


@tool("set_component_visibility", "Show or hide a named assembly component without suppressing it.",
{"name": {"type": "string"}, "visible": {"type": "boolean"}}, ["name", "visible"])
def set_component_visibility(args: dict[str, Any]) -> dict[str, Any]:
_, doc = require_assembly()
component = _named_component(doc, str(args["name"]))
desired = 1 if args["visible"] else 0
component.Visible = desired
actual = int(value(component, "Visible"))
return _component_result(doc, actual == desired, "Updated component visibility.", name=args["name"], visible=actual == 1)


@tool("set_component_suppression", "Suppress or fully resolve a named assembly component in the active configuration.",
{"name": {"type": "string"}, "suppressed": {"type": "boolean"}}, ["name", "suppressed"])
def set_component_suppression(args: dict[str, Any]) -> dict[str, Any]:
_, doc = require_assembly()
component = flag_methods(_named_component(doc, str(args["name"])), "SetSuppression2")
code = int(component.SetSuppression2(0 if args["suppressed"] else 2))
actual = bool(value(component, "IsSuppressed"))
return _component_result(doc, actual == bool(args["suppressed"]), "Updated component suppression.", name=args["name"], suppressed=actual, status=code)


@tool("set_component_configuration", "Switch a component to an existing configuration in its referenced part/subassembly, then rebuild.",
{"name": {"type": "string"}, "configuration": {"type": "string", "minLength": 1}}, ["name", "configuration"])
def set_component_configuration(args: dict[str, Any]) -> dict[str, Any]:
_, doc = require_assembly()
component = _named_component(doc, str(args["name"]))
model = value(component, "GetModelDoc2")
if model is None:
return result(False, "Resolve the component before changing its configuration.")
name = str(args["configuration"])
names = [str(n) for n in value(model, "GetConfigurationNames") or []]
if name not in names:
return result(False, "Referenced configuration does not exist.", available_configurations=names)
component.ReferencedConfiguration = name
rebuild(doc)
actual = str(value(component, "ReferencedConfiguration"))
return _component_result(doc, actual == name, "Updated component configuration.", name=args["name"], configuration=actual)
Loading