SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
Where swx stands in the ecosystem
swx v0.3.0 measured against the Adom Fusion 360 bridge v1.9.341 (the gold standard we mirror) and against every public SOLIDWORKS MCP server we could find · written 2026-09-03
Executive summary
- swx is the only SOLIDWORKS implementation here with a published live-run record. Three runs against a real SOLIDWORKS Design Professional for Makers 2026 install (22-aborted, 120/9, then 125 passed / 5 failed), 19 verbs proven end to end, with measured p90 timings. One competitor (SolidPilot) also claims live validation and is credible about it; the other three are explicit that most or all of their tools are unvalidated, mock, or hobby-grade.
- On raw modeling breadth we are behind SolidPilot — its sketch/feature/assembly/drawing surface is deeper than ours and it is the most mature project in this space by a wide margin.
- On safety we are ahead of all five, and alone. No other project has a write gate. swx writes are deny-by-default at a single choke point, enforced independently at two layers, hardened over eight adversarial review rounds, and the posture held through every live run — three times the bridge failed CLOSED rather than touch the wrong document.
- Our other unique strengths: BOM-first and configuration-aware design (BOM aggregates per
(file, configuration) pair — nobody else models this); native GLB with no optimisation service;
an action ledger plus measured per-verb timings; census-not-dismiss dialog etiquette with
neverAutoAnswerclasses; and real host-ecosystem integration (Adom Bridge verbs, the user's Activity Log, a shipped skill) where every competitor is a bare MCP server for Claude Desktop. - Our real gaps, stated plainly: no cloud/3DEXPERIENCE document access (21 Fusion verbs; a separate OAuth project of roughly the size of the Fusion bridge's APS work); assemblies-with-components, drawings and 2D exports are mock-only because the Makers edition would not let an assembly be populated; and there is no in-process scripting host — a typed JSON DSL stands in.
- Launch was our headline "cannot", and that changed today.
CoCreateInstancereturnsCO_E_SERVER_EXEC_FAILUREon the Connected editions, but a sanctioned launch path via the 3DEXPERIENCE shortcut chain (CATSTART.exe→SWXDesktopLauncher) was discovered 2026-09-03. Implementation is in progress and not yet live-proven. - Scripting has a second route now too: SOLIDWORKS
RunMacro2for.swpVBA macros, VSTA, and C# add-ins are under investigation — with the caveat that the Makers edition restricts third-party add-ins while still running macros. Four of the five competitors already lean on VBA; we do not yet. - Licensing is simple and decision-relevant: exactly one copyleft player — SolidPilot is AGPL-3.0 with a paid commercial option — and everything else, ours included, is MIT. We can read and learn from SolidPilot; we must not vendor its code.
- Electronics is not a gap. 51 of the Fusion bridge's 132 verbs are Fusion Electronics, EAGLE libraries, or Autodesk-specific plumbing. SOLIDWORKS has no concept to bridge to, and no competitor attempts it either.
How to read the cells
| Mark | Means |
|---|---|
| ✓ live | Executed against a real, licensed CAD install and observed to do what it claims. |
| ✓ | Built and shipped, or claimed by the project's own README. Evidence level is stated per row. |
| ⚠ mock | Built and mock-tested only; never executed live in any form. |
| partial | Some of the capability, materially incomplete. |
| ✗ | Absent. |
| n/a | No concept exists to bridge to in that product. |
| WIP | Route identified, implementation in progress, not yet proven. |
| ? | Could not be determined from the repository. |
Evidence discipline: for Fusion bridge and swx, cells come from source we hold — the Fusion
bridge's own describe.py catalog (133 entries, 132 real verbs) and docs/FUSION-PARITY-REPORT.md.
For every competitor column, cells are read-from-README unless the row note says otherwise. Nobody
in the competitor set was installed or run. Licences and star counts were verified against the GitHub
API on 2026-09-03, not read off a badge.
The master table
35 capability rows × 7 implementations. Verb counts: Fusion bridge 132, swx 60, SolidPilot ~46 tools, vespo92 ~30+, bartels 122, Schildkraut ~16 tools + 100+ VBA templates, alisamsam 22.
| # | Capability | Fusion bridge | swx v0.3 | SolidPilot (AGPL-3.0!) | vespo92 (MIT) | bartels (MIT) | Schildkraut (MIT) | alisamsam (MIT) |
|---|---|---|---|---|---|---|---|---|
| 1 | Session lifecycle — attach, stop, kill | ✓ | ✓ live attach · stop: unproven — the one observed ExitApp "decline" had a dirty Part1 open (save-prompt stall, not a decline); no stop event at 0 docs is in the ledger. v1 also holds a COM ref while checking and gates on unsaved-count not open-count (docs/QUIT-INVESTIGATION.md); graceful-quit ladder = 0.5.0 work · kill: never (policy) |
✓ attach | ? | ✓ attach | ? | ✓ attach |
| 2 | Launch the CAD application (and install it) | ✓ launch + silent install | ✓ LIVE-PROVEN 2026-09-11 — attributable. shellExecute (ShellExecuteExW + SEE_MASK_NOCLOSEPROCESS) handed back a real handle for the Platform .lnk (CATSTART pid 131272) and that chain reached Run Begin; the old cmd-route stall is gone. Same run found the bridge killing its OWN chain while the user was at the 3DEXPERIENCE ID sign-in — a native WebView2 window with no UIA controls — because the sldworks deadline fired on a wait that was not a stall. Fixed 0.6.0: the sign-in window is recognised by class and owner pid, every deadline PAUSES while it is up, nothing is killed or escalated, the user is toasted, and a session that attaches after the sign-in is re-attributed (attachedAfterSignIn) instead of being recorded as somebody else's. LIVE AGAIN 2026-09-30, through the bridge ab hosts (adom-bridge 2.1.163 auto-installed the released 0.8.9): tools/launch-gate.py passed every launch claim — shellExecute, attributed, Run Begin 28.8 s, the helper sign-in step passed without a sign-in, COM attached 139.8 s |
✓ claims COM launch (refused on Connected) | ✗ | ✗ needs SW already open | ? | ✗ needs running instance |
| 3 | Requires an in-app add-in | yes (3 verbs to manage it) | no — out-of-process COM | no (C# COM server) | no | no | no | no |
| 4 | Open a local file · disk discovery | ✓ open · ✗ discovery (cloud-native) | ✓ live open · ✓ find_files |
✓ open · ✗ | ✓ (untested) | ✓ | ✓ | ✓ open · ✗ |
| 5 | Create a new document | ✗ (docs arrive from cloud/import) | ✓ live | ✓ part + assembly | ✓ (untested) | ✓ | ✓ | ✓ part + assembly |
| 6 | Save / Save As with overwrite protection | ✓ cloud save · ✗ overwrite guard | ✓ live save_as · ✓ overwrite guard (unique) | ✓ save · ✗ guard | ✓ (untested) · ✗ guard | ✓ · ✗ guard | ✓ · ✗ guard | ✓ · ✗ guard |
| 7 | Cloud document store — search, list, open, up/download | ✓ 21 verbs (APS Data Management) | ✗ lacking — swx_cloud_status returns the honest probe |
✗ | ✗ | ✗ | ✗ | ✗ |
| 8 | Cloud / vendor sign-in + OAuth | ✓ 9 verbs (incl. 2FA, web sign-in) | ✗ lacking | ✗ | ✗ | ✗ | ✗ | ✗ |
| 9 | Parametric modeling — sketch → feature | ✓ (Python script in-process) | ✓ live typed DSL (50×30×20 solid, p90 10.2s) | ✓ live — deepest surface here | partial (basic ops only) | ✓ claimed | ✓ via VBA templates | ✓ basic |
| 10 | In-process scripting host (arbitrary code) | ✓ Python eval inside Fusion |
adapted — typed JSON DSL, validated pre-COM; swx_com_eval escape hatch |
✗ by design (deterministic compiler) | ✗ | ✗ | ✗ | ✓ execute_python in SW context |
| 11 | Macros / VBA — generate, record, execute | n/a (Fusion has no VBA) | WIP — RunMacro2 / VSTA / C# add-in under investigation |
✗ explicitly unsupported | partial (gen works, exec untested) | ✓ | ✓ strongest (record/export/execute + 100+ templates) | ✗ |
| 12 | Assemblies — insert components, mates | ✓ via script | ⚠ mock — AddComponent5 returned Nothing on this edition |
✓ live insert + mate + diff | ✗ | ✓ claimed | ✓ via VBA | partial (create doc only) |
| 13 | Drawings — create, views, dimensions | ✗ no drawing verbs | partial — creation ✓ live, views/dims not built | ✓ live 9 tools; 9 real drawings reconstructed | ✓ (untested) | ✓ claimed | ✓ via VBA | ✗ |
| 14 | Import neutral CAD (STEP etc.) | ✓ | ✓ live (p90 7.8s) | ✓ via 3D Interconnect | ? | ? | ? | ✗ |
| 15 | Export 3D — STEP/IGES/STL/3MF/SAT/Parasolid | ✓ 8 formats | ✓ live 6 proven; 17 formats in table; OBJ refused by SOLIDWORKS | ✓ STEP/IGES/STL | ✓ (untested) | ✓ | ✓ | ✗ none |
| 16 | Export native GLB (web 3D) | ✓ but needs an optimisation service | ✓ live, direct — unique | ✗ | ✗ | ✗ | ✗ | ✗ |
| 17 | Export 2D / document — PDF, DXF, DWG | ✓ DXF/DWG · ✗ PDF | ⚠ mock all three (refused for a part; untested from a drawing) | ✓ PDF/DWG/DXF | ✓ (untested) | ✓ | ✗ | |
| 18 | BOM | ✓ assembly + electronics BOM | ⚠ mock — *but per (file, configuration), the richest design here* | ✗ on the roadmap | ✗ | ✗ | ✓ table insertion | ✗ |
| 19 | Mass / physical properties | ✓ | ✓ live (aluminium, 81 g agreeing) | ✓ live (verified ≤1%) | ✓ (untested) | ✓ claimed | ✓ claimed | ✗ |
| 20 | Design-health — interference detection, rebuild census | ✗ neither | partial — interference ⚠ mock (object confirmed live), rebuild_check built |
partial (analyze_model/verify_state; no interference) |
✓ (untested) | ✗ explicitly not yet | ✓ via VBA | ✗ |
| 21 | Parameters / dimensions — read and drive | ✓ read | ✓ live — drove a dimension to 25 mm, model moved | ✓ modify_dimension |
✓ (untested) | ✓ claimed | ✓ equations | ✗ |
| 22 | Custom properties (file and per-configuration) | partial (buried in the attribute model) | ✓ props_get/props_set |
✗ | ✗ | ? | ✓ | ✗ |
| 23 | Configurations / design tables | ✗ no equivalent concept | ✓ configuration-aware (BOM, properties) · ✗ design tables | ✗ | partial (vba_configurations, untested) |
partial | ✓ strongest (design tables + SQL) | ✗ |
| 24 | Pack and Go — collect a design + all references | ✗ | ✓ built (gated), ⚠ mock | ✗ | ✗ | ✗ | partial (batch ops) | ✗ |
| 25 | PDM / vault integration | n/a | ✗ not built | ✗ | ✗ | ✗ | ✓ only one (5 tools) | ✗ |
| 26 | Application preferences — read and write | ✓ incl. driving the settings modal | ✓ live (written, then read back) · modal driving declined by design | ✗ | ✗ | ✗ | ✗ | partial (set_units) |
| 27 | Screenshots + window management | ✓ | ⚠ mock (delegated to ab; SKIPPED in live runs) | ✗ | ✗ | ✗ | ✗ | ✗ |
| 28 | Blocking-dialog handling | ✓ dismisses them | adapted — censuses by default; neverAutoAnswer classes never closed |
✗ | ✗ | ✗ | ✗ | ✗ |
| 29 | Electronics — schematic, PCB, Gerbers, CPL, design rules | ✓ 15 verbs | n/a | n/a | n/a | n/a | n/a | n/a |
| 30 | Component libraries / 3D packages (EAGLE .lbr) |
✓ 23 verbs | n/a | ✗ | ✗ | ✗ | ✗ | ✗ |
| 31 | Vendor MCP-server proxy | ✓ 6 verbs (Autodesk ships one) | n/a — Dassault ships none | n/a (is itself an MCP server) | n/a | n/a | n/a | n/a |
| 32 | Bridge infrastructure — self-describe, shipped docs, guided demo, uninstall | ✓ all four | ✓ describe/docs/uninstall · ✗ demo (deferred v0.4) | partial (13 MCP resources) | ✗ | partial (docs audit) | partial (resource registry) | ✗ |
| 33 | Action ledger + measured per-verb timings | ✓ ledger, verb times, live feed, alerts | ✓ ledger + timings recorded live | ✗ (dev log only) | ✗ | ✗ logging only | partial ("enhanced logging") | ✗ |
| 34 | Deny-by-default write gate | ✗ no gate, no confirm/reason in its catalog | ✓ live — unique. Two independent layers, 12 adversarial rounds, held in all 3 live runs. HONESTY NOTE: pass 12 (2026-09-09) found that an un-stat-able destination read as FREE — Path::exists() is false both for "nothing is there" and for "could not look" (a parent it cannot traverse, a UNC share it has no token for, a device not ready, an over-length path), and the com host does not share a filesystem view with SOLIDWORKS. Fixed in 0.5.9: symlink_metadata gives three answers and an unreadable one REFUSES (destination_unverifiable) in BOTH layers, tested in both |
✗ | ✗ | partial ("adapter safety wrappers") | partial (macro exec needs permission) | ✗ |
| 35 | Host-ecosystem integration (Adom Bridge, Activity Log, skill) | ✓ native | ✓ native | ✗ MCP clients only | ✗ | ✗ | ✗ | ✗ |
| 36 | Ownership persists across bridge/host restarts (bridge-created docs stay closable without opt-in) | ✗ (no ownership model) | ✓ live 2026-09-08 — owned-docs.json keyed to the SOLIDWORKS process; proven create → host kill → close in default posture. And across UPDATES since 0.9.0: the registry lived in ab's install cache until then, so the 0.8.9 auto-install wiped it (row 49); it now lives in the data root, and the first start after the move restores what an older bridge recorded (pinned: the migration runs before the registry is read) |
✗ | ✗ | ✗ | ✗ | ✗ |
| 37 | Honest UNKNOWN instead of a fabricated empty/zero (doc list, counts, dialogs, interference) | ✓ LIVE 2026-09-09 — on a real 2144-document session swx_docs answers in 3.4 s with count:2144, truncated:true, a 10-doc sample (8 import temps) — after 0.5.4 wedged 30 s on the same session (fixed 0.5.5: bounded GetFirstDocument/GetNext walk, never GetDocuments above the cap; simulator now charges per-doc latency) |
⚠ 0.4.x-0.5.5, mock-proven; the ENUMERATION half FAILED LIVE — docs_enumeration_failed, Option counts, unsaved_unknown, count:null semantics in hints; 29 adversary tests. Live 2026-09-09: swx_docs still timed out at 30s and the com host was killed on a 2144-document session — the degrade path called GetDocuments (one call, every handle) and then GetPathName on all 2144. GetDocumentCount answered in 0.7s. The mock's enumeration was instant, so this row was mock-proven and false live. Fixed in 0.5.5 (walk GetFirstDocument/GetNext for the sample only, time-boxed; the drain walks a bounded window too) with the live session held in the suite via a per-document latency model — re-proof on the live 2144-doc session pending |
✗ | ✗ | ✗ | ✗ | ✗ |
| 38 | Hung / exhausted host detection, and BUSY vs DEAD (Not Responding + real COM timeout; NewDocument-returns-nothing; CPU/memory delta over a sample) | ✗ | ✓ 0.5.1 evidence-based host_app_hung / host_app_exhausted + verdict:"busy"|"dead"|"unknown" from cpuActiveSeconds/memoryDeltaMB — measured live: 17.9 GB not-responding for ~5 min at ~70% of a core and it RECOVERED, so "not responding" now advises WAIT, not "end the task". One reading never says dead |
✗ | ✗ | ✗ | ✗ | ✗ |
| 39 | Stalled-launcher recovery with attribution law (kill only a chain proven ours by handle; never daemons, never sldworks) | ✗ | ✓ shipped 0.4.4, 4 adversary rounds, live-proven 2026-09-11 — the handle world is confirmed on this machine, and the one live defect was the opposite of an over-eager kill law: it killed a chain that was correctly WAITING (sign-in), fixed in 0.6.0. No daemon and no sldworks.exe has ever been touched | ✗ | ✗ | ✗ | ✗ | ✗ |
| 40 | Crash-reporter recovery (click "Restart SOLIDWORKS Design" once, structured match, ledgered) | ✗ | shipped, DISABLED by default until the real control-tree reply is captured | ✗ | ✗ | ✗ | ✗ | ✗ |
| 41 | COM retry-on-reject (busy host: RPC_E_CALL_REJECTED / RETRYLATER backoff on every call) | ? | ✓ live 0.3.3 — 50-read smoke gate, 0 under-reporting, 11 rejects absorbed | ✗ | ✗ | ✗ | ✗ | ✗ |
| 42 | Real-work proof (multi-assembly build + BOM exported from the assembly, verified against a packet) | ✓ (electronics) | ✓ live — NSF crate: 5 assemblies, 383 placements, 32-row BOM, 28/28 part numbers match | ✗ | ✗ | ✗ | ✗ | ✗ |
| 43 | Import / resource lifecycle — no leaked temps, drainable, enumeration never wedges | ✗ | ✓ 0.5.0 — enumeration degrades above a cap ({count,truncated,sample}, never a 30s timeout+kill); swx_close_import_temps drains STEP/IGES …\Temp\swx<pid>\IC~~\… temps in the DEFAULT posture (path is the ownership proof, survives a pid change); import asserts a net +1. Root-caused a live 1342-doc / 8 GB leak. 0.5.3: the resolved %TEMP% is the WHOLE location proof (8.3-aware, no shape-test fallback), and with no resolved root the drain refuses (temp_root_unknown) instead of closing nothing quietly. 0.5.4: the report says which root it compared against (tempRoot) and counts documents that carry the launcher's tail but sit elsewhere (importTempsElsewhere + a sample), so a drain that matched nothing can no longer claim it drained everything. 0.5.6: the victim is CLOSED by the path it was chosen by (it was closed by TITLE, which CloseDoc resolves by name without prompting — a live session held temps sharing a saved file's title), a shared title is refused and reported, and every close is verified by path — the mismatch case is real, because ab's %TEMP% need not be the one SOLIDWORKS used |
✗ | ✗ | ✗ | ✗ | ✗ |
| 44 | Graceful QUIT that is measured, not assumed (never a kill, never answers a dialog, proves the exit from the process census) | ✗ | ✓ LIVE-PROVEN 2026-09-17 (rung a) — swx_stop {userAuthorized, maxRung:"a"} quit a bridge-launched session on the FIRST rung (UserControl=false; ExitApp; every COM reference released), verified absent from the process census; swx_shutdown then removed a stray empty instance (pid 145188) and tasklist showed no sldworks.exe at all. ExitApp is NOT declined at zero documents on this edition — the long-held host_app_stop_declined belief was a SAVE-PROMPT STALL misread as a refusal, which is why the ladder was built pinned at rung (a) and why the preserve-then-close sweep is what actually unblocked it. A rung ladder (a ExitApp → f Restart Manager without RmForceShutdown), pinned at rung (a); 7 re-measured preconditions where UNKNOWN refuses and force waives the UNSAVED question ONLY; every COM reference released before and after each rung, with outstanding refs named in the report; success = this pid AND this creation time absent from the census, never GetActiveObject; per-session children reaped while the documented platform daemons are left alone; a dialog stops the ladder permanently and is never answered; nothing disowned until the exit is verified. every precondition re-measured before EVERY rung (a mid-ladder refusal is a real outcome), the exit POLLED to the rung's budget rather than sampled once (a real ExitApp returns before the process goes), the dialog census covering the swCefSubProc web-view children by parentage, the count cross-checked against the enumeration, and the message rungs re-verifying window ownership before they send. tools/quit-gate.py proves the session was bridge-launched, and its FULL CYCLE PASSED LIVE 2026-09-30 through the bridge ab hosts: rung (a), process gone 29.5 s, per-session servers reaped, nothing on screen, no crash reporter, every rung reported, and SOLIDWORKS relaunched by the bridge 54.7 s later. The gate now reaches the bridge through ab's verb routing (the side-loaded dev copy on 24695 is terminated by ab 2.1.163 within 30 s) and passes userAuthorized:true — the standing authorization — rather than the write-gate pair, which the hosted bridge rightly never enables. MEASURED 2026-10-01: the decline is about session HISTORY — rung (a) was declined three times on a session that had never held a document and quit in 3.4 s once one had been created and closed; since 0.9.3 the ladder PRIMES such a session (empty, no dialog, user-authorized only) and asks again — LIVE-PROVEN 2026-10-01 on 0.9.4: declined at 130 s, primed, quit in 3.4 s (declines measured from 50 s to 8 min old; such sessions quit unprimed at ~25 s), and swx_status exposes the session's document history — and the gate's "no longer running" claim — which had passed vacuously after declines — now requires running:false and is self-tested |
✗ | ✗ | ✗ | ✗ | ✗ |
| 48 | A title collision between SAVED documents is impossible here — measured, not assumed | ✗ | ✓ MEASURED LIVE 2026-09-17 — tools/drain-gate.py --fixture new copied a bridge-created document's own file to a second directory under the same basename and called swx_open on it. SOLIDWORKS REFUSED: errors = 65536 (swFileWithSameTitleAlreadyOpen). So the drain's title-collision guard — which refuses to close any document whose title another open document shares, and names both paths — can only ever fire for PATHLESS documents, which is exactly the state identity-at-birth removes. The guard stays (a document the bridge did not create can still be pathless, and an older bridge's leftovers are), and the measurement is recorded next to it in com.rs so nobody "simplifies" it on the assumption that saved collisions are the common case. No MCP server measures this at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 52 | Never ends a session the user is working in (a measured user-presence guard on every quit and sweep) | ✗ | ✓ 0.9.9, from an event MEASURED 2026-10-01: Drew took over a bridge-launched session — a "leave as found" quit met his File Open dialog, and minutes later the session held his 34-document crate assembly. Every quit, sweep and priming now measures presence (SOLIDWORKS foreground + input under 120 s, documents the bridge did not open, an earlier take-over), refuses user_is_active with the evidence, fails closed on an unreadable measurement, and marks the session taken over for good; only the user's explicit override proceeds, and the gates never pass it. 0.9.10: a document is the bridge's only if a bridge verb opened or created it — in a session the user launched, every document is theirs. No MCP server has a presence guard at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 53 | Signs the user in, unattended, without ever seeing the password (3DEXPERIENCE ID sign-in from the user's own local vault) | ✗ | ✓ 0.9.13, from Drew's request 2026-10-02: the login window's accessible inventory is captured every time it appears; swx_sign_in recognizes the form from that inventory alone, takes the login from the user's pup vault on their laptop through ab, types it through UI Automation, ticks "Remember me", verifies by the window closing, and scrubs the password from every reply, log and ledger line; it fails closed on a missing login, an unknown form or a second step, and never retries a rejected password. No MCP server signs in at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 54 | Renders a product shot at any size, and leaves the user's view as it was (high-resolution image export from the viewport) | ✗ | ✓ 0.9.18, MEASURED LIVE 2026-10-05 (3840×2160 of the 110-document Moveo assembly in 11.6 s, every setting restored; 0.9.19 accounts for every requested setting and adds zoomFactor; 0.9.20 reads every set back, so a setting SOLIDWORKS ignores — RealView on an uncertified GPU, measured — is reported setIgnored with a note, never "applied"): swx_render_image sets view, style, RealView, ambient occlusion, shadows, perspective and a plain background, exports through IModelDoc2::SaveBMP at up to 8192 px a side, converts to PNG and reads the size back from the file (capped:true when only the window size came out); every changed setting is captured, restored on every path, read back and listed; the swconst ids are read from the installed interop DLL, never guessed; a render that changes the screen respects the user-presence guard. The Fusion bridge has no render verb, and no MCP server renders at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 55 | Supports the user's OWN SOLIDWORKS release, with an audit and a self-test (not "whatever version the author has") | ✗ | ✓ 0.10.0, from issue #1/#2 (SOLIDWORKS 2021): all 149 COM members the bridge calls were checked against help.solidworks.com (newest: 2017), so >=2021 is declared as SUPPORTED with 2026 as TESTED (docs/COMPATIBILITY.md); swx_status.solidworks.versionSupport reads the release at attach; a version-gated call refuses needs_solidworks_version by name; swx_selftest returns per-verb pass/fail on any install (read-only, or a scratch part it closes) | ✗ | ✗ | ✗ | ✗ | ✗ |
| 51 | Dialogs judged by MEASURED MODALITY, not by existence (a notification never blocks; a modal always does) | ✗ | ✓ LIVE-PROVEN 2026-10-01 on 0.9.4 — with the 3DEXPERIENCE "Connected" notice on screen, swx_stop quit in 5.1 s and reported it as a notification with its evidence. 0.9.4, from a blocker MEASURED 2026-10-01: the 3DEXPERIENCE "Connected to …" notice — a title-less #32770 tool window whose owner frame stayed ENABLED for 95 s, with no Button-class control — blocked every quit, sweep and import for minutes. Now a window blocks when its kind is known-blocking, its owner frame is disabled, or it has a Button-class control; it is a notification (reported with owner, ownerEnabled, styles, rect and child controls; never answered) only when all of that was measured; unread evidence fails closed. Template placeholder captions are flagged, never presented as the window's words. 0.9.5 (adversary pass 43): the window's WORDS count — a save/recovery/import kind in its text blocks whatever the evidence, two or more button-like captions in any control class block, and measured notification evidence overrides a licence-type title alone; 0.9.7: swx_dismiss_blocking_dialogs uses the same title-and-words classifier before it closes anything; 0.9.8, from a live measurement: an owner frame read disabled for an instant (SOLIDWORKS busy) is re-read before a notice is called a modal. No MCP server looks at a dialog at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 50 | Readiness gating — attached is not ready (no document command reaches a SOLIDWORKS that has not finished starting) | ✗ | ✓ 0.9.3, from a crash MEASURED 2026-10-01: swx_new_document 8 s after COM attach, swx_open at 9 s and swx_close_all_safely at 12 s crashed SOLIDWORKS while its 3DEXPERIENCE add-in was still initialising (performance log: LOAD_ADDIN still running, SWEXH/UNHANDLED, the 3DEXPERIENCE marker only after the document commands, SWERR_REPORT); a control launch with no document commands crashed nothing. Now a READY stage follows attached, decided by two independent signals — COM StartupProcessCompleted and the performance log's 3DEXPERIENCE marker after the last LOAD_ADDIN — with an honest grace and timeout that never promote to ready; every verb that reaches SOLIDWORKS refuses host_app_starting with retryAfterSeconds until then — 0.9.5: gated by default with a pinned 16-verb exemption list, the performance log bound to this session's process creation time (an earlier session's log is never "complete"), COM alone never enough on a machine that writes markers, an on-demand add-in told from a start by quiet + which add-in, the grace unlocking reads only, and the window-message quit rungs ungated under userAuthorized; LIVE 2026-10-01 a document verb was refused during startup. 0.9.6: every gated reply carries the readiness its gate evaluated, the log is read from its per-start header, and the on-demand rule keys on the platform DLL SWK3DCompassAddin.dll; 0.9.7 (LIVE-PROVEN 0.9.6): no marker history — a disabled platform add-in never locks the bridge out, and a log still being written holds even a machine's first start; 0.9.11, from a live lock-out: UNLOAD_ADDIN is never read as a load, a session older than ten minutes with COM's start complete is never held by a log rule unless startup lines are still changing, and the ready latch survives a bridge restart; a sweep during which SOLIDWORKS dies says host_app_gone with the log's crash markers. The rescue held under the crash (26,129 bytes verified). No MCP server distinguishes attached from ready at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 49 | The user's rescued work survives the bridge's own updates — and ab's (recovery never lives in a directory anything else owns) | ✗ | **✓ 0.9.1: the data root is %LOCALAPPDATA%\adom-solidworks-bridge\, a directory only this bridge writes to** — moved out of Adom Bridge\ altogether after adversary pass 39 found 0.9.0's Adom Bridge\solidworks-data sitting inside the directory ab's installer and uninstaller own, whose fate on an ab uninstall or reinstall is documented nowhere; both earlier locations are migrated oldest first, every copy recorded by (root, path, size, mtime, sha256) so a legacy file that changes after its copy is copied again BESIDE it and reported changedSinceCopy, never settled by name — and since 0.9.2 a small file whose size and mtime match is hashed too, and two versions of the ledger or the ownership registry are MERGED (union, both versions kept beside) rather than one picked; a temp-directory fallback makes every sweep refuse (data_root_is_temp), and an unwritable recovery folder is refused once before the first save (recovery_dir_unwritable). 0.9.0, from a SEV-1 MEASURED 2026-09-30: bridges-cache\solidworks was found CREATED 2026-09-18 09:42 by ab's auto-install of 0.8.9 — the updater re-extracts the whole directory, and every recovery folder from the day before, the ledger and the ownership registry went with it (test documents only; nothing of Drew's was lost). The data root is now %LOCALAPPDATA%\Adom Bridge\solidworks-data\, a sibling of the install cache; the first start MIGRATES what an older bridge left (copied under a temporary name and renamed into place once verified byte for byte — so a start that dies mid-copy never leaves a truncated rescue under the real name — never over an existing file, originals left in place, each file once, a copy that does not verify removed and retried next start); swx_recover_list still reads the old location and marks each rescue there atRiskFromUpdate, saying whether a verified copy exists — and in the data root calls a file whose copy has not landed notCopiedYet (pointing at its only copy), never "gone"; and a sweep REFUSES (recovery_inside_install_dir, nothing written, nothing closed) if its recovery folder would land under the install directory or the install cache — however the path is spelled (links, .., case). Every rule mutation-verified. No MCP server keeps a recovery folder at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 47 | **Interconnect-aware import: refuses honestly, with the reason and the setting** | ✗ | **✓ MEASURED + shipped 0.8.2** — on SOLIDWORKS Connected 2026 with swMultiCAD_Enable3DInterconnect TRUE there is NO programmatic neutral-file import route at all: LoadFile4 returns nothing (errors=1) both with Nothing and with a real GetImportFileData object, LoadFile2 returns false, OpenDoc6 answers swFileRequiresRepairError (2097152) across four option values and swInvalidFileTypeError (1024) for docType 0. So swx_import makes ONE LoadFile4 attempt (a future edition that accepts it simply works) and then fails with interconnect_blocks_import, naming the exact setting — Tools > Options > System Options > Import > Enable 3D Interconnect — the measurement date, and the fact that **this bridge does not change user settings, not even temporarily**. No MCP server reads that toggle at all: they report a translator failure, which sends the reader hunting a missing translator that is not the problem | ✗ | ✗ | ✗ | ✗ | ✗ |
| 46 | **3D Interconnect is understood, obeyed and reported** (the user's own setting decides how a neutral file comes in; the bridge reads it and never writes it) | ✗ | **✓ LIVE-MEASURED 2026-09-17, routed in 0.8.0** — GetUserPreferenceToggle(691) = TRUE on the install, so a STEP is not translated at all: LoadFile4 executes and returns nothing with errors=1, and SOLIDWORKS instead OPENS the file with OpenDoc6(path, swDocPART, …) as a part holding a LINKED 3D Interconnect feature. swx_import reads the toggle, routes accordingly, and reports interconnect / linked / sourcePath so a caller knows the part is not self-contained. The preference is NEVER written — not even flip-and-restore, because a crash between the halves would leave the user's CAD configured differently than they left it — and dissolve:true is REFUSED until the link-breaking call is measured on this edition. Import-diagnostics auto-run (toggle 291) is also TRUE, so the modal dialog it raises is classified, reported as stoppedByDialog, and never answered. Toggle ids read from the installed SolidWorks.Interop.swconst.dll | ✗ | ✗ | ✗ | ✗ | ✗ |
| 45 | **Closes its own documents without asking — and loses nothing doing it** (preserve-then-close: every open document written to a recovery folder and verified there BEFORE anything closes) | ✗ | **✓ LIVE-PROVEN 2026-09-17 (0.7.7)** — swx_shutdown {reason} / swx_close_all_safely {reason} save every open document into %LOCALAPPDATA%\adom-solidworks-bridge\recovery\<timestamp>\ (0.9.0: Adom Bridge\solidworks-data\…, inside the directory ab's installer owns; before that …\bridges-cache\solidworks\recovery\…, inside ab's install cache, which an update empties: row 49), verify it, close parents before children, then quit; no write opt-in, no per-document confirmation (Drew, 2026-09-11: "I despise every time you ask for help closing"). The authorization is to CLOSE, not to lose anything, so the consent question is replaced by checkable rules: the sweep REFUSES TO START when the recovery volume cannot hold the session it is about to write (insufficient_headroom with free/needed/shortfall, nothing written, nothing closed), re-checked before every save, with headroomBytesBefore and estimatedWriteBytes always reported — because a recovery file can be the RIGHT document CUT SHORT and no check on the file can tell (the marker is at offset 4, so every prefix carries it); the recovery file is verified STRUCTURALLY — it must be a recognised SOLIDWORKS container AND at least as big as the smallest real document of its KIND (part 24 KB, assembly 80 KB, drawing 256 KB — one floor for all three would have to be the lowest of them, letting an assembly stop at a third of its size), with the KIND carried from the COM read to the verdict and NEVER re-derived from the recovery file's name, because that name is chosen from the kind and so cannot check it; an unreadable document type falls back to the document's OWN PATH and then its title (evidence about the document, not names this sweep chose) and only then to UNKNOWN, which takes a neutral .sldrecover name and the strictest floor — and if SOLIDWORKS refuses to write that name the file is re-saved as .SLDPRT with the fallback RECORDED and the unknown-kind verification unchanged; swx_recover_list re-runs the verdict on every file it lists and reports verified with the reason — a file the sweep refused is listed (never deleted: those bytes are the only ones there are) but never called a rescue, never offered as openable, and its entry says the document was left OPEN — and gives every genuine rescue its own howToOpen, because SOLIDWORKS will not open a .sldrecover file until it is renamed, published as recoverySignatureOk + recoveryBytes, and it fails CLOSED (exists() passes a zero-byte file and any byte floor passes a truncated one; both are what a full disk leaves). The container marker was MEASURED on 166 real documents from three hardware repositories, because the signature every reference names for a SOLIDWORKS document (OLE compound file) appears in NONE of them — verifying that, as pass 23 specified, would have refused to close every document on a modern install; FIRST AUTONOMOUS CLOSE, live 2026-09-17: swx_close_all_safely {userAuthorized, batch:1} on a bridge-launched session took 4 documents (3 same-titled pathless import temps + a throwaway part) to recovery\20260917-150646\ under unique names (25,834 / 26,031 / 25,773 / 26,047 bytes, recoverySignatureOk:true, namingFallback:null), closed each BY PATH, count 4 → 0, done:true, stoppedBy:null, headroom 1.59 TB — nobody was asked to close anything. A document that could not be written is left OPEN and named in remaining; the user's saved-then-edited file is copied to recovery under a new name and their original is asserted byte-for-byte unchanged; SaveAs3 uses swSaveAsOptions_Silent ALONE so the document RE-POINTS at the recovery file and the close key is read from the document after the save; a dialog stops the sweep and is never answered, with the census taken before EVERY save and EVERY close (a save can raise a prompt of its own, which a per-batch census could not see until the closes had happened); and an UNREADABLE window census is its own outcome — saves proceed, nothing closes, stoppedBy:"dialogCensusUnknown". Ordering is proven from a journal, not from the end state. Every rule is mutation-verified (disable it and exactly one test fails). **Ownership measured live 2026-09-30, both halves**: a pathless Part2 preserved (25,959 bytes, verified, listed from the manifest) and Drew's saved R_0603_1608Metric_1.step-1.sldprt closed with its original untouched (same 32,311 bytes, same mtime). Since 0.9.0 such a document is RECORDED as closedInPlace with its original's size and mtime, and swx_recover_list says "closed at its own path, untouched" — or that it has changed since, or is gone — by measuring the file, not by assuming it 0.9.12, from a live 34-document crate session: an assembly session closes completely — everything preserved first, assemblies (active first) before parts, held components deferred and counted closed when they go out with their parent | ✗ | ✗ | ✗ | ✗ | ✗ |
(51 numbered rows; rows 29–31 are the N/A block that accounts for most of the Fusion verb-count gap. Rows 36–42 added 2026-09-08 from the crate build and the launch-resilience rounds; rows 43–45 from the import-leak, quit and safe-close work, and 46–49 from the live runs of 2026-09-17 and 2026-09-30 — the bar is "significantly more powerful than the MCP servers", so every robustness capability gets a row with its evidence level, not a slogan.)
Per-competitor notes
SolidPilot — eyfel/mcp-server-solidworks · AGPL-3.0 + paid commercial · 265★ · C# + Python
The one to take seriously. Four-layer architecture: an AI planner emits a CAD-neutral Feature Graph
IR, a deterministic Python compiler lowers it to ordered tool calls, and a single C# .NET 4.8
execution layer on one STA thread is the only code that touches COM. ~46 tools, 13 MCP resources.
Its README makes verifiable-shaped claims — production parts round-tripped analyze_model → IR →
rebuild_from_ir → compare_parts to a verified match on exact topology and mass properties, nine
real manufacturing drawings reconstructed to ≤0.02% weight match. Deeper than us on modeling,
assemblies, sheet metal and drawings. Has no BOM (on the roadmap), no configurations, no custom
properties, no preferences, no screenshots, no macros (deliberately — the compiler replaces scripting),
no write gate, and no ecosystem beyond Claude Desktop. Its ensure_ready claims to launch SOLIDWORKS
via COM, which is plausible on a classic desktop install and would fail exactly as ours does on
Connected/Makers. Evidence: README only. Not installed, not run.
vespo92/SolidworksMCP-TS — MIT · 222★ · TypeScript + winax
Second-most-starred and the most candid: labelled "Alpha / Experimental", with the README stating
that "most tools have not been validated against a live SolidWorks instance" and that no real
integration tests exist. Its own coverage table grades Modeling "Partially tested" and Drawing, Export,
Analysis and Macro all "Untested". Broad tool surface on paper (modeling, sketch, drawing, export,
analysis with check_interference and get_mass_properties, VBA generation, macro recording); no
assemblies, no BOM. Last pushed 2026-05. Useful as a naming/API reference, not as evidence that
anything works.
andrewbartels1/SolidworksMCP-python — MIT · 67★ · Python
122 tools per today's README (the figure was 109 earlier — it is moving; pushed 2026-09-02), across
modeling, sketching, drawing, analysis, export, automation, templates and macros. Self-described
"hobby/research product" and "under active construction", and it ships an explicit mock warning:
"Mock adapter output is simulated and should not be treated as engineering truth." Runs in mock mode
unless started with --real, and --real requires SOLIDWORKS to already be open — the same
attach-only constraint we have, arrived at without comment. Explicitly does not do checkpoint-level
interference validation. Highest tool count in the field, lowest evidence-per-tool.
Adam-Schildkraut/solidworks-mcp — MIT · 1★ · TypeScript · last push 2025-08
Small but oddly complementary: it is the only project with PDM tools (configure, check-in,
check-out, workflow, folder structure), the only one with SQL-driven design tables for
configurations, and it leans hardest on VBA — macro record/stop/export/execute plus a claimed 100+
VBA generation templates covering part features, assembly mates and interference, drawing views and
tables, custom properties and batch/PDM operations. No validation statement of any kind, one star,
and its README's support links point at a different org (vinnieespo/solidworks-mcp-server), so treat
it as derived work of uncertain provenance. The template library is the interesting artefact here,
not the server.
alisamsam/Solidworks-MCP — MIT (verified) · 108★ · Python · 22 tools
Task brief listed its licence as unknown; the GitHub API confirms MIT, 108★, last pushed 2026-03.
Deliberately minimal and honest about it: connect to a running instance, part/assembly documents,
six sketch primitives, extrude/cut/fillet/chamfer, list features, set units — and execute_python,
which makes it the only project besides ours to offer a scripting escape hatch into a live SOLIDWORKS
session. It has no export tools at all, no drawings, no assembly mates, no BOM, no properties. It
is a clean starter kit, not a competitor for real work.
Licensing
This is the section with a decision in it.
SolidPilot (eyfel/mcp-server-solidworks) — AGPL-3.0, dual-licensed commercially. Verified from the repository's own licence metadata, not a badge. AGPL-3.0 is the strongest common copyleft: it extends GPL's obligations to network use, so anything we distribute that links or incorporates AGPL code must itself be released under AGPL, source included — and under the network clause, even offering it as a hosted service to users triggers the same obligation. For a bridge that ships inside Adom Bridge to customers, that is not a licence we can absorb. The author offers a paid commercial licence as the escape hatch. Conclusion: read it, learn from its architecture — the Feature Graph IR and the single-STA-thread C# COM boundary are both good ideas — and copy neither its code nor its files. Any IR-shaped work of ours must be independently written. If we ever want its code proper, that is a procurement conversation, not an engineering one.
vespo92/SolidworksMCP-TS — MIT. Verified. Permissive; we could vendor or adapt code with attribution. Given the project's own "most tools not validated" disclaimer there is little worth vendoring, but its tool naming is a fair reference.
andrewbartels1/SolidworksMCP-python — MIT. Verified. Permissive. Same caveat: mock-simulated output by default, so its value is as a map of the COM surface rather than as working code.
Adam-Schildkraut/solidworks-mcp — MIT. Verified. Permissive, and the VBA template library is the
one asset in the whole survey that MIT actually makes attractive to us — if the macros route
(RunMacro2) proves out, 100+ MIT-licensed VBA templates are a legitimate head start. Provenance is
murky enough that we should check the templates' own headers before reusing them.
alisamsam/Solidworks-MCP — MIT. Verified (previously unknown to us).
swx — MIT (bridge.json, LICENSE). We are on the permissive side of the field with everyone
except SolidPilot. Exactly one copyleft player; everything else MIT.
Additional items we can pull off
Capabilities nobody in this field has, which swx could add at low cost, roughly in order of value-per-effort:
- Drawing-sheet outputs — PDF + BOM tables from a
.slddrw. Our DXF/DWG/PDF exports are already built and refused for a part, which is the expected behaviour; the drawing is their real story and it is untested. SolidPilot builds drawings but does not ship a BOM; Schildkraut inserts BOM tables but has no evidence. A live-proven drawing → PDF-with-BOM path would be unique in this field. - Sanctioned launch via the 3DEXPERIENCE chain (
CATSTART.exe→SWXDesktopLauncher, found 2026-09-03). Closes our loudest documented "cannot", and no competitor has solved launch on a Connected edition — bartels and alisamsam simply require the app to be open already. - A macros bridge (
RunMacro2for.swp, then VSTA / C# add-ins). Buys back most of the in-process-scripting gap and would let us reuse an MIT template corpus. Caveat to settle first: the Makers edition restricts third-party add-ins but does run macros — which is precisely why macros, not add-ins, are the first move. - Configurations as a first-class surface. We are already configuration-aware in BOM and properties; enumerating, activating and diffing configurations is a small step, and Fusion has no equivalent concept at all. Design tables (Schildkraut's SQL trick) are the stretch goal.
- Pack and Go, proven live. Built and gated already; it needs an assembly with references to exercise. Nobody else has it.
- The action ledger and measured verb timings as a product feature, not plumbing. We have p90s from
real hardware (
run_script10.2s,new_document9.2s,import7.8s,save_as2.7s, all far inside budget). No competitor can tell a user what an operation will cost. - Wiki / molecule integration. Native GLB export already works live; the pipeline from a SOLIDWORKS part to a published molecule is ours to connect and is not even conceivable for a bare MCP server.
- Ship the deny-by-default posture as the marketed differentiator. It is the single strongest claim we have and it is evidenced: eight adversarial rounds, two independently-enforcing layers, and three live runs in which the bridge refused to touch the user's own open document — including one abort where it removed every file it had written. Every competitor in this survey will, on request, write to a path the user owns with no confirmation and no record.
- Per-component mass properties — small, and blocked only on being able to populate an assembly.
What is still unproven, and where
Row 44 is no longer unproven: the quit ladder's rung (a) has quit a real SOLIDWORKS twice, and on
2026-09-30 tools/quit-gate.py ran its full cycle — quit, measure, relaunch — through the bridge ab
hosts. Rungs (b)–(f) have still never run live, and nothing has needed them: the ladder ships pinned
at rung (a), because being wrong on a later rung would cost the user a 1-3 minute relaunch that can
fail. Five of the six MCP servers surveyed never attempt a quit at all, and the sixth reaches for a
kill.
The newest open question is about testing rather than capability: adom-bridge 2.1.163 terminates a
second swx-bridge.exe within 30 s, so the side-loaded dev copy the gates used is gone, and which
dev route ab tolerates (a prerelease install, or a renamed exe reached with SWX_BRIDGE_URL) has not
been measured. Until it is, remember that ab hosts whatever the published manifest names — a
release IS a deploy to every machine.
Nothing above changes the standing recommendation: run tools/live-smoke.py once SOLIDWORKS is
back up, started from the 3DEXPERIENCE Platform. It is what converts the ⚠ mock cells in column B into
✓ live — or finds the next bug, which is what happened all three previous times. The assembly verbs
(swx_bom, swx_interference, per-component mass properties) need a real multi-component assembly or a
classic desktop install; the 2D exports need a real .slddrw. And no competitor cell in this table is
better than read-from-README, because none of them was installed or run.
# Where swx stands in the ecosystem
**swx v0.3.0** measured against the Adom **Fusion 360 bridge v1.9.341** (the gold standard we mirror)
and against every public SOLIDWORKS MCP server we could find · written 2026-09-03
## Executive summary
- **swx is the only SOLIDWORKS implementation here with a published live-run record.** Three runs
against a real *SOLIDWORKS Design Professional for Makers 2026* install (22-aborted, 120/9, then
**125 passed / 5 failed**), 19 verbs proven end to end, with measured p90 timings. One competitor
(SolidPilot) also claims live validation and is credible about it; the other three are explicit that
most or all of their tools are unvalidated, mock, or hobby-grade.
- **On raw modeling breadth we are behind SolidPilot** — its sketch/feature/assembly/drawing surface is
deeper than ours and it is the most mature project in this space by a wide margin.
- **On safety we are ahead of all five, and alone.** No other project has a write gate. swx writes are
deny-by-default at a single choke point, enforced *independently* at two layers, hardened over eight
adversarial review rounds, and the posture held through every live run — three times the bridge failed
CLOSED rather than touch the wrong document.
- **Our other unique strengths:** BOM-first and configuration-aware design (BOM aggregates per
*(file, configuration)* pair — nobody else models this); native GLB with no optimisation service;
an action ledger plus measured per-verb timings; census-not-dismiss dialog etiquette with
`neverAutoAnswer` classes; and real host-ecosystem integration (Adom Bridge verbs, the user's
Activity Log, a shipped skill) where every competitor is a bare MCP server for Claude Desktop.
- **Our real gaps, stated plainly:** no cloud/3DEXPERIENCE document access (21 Fusion verbs; a separate
OAuth project of roughly the size of the Fusion bridge's APS work); assemblies-with-components,
drawings and 2D exports are mock-only because the Makers edition would not let an assembly be
populated; and there is no in-process scripting host — a typed JSON DSL stands in.
- **Launch was our headline "cannot", and that changed today.** `CoCreateInstance` returns
`CO_E_SERVER_EXEC_FAILURE` on the Connected editions, but a sanctioned launch path via the
3DEXPERIENCE shortcut chain (`CATSTART.exe` → `SWXDesktopLauncher`) was discovered 2026-09-03.
Implementation is in progress and **not yet live-proven**.
- **Scripting has a second route now too:** SOLIDWORKS `RunMacro2` for `.swp` VBA macros, VSTA, and C#
add-ins are **under investigation** — with the caveat that the Makers edition restricts third-party
add-ins while still running macros. Four of the five competitors already lean on VBA; we do not yet.
- **Licensing is simple and decision-relevant:** exactly **one** copyleft player — SolidPilot is
**AGPL-3.0** with a paid commercial option — and everything else, ours included, is **MIT**. We can
read and learn from SolidPilot; we must not vendor its code.
- **Electronics is not a gap.** 51 of the Fusion bridge's 132 verbs are Fusion Electronics, EAGLE
libraries, or Autodesk-specific plumbing. SOLIDWORKS has no concept to bridge to, and no competitor
attempts it either.
## How to read the cells
| Mark | Means |
|---|---|
| **✓ live** | Executed against a real, licensed CAD install and observed to do what it claims. |
| **✓** | Built and shipped, or claimed by the project's own README. Evidence level is stated per row. |
| **⚠ mock** | Built and mock-tested only; never executed live in any form. |
| **partial** | Some of the capability, materially incomplete. |
| **✗** | Absent. |
| **n/a** | No concept exists to bridge to in that product. |
| **WIP** | Route identified, implementation in progress, not yet proven. |
| **?** | Could not be determined from the repository. |
Evidence discipline: for **Fusion bridge** and **swx**, cells come from source we hold — the Fusion
bridge's own `describe.py` catalog (133 entries, 132 real verbs) and `docs/FUSION-PARITY-REPORT.md`.
For every competitor column, cells are **read-from-README** unless the row note says otherwise. Nobody
in the competitor set was installed or run. Licences and star counts were verified against the GitHub
API on 2026-09-03, not read off a badge.
## The master table
35 capability rows × 7 implementations. Verb counts: Fusion bridge **132**, swx **60**,
SolidPilot ~**46 tools**, vespo92 ~**30+**, bartels **122**, Schildkraut **~16 tools + 100+ VBA
templates**, alisamsam **22**.
| # | Capability | Fusion bridge | **swx v0.3** | SolidPilot **(AGPL-3.0!)** | vespo92 (MIT) | bartels (MIT) | Schildkraut (MIT) | alisamsam (MIT) |
|---:|---|---|---|---|---|---|---|---|
| 1 | Session lifecycle — attach, stop, kill | ✓ | **✓ live** attach · stop: **unproven** — the one observed `ExitApp` "decline" had a dirty Part1 open (save-prompt stall, not a decline); no stop event at 0 docs is in the ledger. v1 also holds a COM ref while checking and gates on unsaved-count not open-count (docs/QUIT-INVESTIGATION.md); graceful-quit ladder = 0.5.0 work · kill: never (policy) | ✓ attach | ? | ✓ attach | ? | ✓ attach |
| 2 | Launch the CAD application (and install it) | ✓ launch + silent install | **✓ LIVE-PROVEN 2026-09-11 — attributable.** `shellExecute` (ShellExecuteExW + SEE_MASK_NOCLOSEPROCESS) handed back a real handle for the Platform .lnk (CATSTART pid 131272) and that chain reached `Run Begin`; the old cmd-route stall is gone. Same run found the bridge killing its OWN chain while the user was at the 3DEXPERIENCE ID sign-in — a native WebView2 window with no UIA controls — because the sldworks deadline fired on a wait that was not a stall. **Fixed 0.6.0**: the sign-in window is recognised by class and owner pid, every deadline PAUSES while it is up, nothing is killed or escalated, the user is toasted, and a session that attaches after the sign-in is re-attributed (`attachedAfterSignIn`) instead of being recorded as somebody else's. **LIVE AGAIN 2026-09-30, through the bridge ab hosts** (adom-bridge 2.1.163 auto-installed the released 0.8.9): `tools/launch-gate.py` passed every launch claim — `shellExecute`, attributed, `Run Begin` 28.8 s, the helper sign-in step passed without a sign-in, COM attached 139.8 s | ✓ claims COM launch (refused on Connected) | ✗ | ✗ needs SW already open | ? | ✗ needs running instance |
| 3 | Requires an in-app add-in | yes (3 verbs to manage it) | **no — out-of-process COM** | no (C# COM server) | no | no | no | no |
| 4 | Open a local file · disk discovery | ✓ open · ✗ discovery (cloud-native) | **✓ live** open · **✓** `find_files` | ✓ open · ✗ | ✓ (untested) | ✓ | ✓ | ✓ open · ✗ |
| 5 | Create a new document | ✗ (docs arrive from cloud/import) | **✓ live** | ✓ part + assembly | ✓ (untested) | ✓ | ✓ | ✓ part + assembly |
| 6 | Save / Save As **with overwrite protection** | ✓ cloud save · ✗ overwrite guard | **✓ live** save_as · **✓ overwrite guard (unique)** | ✓ save · ✗ guard | ✓ (untested) · ✗ guard | ✓ · ✗ guard | ✓ · ✗ guard | ✓ · ✗ guard |
| 7 | Cloud document store — search, list, open, up/download | ✓ 21 verbs (APS Data Management) | **✗ lacking** — `swx_cloud_status` returns the honest probe | ✗ | ✗ | ✗ | ✗ | ✗ |
| 8 | Cloud / vendor sign-in + OAuth | ✓ 9 verbs (incl. 2FA, web sign-in) | ✗ lacking | ✗ | ✗ | ✗ | ✗ | ✗ |
| 9 | Parametric modeling — sketch → feature | ✓ (Python script in-process) | **✓ live** typed DSL (50×30×20 solid, p90 10.2s) | **✓ live** — deepest surface here | partial (basic ops only) | ✓ claimed | ✓ via VBA templates | ✓ basic |
| 10 | In-process scripting host (arbitrary code) | ✓ Python `eval` inside Fusion | **adapted** — typed JSON DSL, validated pre-COM; `swx_com_eval` escape hatch | ✗ by design (deterministic compiler) | ✗ | ✗ | ✗ | ✓ `execute_python` in SW context |
| 11 | Macros / VBA — generate, record, execute | n/a (Fusion has no VBA) | **WIP** — `RunMacro2` / VSTA / C# add-in under investigation | ✗ explicitly unsupported | partial (gen works, exec untested) | ✓ | **✓ strongest** (record/export/execute + 100+ templates) | ✗ |
| 12 | Assemblies — insert components, mates | ✓ via script | ⚠ mock — `AddComponent5` returned Nothing on this edition | **✓ live** insert + mate + diff | ✗ | ✓ claimed | ✓ via VBA | partial (create doc only) |
| 13 | Drawings — create, views, dimensions | ✗ no drawing verbs | partial — creation **✓ live**, views/dims not built | **✓ live** 9 tools; 9 real drawings reconstructed | ✓ (untested) | ✓ claimed | ✓ via VBA | ✗ |
| 14 | Import neutral CAD (STEP etc.) | ✓ | **✓ live** (p90 7.8s) | ✓ via 3D Interconnect | ? | ? | ? | ✗ |
| 15 | Export 3D — STEP/IGES/STL/3MF/SAT/Parasolid | ✓ 8 formats | **✓ live** 6 proven; 17 formats in table; OBJ refused by SOLIDWORKS | ✓ STEP/IGES/STL | ✓ (untested) | ✓ | ✓ | ✗ none |
| 16 | Export **native GLB** (web 3D) | ✓ but needs an optimisation service | **✓ live, direct — unique** | ✗ | ✗ | ✗ | ✗ | ✗ |
| 17 | Export 2D / document — PDF, DXF, DWG | ✓ DXF/DWG · ✗ PDF | ⚠ mock all three (refused for a part; untested from a drawing) | ✓ PDF/DWG/DXF | ✓ (untested) | ✓ | ✓ PDF | ✗ |
| 18 | BOM | ✓ assembly + electronics BOM | ⚠ mock — **but per *(file, configuration)*, the richest design here** | ✗ on the roadmap | ✗ | ✗ | ✓ table insertion | ✗ |
| 19 | Mass / physical properties | ✓ | **✓ live** (aluminium, 81 g agreeing) | **✓ live** (verified ≤1%) | ✓ (untested) | ✓ claimed | ✓ claimed | ✗ |
| 20 | Design-health — interference detection, rebuild census | ✗ neither | partial — interference ⚠ mock (object confirmed live), `rebuild_check` built | partial (`analyze_model`/`verify_state`; no interference) | ✓ (untested) | ✗ explicitly not yet | ✓ via VBA | ✗ |
| 21 | Parameters / dimensions — read **and drive** | ✓ read | **✓ live** — drove a dimension to 25 mm, model moved | ✓ `modify_dimension` | ✓ (untested) | ✓ claimed | ✓ equations | ✗ |
| 22 | Custom properties (file and per-configuration) | partial (buried in the attribute model) | **✓** `props_get`/`props_set` | ✗ | ✗ | ? | ✓ | ✗ |
| 23 | Configurations / design tables | ✗ no equivalent concept | ✓ configuration-aware (BOM, properties) · ✗ design tables | ✗ | partial (`vba_configurations`, untested) | partial | **✓ strongest** (design tables + SQL) | ✗ |
| 24 | Pack and Go — collect a design + all references | ✗ | ✓ built (gated), ⚠ mock | ✗ | ✗ | ✗ | partial (batch ops) | ✗ |
| 25 | PDM / vault integration | n/a | ✗ not built | ✗ | ✗ | ✗ | **✓ only one** (5 tools) | ✗ |
| 26 | Application preferences — read and write | ✓ incl. driving the settings modal | **✓ live** (written, then read back) · modal driving declined by design | ✗ | ✗ | ✗ | ✗ | partial (`set_units`) |
| 27 | Screenshots + window management | ✓ | ⚠ mock (delegated to ab; SKIPPED in live runs) | ✗ | ✗ | ✗ | ✗ | ✗ |
| 28 | Blocking-dialog handling | ✓ dismisses them | **adapted — censuses by default**; `neverAutoAnswer` classes never closed | ✗ | ✗ | ✗ | ✗ | ✗ |
| 29 | Electronics — schematic, PCB, Gerbers, CPL, design rules | ✓ 15 verbs | n/a | n/a | n/a | n/a | n/a | n/a |
| 30 | Component libraries / 3D packages (EAGLE `.lbr`) | ✓ 23 verbs | n/a | ✗ | ✗ | ✗ | ✗ | ✗ |
| 31 | Vendor MCP-server proxy | ✓ 6 verbs (Autodesk ships one) | n/a — Dassault ships none | n/a (is itself an MCP server) | n/a | n/a | n/a | n/a |
| 32 | Bridge infrastructure — self-describe, shipped docs, guided demo, uninstall | ✓ all four | ✓ describe/docs/uninstall · ✗ demo (deferred v0.4) | partial (13 MCP resources) | ✗ | partial (docs audit) | partial (resource registry) | ✗ |
| 33 | **Action ledger + measured per-verb timings** | ✓ ledger, verb times, live feed, alerts | **✓ ledger + timings recorded live** | ✗ (dev log only) | ✗ | ✗ logging only | partial ("enhanced logging") | ✗ |
| 34 | **Deny-by-default write gate** | ✗ no gate, no confirm/reason in its catalog | **✓ live — unique. Two independent layers, 12 adversarial rounds, held in all 3 live runs.** HONESTY NOTE: pass 12 (2026-09-09) found that an un-stat-able destination read as FREE — `Path::exists()` is false both for "nothing is there" and for "could not look" (a parent it cannot traverse, a UNC share it has no token for, a device not ready, an over-length path), and the com host does not share a filesystem view with SOLIDWORKS. Fixed in **0.5.9**: `symlink_metadata` gives three answers and an unreadable one REFUSES (`destination_unverifiable`) in BOTH layers, tested in both | ✗ | ✗ | partial ("adapter safety wrappers") | partial (macro exec needs permission) | ✗ |
| 35 | Host-ecosystem integration (Adom Bridge, Activity Log, skill) | ✓ native | **✓ native** | ✗ MCP clients only | ✗ | ✗ | ✗ | ✗ |
| 36 | **Ownership persists across bridge/host restarts** (bridge-created docs stay closable without opt-in) | ✗ (no ownership model) | **✓ live 2026-09-08** — `owned-docs.json` keyed to the SOLIDWORKS process; proven create → host kill → close in default posture. **And across UPDATES since 0.9.0**: the registry lived in ab's install cache until then, so the 0.8.9 auto-install wiped it (row 49); it now lives in the data root, and the first start after the move restores what an older bridge recorded (pinned: the migration runs before the registry is read) | ✗ | ✗ | ✗ | ✗ | ✗ |
| 37 | **Honest UNKNOWN instead of a fabricated empty/zero** (doc list, counts, dialogs, interference) | **✓ LIVE 2026-09-09** — on a real 2144-document session `swx_docs` answers in 3.4 s with `count:2144, truncated:true`, a 10-doc sample (8 import temps) — after 0.5.4 wedged 30 s on the same session (fixed 0.5.5: bounded GetFirstDocument/GetNext walk, never GetDocuments above the cap; simulator now charges per-doc latency) | **⚠ 0.4.x-0.5.5, mock-proven; the ENUMERATION half FAILED LIVE** — `docs_enumeration_failed`, `Option` counts, `unsaved_unknown`, `count:null` semantics in hints; 29 adversary tests. **Live 2026-09-09: `swx_docs` still timed out at 30s and the com host was killed on a 2144-document session** — the degrade path called `GetDocuments` (one call, every handle) and then `GetPathName` on all 2144. `GetDocumentCount` answered in 0.7s. The mock's enumeration was instant, so this row was mock-proven and false live. **Fixed in 0.5.5** (walk `GetFirstDocument`/`GetNext` for the sample only, time-boxed; the drain walks a bounded window too) with the live session held in the suite via a per-document latency model — **re-proof on the live 2144-doc session pending** | ✗ | ✗ | ✗ | ✗ | ✗ |
| 38 | **Hung / exhausted host detection, and BUSY vs DEAD** (Not Responding + real COM timeout; NewDocument-returns-nothing; CPU/memory delta over a sample) | ✗ | **✓ 0.5.1** evidence-based `host_app_hung` / `host_app_exhausted` + `verdict:"busy"\|"dead"\|"unknown"` from `cpuActiveSeconds`/`memoryDeltaMB` — measured live: 17.9 GB not-responding for ~5 min at ~70% of a core and it RECOVERED, so "not responding" now advises WAIT, not "end the task". One reading never says dead | ✗ | ✗ | ✗ | ✗ | ✗ |
| 39 | **Stalled-launcher recovery with attribution law** (kill only a chain proven ours by handle; never daemons, never sldworks) | ✗ | **✓ shipped 0.4.4**, 4 adversary rounds, **live-proven 2026-09-11** — the handle world is confirmed on this machine, and the one live defect was the opposite of an over-eager kill law: it killed a chain that was correctly WAITING (sign-in), fixed in 0.6.0. No daemon and no sldworks.exe has ever been touched | ✗ | ✗ | ✗ | ✗ | ✗ |
| 40 | **Crash-reporter recovery** (click "Restart SOLIDWORKS Design" once, structured match, ledgered) | ✗ | **shipped, DISABLED by default** until the real control-tree reply is captured | ✗ | ✗ | ✗ | ✗ | ✗ |
| 41 | **COM retry-on-reject** (busy host: RPC_E_CALL_REJECTED / RETRYLATER backoff on every call) | ? | **✓ live 0.3.3** — 50-read smoke gate, 0 under-reporting, 11 rejects absorbed | ✗ | ✗ | ✗ | ✗ | ✗ |
| 42 | **Real-work proof** (multi-assembly build + BOM exported from the assembly, verified against a packet) | ✓ (electronics) | **✓ live** — NSF crate: 5 assemblies, 383 placements, 32-row BOM, 28/28 part numbers match | ✗ | ✗ | ✗ | ✗ | ✗ |
| 43 | **Import / resource lifecycle — no leaked temps, drainable, enumeration never wedges** | ✗ | **✓ 0.5.0** — enumeration degrades above a cap (`{count,truncated,sample}`, never a 30s timeout+kill); `swx_close_import_temps` drains STEP/IGES `…\Temp\swx<pid>\IC~~\…` temps in the DEFAULT posture (path is the ownership proof, survives a pid change); import asserts a net +1. Root-caused a live 1342-doc / 8 GB leak. **0.5.3**: the resolved `%TEMP%` is the WHOLE location proof (8.3-aware, no shape-test fallback), and with no resolved root the drain refuses (`temp_root_unknown`) instead of closing nothing quietly. **0.5.4**: the report says which root it compared against (`tempRoot`) and counts documents that carry the launcher's tail but sit elsewhere (`importTempsElsewhere` + a sample), so a drain that matched nothing can no longer claim it drained everything. **0.5.6**: the victim is CLOSED by the path it was chosen by (it was closed by TITLE, which `CloseDoc` resolves by name without prompting — a live session held temps sharing a saved file's title), a shared title is refused and reported, and every close is verified by path — the mismatch case is real, because ab's `%TEMP%` need not be the one SOLIDWORKS used | ✗ | ✗ | ✗ | ✗ | ✗ |
| 44 | **Graceful QUIT that is measured, not assumed** (never a kill, never answers a dialog, proves the exit from the process census) | ✗ | **✓ LIVE-PROVEN 2026-09-17 (rung a)** — `swx_stop {userAuthorized, maxRung:"a"}` quit a bridge-launched session on the FIRST rung (UserControl=false; ExitApp; every COM reference released), verified absent from the process census; `swx_shutdown` then removed a stray empty instance (pid 145188) and `tasklist` showed no `sldworks.exe` at all. **`ExitApp` is NOT declined at zero documents on this edition** — the long-held `host_app_stop_declined` belief was a SAVE-PROMPT STALL misread as a refusal, which is why the ladder was built pinned at rung (a) and why the preserve-then-close sweep is what actually unblocked it. A rung ladder (a `ExitApp` → f Restart Manager *without* `RmForceShutdown`), pinned at rung (a); 7 re-measured preconditions where UNKNOWN refuses and `force` waives the UNSAVED question ONLY; every COM reference released before and after each rung, with outstanding refs named in the report; success = *this pid AND this creation time* absent from the census, never `GetActiveObject`; per-session children reaped while the documented platform daemons are left alone; a dialog stops the ladder permanently and is never answered; nothing disowned until the exit is verified. every precondition re-measured before EVERY rung (a mid-ladder refusal is a real outcome), the exit POLLED to the rung's budget rather than sampled once (a real `ExitApp` returns before the process goes), the dialog census covering the `swCefSubProc` web-view children by parentage, the count cross-checked against the enumeration, and the message rungs re-verifying window ownership before they send. `tools/quit-gate.py` proves the session was bridge-launched, and **its FULL CYCLE PASSED LIVE 2026-09-30 through the bridge ab hosts**: rung (a), process gone 29.5 s, per-session servers reaped, nothing on screen, no crash reporter, every rung reported, and SOLIDWORKS relaunched by the bridge 54.7 s later. The gate now reaches the bridge through ab's verb routing (the side-loaded dev copy on 24695 is terminated by ab 2.1.163 within 30 s) and passes `userAuthorized:true` — the standing authorization — rather than the write-gate pair, which the hosted bridge rightly never enables. **MEASURED 2026-10-01: the decline is about session HISTORY** — rung (a) was declined three times on a session that had never held a document and quit in 3.4 s once one had been created and closed; since 0.9.3 the ladder PRIMES such a session (empty, no dialog, user-authorized only) and asks again — **LIVE-PROVEN 2026-10-01 on 0.9.4**: declined at 130 s, primed, quit in 3.4 s (declines measured from 50 s to 8 min old; such sessions quit unprimed at ~25 s), and `swx_status` exposes the session's document history — and the gate's "no longer running" claim — which had passed vacuously after declines — now requires `running:false` and is self-tested | ✗ | ✗ | ✗ | ✗ | ✗ |
| 48 | **A title collision between SAVED documents is impossible here — measured, not assumed** | ✗ | **✓ MEASURED LIVE 2026-09-17** — `tools/drain-gate.py --fixture new` copied a bridge-created document's own file to a second directory under the same basename and called `swx_open` on it. SOLIDWORKS REFUSED: `errors = 65536` (`swFileWithSameTitleAlreadyOpen`). So the drain's title-collision guard — which refuses to close any document whose title another open document shares, and names both paths — can only ever fire for PATHLESS documents, which is exactly the state identity-at-birth removes. The guard stays (a document the bridge did not create can still be pathless, and an older bridge's leftovers are), and the measurement is recorded next to it in `com.rs` so nobody "simplifies" it on the assumption that saved collisions are the common case. No MCP server measures this at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 52 | **Never ends a session the user is working in** (a measured user-presence guard on every quit and sweep) | ✗ | **✓ 0.9.9, from an event MEASURED 2026-10-01**: Drew took over a bridge-launched session — a "leave as found" quit met his File Open dialog, and minutes later the session held his 34-document crate assembly. Every quit, sweep and priming now measures presence (SOLIDWORKS foreground + input under 120 s, documents the bridge did not open, an earlier take-over), refuses `user_is_active` with the evidence, fails closed on an unreadable measurement, and marks the session taken over for good; only the user's explicit override proceeds, and the gates never pass it. 0.9.10: a document is the bridge's only if a bridge verb opened or created it — in a session the user launched, every document is theirs. No MCP server has a presence guard at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 53 | **Signs the user in, unattended, without ever seeing the password** (3DEXPERIENCE ID sign-in from the user's own local vault) | ✗ | **✓ 0.9.13, from Drew's request 2026-10-02**: the login window's accessible inventory is captured every time it appears; `swx_sign_in` recognizes the form from that inventory alone, takes the login from the user's pup vault on their laptop through ab, types it through UI Automation, ticks "Remember me", verifies by the window closing, and scrubs the password from every reply, log and ledger line; it fails closed on a missing login, an unknown form or a second step, and never retries a rejected password. No MCP server signs in at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 54 | **Renders a product shot at any size, and leaves the user's view as it was** (high-resolution image export from the viewport) | ✗ | **✓ 0.9.18, MEASURED LIVE 2026-10-05** (3840×2160 of the 110-document Moveo assembly in 11.6 s, every setting restored; 0.9.19 accounts for every requested setting and adds `zoomFactor`; 0.9.20 reads every set back, so a setting SOLIDWORKS ignores — RealView on an uncertified GPU, measured — is reported `setIgnored` with a note, never "applied"): `swx_render_image` sets view, style, RealView, ambient occlusion, shadows, perspective and a plain background, exports through `IModelDoc2::SaveBMP` at up to 8192 px a side, converts to PNG and reads the size back from the file (`capped:true` when only the window size came out); every changed setting is captured, restored on every path, read back and listed; the swconst ids are read from the installed interop DLL, never guessed; a render that changes the screen respects the user-presence guard. The Fusion bridge has no render verb, and no MCP server renders at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 55 | **Supports the user's OWN SOLIDWORKS release, with an audit and a self-test** (not "whatever version the author has") | ✗ | **✓ 0.10.0, from issue #1/#2 (SOLIDWORKS 2021)**: all 149 COM members the bridge calls were checked against help.solidworks.com (newest: 2017), so `>=2021` is declared as SUPPORTED with 2026 as TESTED (`docs/COMPATIBILITY.md`); `swx_status.solidworks.versionSupport` reads the release at attach; a version-gated call refuses `needs_solidworks_version` by name; `swx_selftest` returns per-verb pass/fail on any install (read-only, or a scratch part it closes) | ✗ | ✗ | ✗ | ✗ | ✗ |
| 51 | **Dialogs judged by MEASURED MODALITY, not by existence** (a notification never blocks; a modal always does) | ✗ | **✓ LIVE-PROVEN 2026-10-01 on 0.9.4** — with the 3DEXPERIENCE "Connected" notice on screen, `swx_stop` quit in 5.1 s and reported it as a notification with its evidence. **0.9.4, from a blocker MEASURED 2026-10-01**: the 3DEXPERIENCE "Connected to …" notice — a title-less `#32770` tool window whose owner frame stayed ENABLED for 95 s, with no Button-class control — blocked every quit, sweep and import for minutes. Now a window blocks when its kind is known-blocking, its owner frame is disabled, or it has a Button-class control; it is a `notification` (reported with owner, ownerEnabled, styles, rect and child controls; never answered) only when all of that was measured; unread evidence fails closed. Template placeholder captions are flagged, never presented as the window's words. **0.9.5 (adversary pass 43): the window's WORDS count — a save/recovery/import kind in its text blocks whatever the evidence, two or more button-like captions in any control class block, and measured notification evidence overrides a licence-type title alone; 0.9.7: swx_dismiss_blocking_dialogs uses the same title-and-words classifier before it closes anything; 0.9.8, from a live measurement: an owner frame read disabled for an instant (SOLIDWORKS busy) is re-read before a notice is called a modal.** No MCP server looks at a dialog at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 50 | **Readiness gating — attached is not ready** (no document command reaches a SOLIDWORKS that has not finished starting) | ✗ | **✓ 0.9.3, from a crash MEASURED 2026-10-01**: `swx_new_document` 8 s after COM attach, `swx_open` at 9 s and `swx_close_all_safely` at 12 s crashed SOLIDWORKS while its 3DEXPERIENCE add-in was still initialising (performance log: LOAD_ADDIN still running, SWEXH/UNHANDLED, the 3DEXPERIENCE marker only after the document commands, SWERR_REPORT); a control launch with no document commands crashed nothing. Now a READY stage follows `attached`, decided by two independent signals — COM `StartupProcessCompleted` and the performance log's 3DEXPERIENCE marker after the last LOAD_ADDIN — with an honest grace and timeout that never promote to ready; every verb that reaches SOLIDWORKS refuses `host_app_starting` with `retryAfterSeconds` until then — **0.9.5: gated by default with a pinned 16-verb exemption list, the performance log bound to this session's process creation time (an earlier session's log is never "complete"), COM alone never enough on a machine that writes markers, an on-demand add-in told from a start by quiet + which add-in, the grace unlocking reads only, and the window-message quit rungs ungated under userAuthorized; LIVE 2026-10-01 a document verb was refused during startup. 0.9.6: every gated reply carries the readiness its gate evaluated, the log is read from its per-start header, and the on-demand rule keys on the platform DLL SWK3DCompassAddin.dll; 0.9.7 (LIVE-PROVEN 0.9.6): no marker history — a disabled platform add-in never locks the bridge out, and a log still being written holds even a machine's first start; 0.9.11, from a live lock-out: `UNLOAD_ADDIN` is never read as a load, a session older than ten minutes with COM's start complete is never held by a log rule unless startup lines are still changing, and the ready latch survives a bridge restart**; a sweep during which SOLIDWORKS dies says `host_app_gone` with the log's crash markers. The rescue held under the crash (26,129 bytes verified). No MCP server distinguishes attached from ready at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 49 | **The user's rescued work survives the bridge's own updates — and ab's** (recovery never lives in a directory anything else owns) | ✗ | **✓ 0.9.1: the data root is `%LOCALAPPDATA%\adom-solidworks-bridge\`, a directory only this bridge writes to** — moved out of `Adom Bridge\` altogether after adversary pass 39 found 0.9.0's `Adom Bridge\solidworks-data` sitting inside the directory ab's installer and uninstaller own, whose fate on an ab uninstall or reinstall is documented nowhere; both earlier locations are migrated oldest first, every copy recorded by (root, path, size, mtime, sha256) so a legacy file that changes after its copy is copied again BESIDE it and reported `changedSinceCopy`, never settled by name — and since 0.9.2 a small file whose size and mtime match is hashed too, and two versions of the ledger or the ownership registry are MERGED (union, both versions kept beside) rather than one picked; a temp-directory fallback makes every sweep refuse (`data_root_is_temp`), and an unwritable recovery folder is refused once before the first save (`recovery_dir_unwritable`). **0.9.0, from a SEV-1 MEASURED 2026-09-30**: `bridges-cache\solidworks` was found CREATED 2026-09-18 09:42 by ab's auto-install of 0.8.9 — the updater re-extracts the whole directory, and every recovery folder from the day before, the ledger and the ownership registry went with it (test documents only; nothing of Drew's was lost). The data root is now `%LOCALAPPDATA%\Adom Bridge\solidworks-data\`, a sibling of the install cache; the first start MIGRATES what an older bridge left (copied under a temporary name and renamed into place once verified byte for byte — so a start that dies mid-copy never leaves a truncated rescue under the real name — never over an existing file, originals left in place, each file once, a copy that does not verify removed and retried next start); `swx_recover_list` still reads the old location and marks each rescue there `atRiskFromUpdate`, saying whether a verified copy exists — and in the data root calls a file whose copy has not landed `notCopiedYet` (pointing at its only copy), never "gone"; and a sweep REFUSES (`recovery_inside_install_dir`, nothing written, nothing closed) if its recovery folder would land under the install directory or the install cache — however the path is spelled (links, `..`, case). Every rule mutation-verified. No MCP server keeps a recovery folder at all | ✗ | ✗ | ✗ | ✗ | ✗ |
| 47 | **Interconnect-aware import: refuses honestly, with the reason and the setting** | ✗ | **✓ MEASURED + shipped 0.8.2** — on SOLIDWORKS Connected 2026 with `swMultiCAD_Enable3DInterconnect` TRUE there is NO programmatic neutral-file import route at all: LoadFile4 returns nothing (`errors=1`) both with `Nothing` and with a real `GetImportFileData` object, LoadFile2 returns false, OpenDoc6 answers `swFileRequiresRepairError` (2097152) across four option values and `swInvalidFileTypeError` (1024) for docType 0. So `swx_import` makes ONE LoadFile4 attempt (a future edition that accepts it simply works) and then fails with `interconnect_blocks_import`, naming the exact setting — Tools > Options > System Options > Import > Enable 3D Interconnect — the measurement date, and the fact that **this bridge does not change user settings, not even temporarily**. No MCP server reads that toggle at all: they report a translator failure, which sends the reader hunting a missing translator that is not the problem | ✗ | ✗ | ✗ | ✗ | ✗ |
| 46 | **3D Interconnect is understood, obeyed and reported** (the user's own setting decides how a neutral file comes in; the bridge reads it and never writes it) | ✗ | **✓ LIVE-MEASURED 2026-09-17, routed in 0.8.0** — `GetUserPreferenceToggle(691)` = TRUE on the install, so a STEP is not translated at all: `LoadFile4` executes and returns nothing with `errors=1`, and SOLIDWORKS instead OPENS the file with `OpenDoc6(path, swDocPART, …)` as a part holding a LINKED 3D Interconnect feature. `swx_import` reads the toggle, routes accordingly, and reports `interconnect` / `linked` / `sourcePath` so a caller knows the part is not self-contained. The preference is NEVER written — not even flip-and-restore, because a crash between the halves would leave the user's CAD configured differently than they left it — and `dissolve:true` is REFUSED until the link-breaking call is measured on this edition. Import-diagnostics auto-run (toggle 291) is also TRUE, so the modal dialog it raises is classified, reported as `stoppedByDialog`, and never answered. Toggle ids read from the installed `SolidWorks.Interop.swconst.dll` | ✗ | ✗ | ✗ | ✗ | ✗ |
| 45 | **Closes its own documents without asking — and loses nothing doing it** (preserve-then-close: every open document written to a recovery folder and verified there BEFORE anything closes) | ✗ | **✓ LIVE-PROVEN 2026-09-17 (0.7.7)** — `swx_shutdown {reason}` / `swx_close_all_safely {reason}` save every open document into `%LOCALAPPDATA%\adom-solidworks-bridge\recovery\<timestamp>\` (0.9.0: `Adom Bridge\solidworks-data\…`, inside the directory ab's installer owns; before that `…\bridges-cache\solidworks\recovery\…`, inside ab's install cache, which an update empties: row 49), verify it, close parents before children, then quit; no write opt-in, no per-document confirmation (Drew, 2026-09-11: *"I despise every time you ask for help closing"*). The authorization is to CLOSE, not to lose anything, so the consent question is replaced by checkable rules: the sweep REFUSES TO START when the recovery volume cannot hold the session it is about to write (`insufficient_headroom` with free/needed/shortfall, nothing written, nothing closed), re-checked before every save, with `headroomBytesBefore` and `estimatedWriteBytes` always reported — because a recovery file can be the RIGHT document CUT SHORT and no check on the file can tell (the marker is at offset 4, so every prefix carries it); the recovery file is verified STRUCTURALLY — it must be a recognised SOLIDWORKS container AND at least as big as the smallest real document of its KIND (part 24 KB, assembly 80 KB, drawing 256 KB — one floor for all three would have to be the lowest of them, letting an assembly stop at a third of its size), with the KIND carried from the COM read to the verdict and NEVER re-derived from the recovery file's name, because that name is chosen from the kind and so cannot check it; an unreadable document type falls back to the document's OWN PATH and then its title (evidence about the document, not names this sweep chose) and only then to UNKNOWN, which takes a neutral `.sldrecover` name and the strictest floor — and if SOLIDWORKS refuses to write that name the file is re-saved as `.SLDPRT` with the fallback RECORDED and the unknown-kind verification unchanged; `swx_recover_list` re-runs the verdict on every file it lists and reports `verified` with the reason — a file the sweep refused is listed (never deleted: those bytes are the only ones there are) but never called a rescue, never offered as openable, and its entry says the document was left OPEN — and gives every genuine rescue its own `howToOpen`, because SOLIDWORKS will not open a `.sldrecover` file until it is renamed, published as `recoverySignatureOk` + `recoveryBytes`, and it fails CLOSED (`exists()` passes a zero-byte file and any byte floor passes a truncated one; both are what a full disk leaves). The container marker was MEASURED on 166 real documents from three hardware repositories, because the signature every reference names for a SOLIDWORKS document (OLE compound file) appears in NONE of them — verifying that, as pass 23 specified, would have refused to close every document on a modern install; **FIRST AUTONOMOUS CLOSE, live 2026-09-17**: `swx_close_all_safely {userAuthorized, batch:1}` on a bridge-launched session took 4 documents (3 same-titled pathless import temps + a throwaway part) to `recovery\20260917-150646\` under unique names (25,834 / 26,031 / 25,773 / 26,047 bytes, `recoverySignatureOk:true`, `namingFallback:null`), closed each BY PATH, count 4 → 0, `done:true`, `stoppedBy:null`, headroom 1.59 TB — nobody was asked to close anything. A document that could not be written is left OPEN and named in `remaining`; the user's saved-then-edited file is copied to recovery under a new name and their original is asserted byte-for-byte unchanged; `SaveAs3` uses `swSaveAsOptions_Silent` ALONE so the document RE-POINTS at the recovery file and the close key is read from the document after the save; a dialog stops the sweep and is never answered, with the census taken before EVERY save and EVERY close (a save can raise a prompt of its own, which a per-batch census could not see until the closes had happened); and an UNREADABLE window census is its own outcome — saves proceed, nothing closes, `stoppedBy:"dialogCensusUnknown"`. Ordering is proven from a journal, not from the end state. Every rule is mutation-verified (disable it and exactly one test fails). **Ownership measured live 2026-09-30, both halves**: a pathless `Part2` preserved (25,959 bytes, verified, listed from the manifest) and Drew's saved `R_0603_1608Metric_1.step-1.sldprt` closed with its original untouched (same 32,311 bytes, same mtime). Since 0.9.0 such a document is RECORDED as `closedInPlace` with its original's size and mtime, and `swx_recover_list` says "closed at its own path, untouched" — or that it has changed since, or is gone — by measuring the file, not by assuming it **0.9.12, from a live 34-document crate session**: an assembly session closes completely — everything preserved first, assemblies (active first) before parts, held components deferred and counted closed when they go out with their parent | ✗ | ✗ | ✗ | ✗ | ✗ |
*(51 numbered rows; rows 29–31 are the N/A block that accounts for most of the Fusion verb-count gap. Rows 36–42 added 2026-09-08 from the crate build and the launch-resilience rounds; rows 43–45 from the import-leak, quit and safe-close work, and 46–49 from the live runs of 2026-09-17 and 2026-09-30 — the bar is "significantly more powerful than the MCP servers", so every robustness capability gets a row with its evidence level, not a slogan.)*
## Per-competitor notes
### SolidPilot — eyfel/mcp-server-solidworks · **AGPL-3.0** + paid commercial · 265★ · C# + Python
The one to take seriously. Four-layer architecture: an AI planner emits a CAD-neutral **Feature Graph
IR**, a deterministic Python compiler lowers it to ordered tool calls, and a **single C# .NET 4.8
execution layer on one STA thread is the only code that touches COM**. ~46 tools, 13 MCP resources.
Its README makes verifiable-shaped claims — production parts round-tripped `analyze_model` → IR →
`rebuild_from_ir` → `compare_parts` to a `verified` match on exact topology and mass properties, nine
real manufacturing drawings reconstructed to ≤0.02% weight match. Deeper than us on modeling,
assemblies, sheet metal and drawings. Has **no** BOM (on the roadmap), no configurations, no custom
properties, no preferences, no screenshots, no macros (deliberately — the compiler replaces scripting),
no write gate, and no ecosystem beyond Claude Desktop. Its `ensure_ready` claims to launch SOLIDWORKS
via COM, which is plausible on a classic desktop install and would fail exactly as ours does on
Connected/Makers. **Evidence: README only. Not installed, not run.**
### vespo92/SolidworksMCP-TS — **MIT** · 222★ · TypeScript + `winax`
Second-most-starred and the most candid: labelled **"Alpha / Experimental"**, with the README stating
that *"most tools have not been validated against a live SolidWorks instance"* and that no real
integration tests exist. Its own coverage table grades Modeling "Partially tested" and Drawing, Export,
Analysis and Macro all **"Untested"**. Broad tool surface on paper (modeling, sketch, drawing, export,
analysis with `check_interference` and `get_mass_properties`, VBA generation, macro recording); no
assemblies, no BOM. Last pushed 2026-05. Useful as a naming/API reference, not as evidence that
anything works.
### andrewbartels1/SolidworksMCP-python — **MIT** · 67★ · Python
**122 tools** per today's README (the figure was 109 earlier — it is moving; pushed 2026-09-02), across
modeling, sketching, drawing, analysis, export, automation, templates and macros. Self-described
**"hobby/research product"** and "under active construction", and it ships an explicit mock warning:
*"Mock adapter output is simulated and should not be treated as engineering truth."* Runs in mock mode
unless started with `--real`, and `--real` **requires SOLIDWORKS to already be open** — the same
attach-only constraint we have, arrived at without comment. Explicitly does *not* do checkpoint-level
interference validation. Highest tool count in the field, lowest evidence-per-tool.
### Adam-Schildkraut/solidworks-mcp — **MIT** · 1★ · TypeScript · last push 2025-08
Small but oddly complementary: it is the **only** project with **PDM tools** (configure, check-in,
check-out, workflow, folder structure), the only one with **SQL-driven design tables** for
configurations, and it leans hardest on VBA — macro record/stop/export/execute plus a claimed **100+
VBA generation templates** covering part features, assembly mates and interference, drawing views and
tables, custom properties and batch/PDM operations. No validation statement of any kind, one star,
and its README's support links point at a different org (`vinnieespo/solidworks-mcp-server`), so treat
it as derived work of uncertain provenance. **The template library is the interesting artefact here,
not the server.**
### alisamsam/Solidworks-MCP — **MIT (verified)** · 108★ · Python · 22 tools
Task brief listed its licence as unknown; the GitHub API confirms **MIT**, 108★, last pushed 2026-03.
Deliberately minimal and honest about it: connect to a *running* instance, part/assembly documents,
six sketch primitives, extrude/cut/fillet/chamfer, list features, set units — and `execute_python`,
which makes it the only project besides ours to offer a scripting escape hatch into a live SOLIDWORKS
session. **It has no export tools at all**, no drawings, no assembly mates, no BOM, no properties. It
is a clean starter kit, not a competitor for real work.
## Licensing
**This is the section with a decision in it.**
**SolidPilot (eyfel/mcp-server-solidworks) — AGPL-3.0, dual-licensed commercially.** Verified from the
repository's own licence metadata, not a badge. AGPL-3.0 is the strongest common copyleft: it extends
GPL's obligations to network use, so **anything we distribute that links or incorporates AGPL code must
itself be released under AGPL, source included** — and under the network clause, even offering it as a
hosted service to users triggers the same obligation. For a bridge that ships inside Adom Bridge to
customers, that is not a licence we can absorb. The author offers a **paid commercial licence** as the
escape hatch. **Conclusion: read it, learn from its architecture — the Feature Graph IR and the
single-STA-thread C# COM boundary are both good ideas — and copy neither its code nor its files.** Any
IR-shaped work of ours must be independently written. If we ever want its code proper, that is a
procurement conversation, not an engineering one.
**vespo92/SolidworksMCP-TS — MIT.** Verified. Permissive; we could vendor or adapt code with attribution.
Given the project's own "most tools not validated" disclaimer there is little worth vendoring, but its
tool naming is a fair reference.
**andrewbartels1/SolidworksMCP-python — MIT.** Verified. Permissive. Same caveat: mock-simulated output
by default, so its value is as a map of the COM surface rather than as working code.
**Adam-Schildkraut/solidworks-mcp — MIT.** Verified. Permissive, and the **VBA template library is the
one asset in the whole survey that MIT actually makes attractive to us** — if the macros route
(`RunMacro2`) proves out, 100+ MIT-licensed VBA templates are a legitimate head start. Provenance is
murky enough that we should check the templates' own headers before reusing them.
**alisamsam/Solidworks-MCP — MIT.** Verified (previously unknown to us).
**swx — MIT** (`bridge.json`, `LICENSE`). We are on the permissive side of the field with everyone
except SolidPilot. Exactly one copyleft player; everything else MIT.
## Additional items we can pull off
Capabilities **nobody** in this field has, which swx could add at low cost, roughly in order of
value-per-effort:
1. **Drawing-sheet outputs — PDF + BOM tables from a `.slddrw`.** Our DXF/DWG/PDF exports are already
built and refused for a part, which is the expected behaviour; the drawing is their real story and
it is untested. SolidPilot builds drawings but does not ship a BOM; Schildkraut inserts BOM tables
but has no evidence. **A live-proven drawing → PDF-with-BOM path would be unique in this field.**
2. **Sanctioned launch via the 3DEXPERIENCE chain** (`CATSTART.exe` → `SWXDesktopLauncher`, found
2026-09-03). Closes our loudest documented "cannot", and no competitor has solved launch on a
Connected edition — bartels and alisamsam simply require the app to be open already.
3. **A macros bridge** (`RunMacro2` for `.swp`, then VSTA / C# add-ins). Buys back most of the
in-process-scripting gap and would let us reuse an MIT template corpus. Caveat to settle first: the
Makers edition restricts third-party add-ins but does run macros — which is precisely why macros,
not add-ins, are the first move.
4. **Configurations as a first-class surface.** We are already configuration-aware in BOM and
properties; enumerating, activating and diffing configurations is a small step, and Fusion has no
equivalent concept at all. Design tables (Schildkraut's SQL trick) are the stretch goal.
5. **Pack and Go, proven live.** Built and gated already; it needs an assembly with references to
exercise. Nobody else has it.
6. **The action ledger and measured verb timings as a product feature, not plumbing.** We have p90s from
real hardware (`run_script` 10.2s, `new_document` 9.2s, `import` 7.8s, `save_as` 2.7s, all far inside
budget). No competitor can tell a user what an operation will cost.
7. **Wiki / molecule integration.** Native GLB export already works live; the pipeline from a
SOLIDWORKS part to a published molecule is ours to connect and is not even conceivable for a bare
MCP server.
8. **Ship the deny-by-default posture as the marketed differentiator.** It is the single strongest
claim we have and it is *evidenced*: eight adversarial rounds, two independently-enforcing layers,
and three live runs in which the bridge refused to touch the user's own open document — including
one abort where it removed every file it had written. Every competitor in this survey will, on
request, write to a path the user owns with no confirmation and no record.
9. **Per-component mass properties** — small, and blocked only on being able to populate an assembly.
## What is still unproven, and where
Row 44 is no longer unproven: the quit ladder's rung (a) has quit a real SOLIDWORKS twice, and on
2026-09-30 `tools/quit-gate.py` ran its full cycle — quit, measure, relaunch — through the bridge ab
hosts. Rungs (b)–(f) have still never run live, and nothing has needed them: the ladder ships pinned
at rung (a), because being *wrong* on a later rung would cost the user a 1-3 minute relaunch that can
fail. Five of the six MCP servers surveyed never attempt a quit at all, and the sixth reaches for a
kill.
The newest open question is about testing rather than capability: adom-bridge 2.1.163 terminates a
second `swx-bridge.exe` within 30 s, so the side-loaded dev copy the gates used is gone, and which
dev route ab tolerates (a prerelease install, or a renamed exe reached with `SWX_BRIDGE_URL`) has not
been measured. Until it is, remember that ab hosts whatever the published manifest names — **a
release IS a deploy to every machine**.
Nothing above changes the standing recommendation: **run `tools/live-smoke.py`** once SOLIDWORKS is
back up, started from the 3DEXPERIENCE Platform. It is what converts the ⚠ mock cells in column B into
✓ live — or finds the next bug, which is what happened all three previous times. The assembly verbs
(`swx_bom`, `swx_interference`, per-component mass properties) need a real multi-component assembly or a
classic desktop install; the 2D exports need a real `.slddrw`. And no competitor cell in this table is
better than read-from-README, because none of them was installed or run.