Metadata-Version: 2.4
Name: dcc-mcp-3dsmax
Version: 0.1.5
Summary: 3ds Max plugin for the DCC Model Context Protocol (MCP) ecosystem — embeds a Streamable HTTP MCP server directly inside 3ds Max
Project-URL: Homepage, https://github.com/loonghao/dcc-mcp-3dsmax
Project-URL: Repository, https://github.com/loonghao/dcc-mcp-3dsmax
Project-URL: Issues, https://github.com/loonghao/dcc-mcp-3dsmax/issues
Project-URL: Changelog, https://github.com/loonghao/dcc-mcp-3dsmax/releases
Author-email: Long Hao <hal.long@outlook.com>
License: MIT
License-File: LICENSE
Keywords: 3ds-max,3dsmax,ai,dcc,llm,mcp,model-context-protocol
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
Requires-Dist: dcc-mcp-core<1.0.0,>=0.17.23
Requires-Dist: dcc-mcp-server<1.0.0,>=0.17.23
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: hatchling; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.1.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: pyyaml>=5.0; extra == 'dev'
Requires-Dist: requests>=2.28.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Requires-Dist: tomli; (python_version < '3.11') and extra == 'dev'
Description-Content-Type: text/markdown

# dcc-mcp-3dsmax

3ds Max plugin for the DCC Model Context Protocol (MCP) ecosystem.

> **Status:** This project is under active development. APIs, packaging, and 3ds Max integration details may change quickly while the adapter tracks the latest `dcc-mcp-core` releases.

## Features

- **Sidecar MCP Server**: Starts `dcc-mcp-server.exe sidecar` and keeps 3ds Max scene edits on the main thread
- **Progressive Skill Loading**: Discover skills without loading them immediately
- **Shared Gateway**: Registers with the stable gateway at `http://127.0.0.1:9765/mcp`
- **Job Persistence**: SQLite-based job storage for long-running operations
- **Prometheus Metrics**: Optional `/metrics` endpoint for monitoring

## Installation

```bash
pip install dcc-mcp-3dsmax
```

## Quickstart (inside 3ds Max MAXScript Listener)

```python
import dcc_mcp_3dsmax

# Start on a random instance port; the public gateway stays fixed.
server = dcc_mcp_3dsmax.start_server()

# Progressive loading — discover skills without loading them immediately
n = server.discover_skills()        # scan paths, register tool metadata
server.load_skill("3dsmax-scene")  # lazy-load a specific skill

dcc_mcp_3dsmax.stop_server()
```

## Sidecar Bridge

Start the sidecar bootstrap inside 3ds Max:

```maxscript
python.ExecuteFile @"C:\path\to\dcc-mcp-3dsmax\examples\start_sidecar_bridge.py"
```

This starts the random-port `/dispatch` bridge for main-thread scene edits, a
random-port `qtserver://` bridge for the sidecar process, and registers the
3ds Max instance with the stable gateway at `http://127.0.0.1:9765/mcp`.
See `docs/SIDECAR.md`.

The bootstrap also installs a `DCC MCP` menu with Start Sidecar, Stop Sidecar,
Open Gateway Admin, and Print Status commands. 3ds Max shutdown triggers the
same stop path via `#preSystemShutdown`, so the sidecar process and local
bridges are cleaned up when the host exits.

## Skill Development

Create a skill with `SKILL.md` metadata file and Python scripts:

```python
# my_skill/action_create_box.py
from dcc_mcp_3dsmax.api import max_success, with_max

@with_max
def main(width: float = 100.0, height: float = 100.0, depth: float = 100.0) -> dict:
    import pymxs
    rt = pymxs.runtime

    box_obj = rt.Box(width=width, height=height, depth=depth)
    return max_success("Created box", object_name=str(box_obj))
```

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `DCC_MCP_3DSMAX_METRICS` | Enable Prometheus `/metrics` endpoint | `0` |
| `DCC_MCP_3DSMAX_JOB_STORAGE` | Path to SQLite job database | platform default |
| `DCC_MCP_3DSMAX_DISABLE_EXECUTE_PYTHON` | Disable `execute_python` tool | `0` |
| `DCC_MCP_3DSMAX_DISABLE_ARBITRARY_SCRIPT` | Disable all arbitrary script execution | `0` |
| `DCC_MCP_3DSMAX_ENABLE_GATEWAY_FAILOVER` | Enable gateway failover | `1` |
| `DCC_MCP_3DSMAX_SKILL_PATHS` | Extra skill search paths (semicolon-separated) | None |
| `DCC_MCP_3DSMAX_BRIDGE_PORT` | Sidecar bridge localhost port | random |
| `DCC_MCP_3DSMAX_SIDECAR_LOG` | Explicit stdout/stderr log file for the sidecar subprocess | platform log dir |
| `DCC_MCP_3DSMAX_SIDECAR_LOG_DIR` | Directory for default sidecar stdout/stderr logs | core log dir |
| `DCC_MCP_3DSMAX_SIDECAR_LOG_RETENTION_DAYS` | Days to keep default sidecar logs | `14` |
| `DCC_MCP_3DSMAX_SIDECAR_LOG_MAX_BYTES` | Rotate a default sidecar log after this size | `10485760` |
| `DCC_MCP_3DSMAX_SIDECAR_LOG_MAX_FILES` | Rotated default sidecar log files to keep | `5` |
| `DCC_MCP_3DSMAX_BOOTSTRAP_PATHS` | Extra package Python roots for startup bootstrapping | None |
| `DCC_MCP_PYTHONPATHS` | Shared package Python roots for Rez/pipeline launchers | None |
| `DCC_MCP_3DSMAX_ROOT` | Adapter package root; startup probes `python`, `python37`, `src`, and root | None |
| `DCC_MCP_CORE_ROOT` | `dcc-mcp-core` package root; startup probes `python`, `python37`, `src`, and root | None |
| `DCC_MCP_SERVER_ROOT` | `dcc-mcp-server` package root; startup probes Python roots and sidecar binary locations | None |
| `DCC_MCP_SERVER_BIN` | Explicit `dcc-mcp-server` executable path | auto-detect |
| `DCC_MCP_REGISTRY_DIR` | Optional shared gateway/sidecar registry override | core default |

For Rez-style deployment, launch 3ds Max with package roots in the environment
instead of copying packages into the user scripts folder. A pipeline package
cache can expose paths such as `<package-cache>/dcc_mcp_core`,
`<package-cache>/dcc_mcp_3dsmax`, and `<package-cache>/dcc_mcp_server`
through the root variables above.
The MZP installer uses isolated version directories under
`<user scripts>/dcc_mcp_3dsmax/versions/`, so installing a new payload does not
delete the version that may already be loaded by the running 3ds Max process.
Uninstall cleanup uses the import-light lifecycle helpers from `dcc-mcp-core`
when available, so locked native files are reported as restart-required instead
of disappearing into a generic `PermissionError`.

## Requirements

- 3ds Max 2017 or later (Python 3.x with pymxs support)
- Python >= 3.7
- dcc-mcp-core >= 0.17.23
- dcc-mcp-server >= 0.17.23

## License

MIT
