mcp-for-clo3d
by ttiimmaacc
README.md
# MCP for CLO3D
Control CLO3D from Claude, Codex, Cursor or any MCP client: inspect projects, build and edit
pattern pieces, manage fabrics and colorways, run simulations and export models, all from a chat.
```
AI assistant <-- MCP --> MCP server (Python) <-- files --> CLO plug-in (native DLL) --> CLO3D
src/clo3d_mcp %TEMP%\clo3d_mcp cpp_plugin/
```
CLO stays fully usable while the plug-in listens. Requests are answered in roughly 50 ms.
Tested with **CLO 2025.2.236 on Windows**.
## Why a native plug-in
CLO's embedded Python cannot serve requests in the background:
- background threads stop running once a script returns,
- a polling loop on the main thread freezes CLO,
- CLO ships no Qt bindings for Python, so there is no timer to hook, and
- `rest_api.CallbackRestRequest`, the only asynchronous call, cannot accept a Python callback
in this build.
So the CLO side is a small C++ plug-in built on CLO's official SDK. It runs a timer on CLO's UI
thread, so every request is executed on the main thread between UI events.
## Setup
### 1. Get the plug-in DLL
Download `CloMcpPlugin.dll` from the
[latest release](https://github.com/ttiimmaacc/mcp-for-clo3d/releases/latest). Each release says
which CLO version it's for, and the DLL only works with that exact CLO build (currently
**2025.2.236**). GitHub Actions builds every release from this repo against CLO's official SDK,
and each release includes the DLL's SHA-256 checksum.
<details>
<summary>Or build it yourself (needed for any other CLO version)</summary>
CLO's SDK files can't be redistributed, so you download the SDK yourself.
1. Install **Visual Studio Build Tools** with the *Desktop development with C++* workload.
2. Download the CLO SDK that matches your CLO version from
[developer.clo3d.com/download.html](https://developer.clo3d.com/download.html)
(CLO 2025.2.236 → SDK v9.1.0, `CLO_SDK_v2025.2.236_WIN.zip`) and unzip it.
3. Point `CLO_SDK_DIR` at the unzipped folder (the one containing `CLOAPIInterface\`) and build:
```bat
set CLO_SDK_DIR=C:\path\to\CLO_SDK_v2025.2.236_WIN
cpp_plugin\build.bat
python cpp_plugin\check_runtime.py
```
`check_runtime.py` confirms that every C++ runtime function the DLL imports exists in the
runtime DLLs your CLO install ships, because CLO loads its own copies.
> **Use the SDK for your exact CLO version.** The plug-in calls CLO through C++ vtables. Headers
> from another CLO version put functions at different slots and will call the wrong ones.
</details>
### 2. Register it in CLO
1. **Plugins → Plug-in Manager → + ADD**, choose `CloMcpPlugin.dll`, name it, **OK**.
2. **Plugins → Plug-in → CLO MCP Listener (start/stop)** now appears. The listener starts
when CLO loads the plug-in. Clicking the item stops or starts it and shows a message box with
the new state.
To check that it is running, open `%TEMP%\clo3d_mcp\status.json`. It should show
`"state": "listening"` and a `ticks` count that keeps rising.
### 3. Connect your MCP client
The server runs with [uv](https://docs.astral.sh/uv/).
**Claude Code**
```bash
claude mcp add clo3d -- uvx --from git+https://github.com/ttiimmaacc/mcp-for-clo3d.git mcp-for-clo3d
```
**Claude Desktop** (`claude_desktop_config.json`)
```json
{
"mcpServers": {
"clo3d": {
"command": "uvx",
"args": ["--from", "git+https://github.com/ttiimmaacc/mcp-for-clo3d.git", "mcp-for-clo3d"]
}
}
}
```
**Codex** (`~/.codex/config.toml`)
```toml
[mcp_servers.clo3d]
command = "uvx"
args = ["--from", "git+https://github.com/ttiimmaacc/mcp-for-clo3d.git", "mcp-for-clo3d"]
tool_timeout_sec = 200 # simulations and exports can take up to 180 s
```
Only connect one client to CLO at a time, because they share the same request file.
Then ask things like *"What's in this project?"*, *"Create a rectangle pattern 400 × 600 mm"*,
*"Run 100 simulation steps and export a GLB to my desktop"*.
## Tools
| Area | Tools |
|------|-------|
| Scene | `get_project_info`, `new_project`, `open_file`, `save_project`, `get_garment_info`, `import_file` |
| Patterns | `get_pattern_count`, `get_pattern_list`, `get_pattern_info`, `get_pattern_bounding_box`, `set_pattern_name`, `copy_pattern`, `delete_pattern`, `flip_pattern`, `create_pattern`, `get_arrangement_list` |
| Fabrics | `get_fabric_list`, `add_fabric`, `replace_fabric`, `assign_fabric_to_pattern`, `set_fabric_color`, `get_fabric_for_pattern` |
| Export | `export_obj`, `export_fbx`, `export_glb`, `export_gltf`, `export_thumbnail`, `export_snapshot`, `export_turntable`, `export_tech_pack` |
| Simulation | `simulate` |
| Colorways | `get_colorways`, `set_current_colorway` |
The plug-in also implements `ping`, fabric/colorway deletion, colorway copy/rename, avatar
queries and simulation quality. These aren't exposed as MCP tools yet.
## How it works
- The **MCP server** (`src/clo3d_mcp`) writes `request.json` to `%TEMP%\clo3d_mcp` (override
with `CLO3D_MCP_DIR`) and waits up to 180 s for `response.json`. Both sides write to a temp
file and rename it into place.
- The **plug-in** (`cpp_plugin/CloMcpPlugin.cpp`) creates a hidden message-only window with a
50 ms timer. CLO's event loop dispatches the timer, so the plug-in reads the request, calls the
CLO API on the main thread and writes the response. It never blocks CLO.
- The plug-in pins itself in memory, because CLO loads the DLL to read its menu name and unloads it
again during registration. Only one listener runs per CLO process.
- Native faults inside a command are caught (built with `/EHa`) and returned as an error
instead of taking CLO down.
- To stop the listener without the menu, create an empty file named `stop` in the request folder.
## Development
```bash
uv run --with pytest pytest # server tests (mock plug-in)
cpp_plugin\test\build_tests.bat # builds two stand-in hosts that load the real DLL outside CLO
python cpp_plugin\test\smoke_test.py # DLL + stand-in host + MCP client, end to end
```
`host.exe` loads the plug-in and runs a Win32 event loop. `host_add.exe` reproduces the
Plug-in Manager's load → read name → unload sequence. Both use CLO's real `CLOAPIInterface.dll`
with fake API objects, so you can test the plug-in and the MCP client without CLO.
### Releases
[`.github/workflows/build.yml`](.github/workflows/build.yml) runs on every push and pull request.
It downloads CLO's SDK from CLO's official link (checksum-pinned, never committed), builds the DLL,
checks its imports against CLO's runtime export lists in `cpp_plugin/clo_exports/<version>/`, and
runs the tests and smoke test. Pushing a tag publishes a release:
```bash
git tag v0.1.0
git push origin v0.1.0
```
To support a new CLO version, update `CLO_VERSION`, `CLO_SDK_URL` and `CLO_SDK_SHA256` in the
workflow. Then, on a machine with that CLO installed, run
`python cpp_plugin\check_runtime.py --write-exports cpp_plugin\clo_exports\<version>` and commit
the result.
## Troubleshooting
- **The client times out:** check `status.json`. If it's missing or `ticks` isn't rising, start
the listener from **Plugins → Plug-in**.
- **Rebuilding fails with `LNK1104: cannot open file ...CloMcpPlugin.dll`:** CLO has the DLL
loaded. Close CLO, then rebuild.
- **CLO crashes when adding the plug-in, or calls do odd things:** the SDK doesn't match your CLO
version.
## Credits and licence
MIT, see [LICENSE](LICENSE). The Python MCP server started from
[Ubani-Studio/clo3d-mcp](https://github.com/Ubani-Studio/clo3d-mcp) by Violet Sphinx (MIT).
This project replaces its Python CLO plug-in with the native plug-in.
CLO's SDK is **not** included and is not covered by this licence. See [NOTICE](NOTICE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues