max-mcp
Integrates with a running Autodesk 3ds Max session, letting an AI assistant read the current selection, query objects and layers, hide/show layers, capture viewport screenshots, and execute MAXScript or Python (pymxs) in the live scene, with every scene change recorded as a named undo step that can be audited and reverted from 3ds Max's history.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@max-mcpcapture the active viewport and list every object on the Walls layer"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
max-mcp
Let an AI assistant work inside your running Autodesk 3ds Max session, and keep the user in control of what it changed.
max-mcp is an MCP server for 3ds Max. Any MCP client (Claude Code, Claude Desktop, Cursor, Gemini CLI, ChatGPT developer mode, custom agents over HTTP) can read the selection, query objects and layers, grab the viewport, and run MAXScript or Python (pymxs) in the live scene. Every request is logged, every scene change is a named undo record, and the AI can only undo its own steps.
Why this project - archviz work in 3ds Max is full of repetitive scene surgery (renaming, layer sorting, batch property edits, checks) that an assistant can do well, but only if it sees the open scene and the user can audit and reverse what it did. Headless batch scripts can't see the open scene; most bridges give the AI a raw "run script" tool and nothing else. max-mcp is the small, model-agnostic layer in between. It is also a portfolio piece.
The max-mcp window inside 3ds Max: History tab with per-request undo state, scene diff and the code that ran.
How it works
Piece | Runs in | Depends on |
| 3ds Max (its own Python 3.11) |
|
| your Python 3.10+ | official |
The listener accepts newline-delimited JSON on 127.0.0.1:30025; the MCP server
(stdio or streamable HTTP) forwards tool calls to it. Commands run on Max's main
thread (see below). The bridge never saves your scene and has no save tool.
Tested with 3ds Max 2025 (Python 3.11.8, PySide6 6.5.3). Other versions that
ship pymxs + PySide6 should work but are untested.
Related MCP server: 3dsmax-mcp
Install
git clone <repo-url> max-mcp
cd max-mcp
pip install . # or pip install -e . (editable)
# without installing: uvx --from . max-mcpNo installer: the listener only needs its folder on sys.path, which the
start script does by itself (it also drops the two action icons into Max's
usericons folder, see below).
1. Load it inside 3ds Max
Scripting > Run Script... and pick max_side/max_mcp_start.ms. The
MAXScript Listener prints [MaxMcp] dinleniyor 127.0.0.1:30025 and the window
is available as macroScript MaxMcp Settings (category max-mcp, add it to
any menu/toolbar/quad via Customize > Customize User Interface), or with
python.Execute "import max_mcp_ui; max_mcp_ui.show()".
Both actions, MaxMcp Settings and MaxMcp Start/Stop (a check button that
stays highlighted while the listener runs), come with SVG icons, so they can go
on the ribbon too: right-click the ribbon > Customize Ribbon, pick category
max-mcp in the action list and drag them onto a panel. The icons live in
max_side/icons/MaxMcp/; the macro file copies them to Max's per-user
usericons\MaxMcp folder when they are missing or changed. That folder is the
only thing written outside the repo besides the optional startup loader.
To load it automatically at startup, press Install loader in the window
(writes a one-line max_mcp_loader.ms into Max's per-user startup folder;
Remove loader deletes it) or use the CLI:
python -m max_mcp.paths # shows detected paths and the loader text, writes nothing
python -m max_mcp.paths --write # writes the loaderWhether the listener actually starts at startup is the autostart setting.
2. Register the MCP server in your client
The window's Client configuration box generates these for your current
port/key (press Copy). Defaults shown; replace python with the interpreter
that has mcp installed.
Claude Code
claude mcp add -s user max -- python -m max_mcp.server
# HTTP transport:
claude mcp add -s user --transport http max http://127.0.0.1:30026/mcpClaude Desktop (claude_desktop_config.json), Cursor (.cursor/mcp.json
or global MCP settings), Gemini CLI (~/.gemini/settings.json) - all use
the same mcpServers shape:
{ "mcpServers": { "max": { "command": "python", "args": ["-m", "max_mcp.server"] } } }Gemini CLI's HTTP form uses "httpUrl": "http://127.0.0.1:30026/mcp"; Cursor's
uses "url". These shapes follow each vendor's public docs at the time of
writing but were not verified by running those clients here; only Claude
Code and the official mcp Python client were tested.
HTTP / remote clients (ChatGPT developer mode, OpenAI/xAI remote MCP tools, custom agents) - run the HTTP transport and point the client at the URL:
python -m max_mcp.server --transport http # http://127.0.0.1:30026/mcp
python -m max_mcp.server --transport http --http-host 0.0.0.0 --key <secret> # LAN; key mandatoryWith a key, clients must send Authorization: Bearer <secret>. Hosted services
need the URL to be reachable from the internet (a tunnel such as ngrok or
cloudflared, over HTTPS) - not verified here, and exposing Max's script
execution to the internet is your risk to take.
Configuration
Settings live in %LOCALAPPDATA%\max-mcp\config.json (override the path with
MAX_MCP_CONFIG) and are edited in the window. Precedence, highest first:
environment variable > command-line argument > config file > default.
Key | Env | Default | Meaning |
|
| 30025 | listener TCP port |
|
| 127.0.0.1 | listener bind address |
|
| "" / false | shared key (env var implies enabled) |
|
| true | start listener with Max (needs loader) |
|
| 50 | main-thread pump interval |
|
| 60 | seconds a call may wait for Max |
|
| 127.0.0.1 / 30026 | streamable-HTTP bind |
|
| off |
|
|
| 10 / 2048 | checkpoint retention |
|
| 5 | history.jsonl size before rotation |
|
| true | may the |
Server CLI: --transport stdio|http --port --host --key --timeout --http-host --http-port --config.
Tools
Tool | Parameters | What it does | Undoable |
| - | version, scene path, dirty flag, units, counts, renderer, listener status | read-only |
|
| selected objects | read-only |
|
| find objects; | read-only |
| - | layers with hidden/frozen/current flags and object counts | read-only |
|
| hide/show a layer | yes - |
|
| active viewport to PNG, returns the path | read-only (writes the PNG) |
|
| run MAXScript; returns the last value ( | yes when |
|
| run Python in Max; | yes when |
|
| the command history (see below) | read-only |
|
| undo the bridge's own records only | it is the undo |
Object records contain name, class, layer, pos, hidden; with detail=true
also superclass, bbox_min/max, rotation, scale, parent, children, frozen, selected, wirecolor, material {name, class}, user_props, faces.
History, undo and checkpoints
Every request is appended to <config dir>/history.jsonl (rotated at
history_max_mb, two older files kept) with time, MCP client name
(clientInfo), tool, argument summary, full args, duration, ok/error, output,
objects added/removed, selection before/after and a "scene changed" flag from
Max's undo put counter. The History tab of the window shows the rows; a row
reveals the full code and output, Copy code and Re-run act on it.
Undo records. Scene-changing tools are accepted as one undo record each,
labelled MCP: <tool> #<id>, so Ctrl+Z in Max undoes exactly one request. An
error inside the record cancels it (partial changes are rolled back) and the
error is returned.
max_undo (the AI). Undoes the last steps records or everything down to
to_history_id - but only if every level on the way is a bridge record. The
bridge reads the real stack (theHold.getUndoNames()), identifies its own
levels by label and depth, and verifies after each max undo. If a user's
manual step sits in between the call is refused and names the step; if the
target has left the undo stack it fails. (When the pump runs inside a
python.Execute call - the dotNet-timer fallback - Max names every level
"MAXScript"; the depth bookkeeping still works, but once the stack is full
and Max starts dropping old levels those records are reported as gone rather
than guessed.) Undone entries are marked
undone in the history; the undo call is itself a history row. The
"AI may undo its own steps" switch in the window turns the tool off
(it then returns "disabled"). There is no max_redo: Max clears the redo
stack on the next change, and the next AI request is a change, so a redo tool
would almost never have anything to redo; Ctrl+Y in Max covers the rare case.
Revert to here (the user). The History tab can undo back to any record still on the stack, including past the user's own steps - after a confirmation that lists them. Rows whose record is gone are grey ("gone" / "undone").
Checkpoints (optional, default off). With checkpoint_mode = changing
(or all) the bridge copies the scene before each request with
saveMaxFile <copy> useNewFile:false quiet:true, which keeps the scene's
own file name and path and never touches your file; the "modified" flag is
restored afterwards. Default off because a full scene write before every
command is slow on large scenes and the undo records already cover normal use;
turn it on for risky sessions. Copies live in <config dir>/checkpoints,
limited by count and total size, oldest deleted first.
Restoring a checkpoint is deliberately NOT an MCP tool. It replaces the
whole scene and discards everything done since, including the user's manual
work, so it only exists as Restore checkpoint in the History tab, behind a
confirmation. The restore goes through Max's Hold/Fetch mechanism (the copy is
placed as maxhold.mx and fetched), so the scene keeps its file name and path
and nothing is written to your file until you save.
The window also shows and sets Max's undo levels (theHold.setMaxUndoLevels).
How the main-thread problem is solved
pymxs must only be used from Max's main (UI) thread. The listener never
touches Max from its socket threads: every request is queued, and a PySide6
QTimer on the main thread drains the queue, runs the handler and hands the
result back through a threading.Event. Max's own Qt event loop fires the
timer. max_mcp_start.ms falls back to a System.Windows.Forms.Timer calling
max_mcp_listener.pump() if the QTimer cannot be created.
Consequences:
A call waits at most
timeoutseconds for the main thread. If Max is busy (rendering, a long script, a modal dialog blocking the event loop) the call returns a timeout error; a job that had not started is dropped, one already running keeps running and its result is discarded.A long command blocks the Max UI for its duration and cannot be interrupted from outside. Keep
max_run_*snippets short or raisetimeoutdeliberately.When Max closes, the socket closes; the MCP server reports "cannot reach the 3ds Max listener" until Max (with the listener) is back. A fresh connection is opened per call, so nothing needs a restart on the MCP side.
Security
The listener binds to
127.0.0.1by default; the HTTP transport too. Binding HTTP to any other address requires a key (the server refuses to start otherwise); clients sendAuthorization: Bearer <key>.max_run_maxscript/max_run_pythonexecute arbitrary code inside Max with your user rights. On a single-user machine any local process already has that power, so the key is off by default; enable it (Generate + "require shared key") on shared machines or whenever HTTP leaves localhost.The bridge never saves the scene. It writes: the history file, optional checkpoint copies, viewport PNGs where you ask for them, and (only through the window's Install/Remove buttons) the startup loader.
Tests
pip install -e .[dev]
pytest # unit tests, no 3ds Max required (fake pymxs, fake undo stack)
python tests/e2e_batch.py # optional: headless 3dsmaxbatch round trip, needs Max installedUnit tests cover the protocol/queue/timeout machinery, every handler against a
fake pymxs, config precedence, the UI-free settings model, history rotation,
undo bookkeeping (own steps only, refusal on user steps, target gone, switch
off), checkpoint naming/pruning, and the streamable-HTTP transport with the
official MCP client (key required / 401 / public bind refused).
The headless test runs the listener with serve_blocking() on Max's main
thread because 3dsmaxbatch has no Qt event loop while a script runs, so the
QTimer pump and the window are only exercised in an interactive Max:
Open 3ds Max, run
max_side/max_mcp_start.ms.In a terminal:
python -c "from max_mcp import client; print(client.call('info'))"-pump_modeshould readqt.From your MCP client:
max_selection, thenmax_run_pythoncreating a box, thenmax_undo- the box disappears; press Ctrl+Z / look at the History tab.
Troubleshooting
"cannot reach the 3ds Max listener" - Max not running, listener not started, or different ports on the two sides. Check the MAXScript Listener for
[MaxMcp] dinleniyor ...;python -m max_mcp.pathsconfirms paths.Every call times out - the pump is not running (modal dialog, timer never created). Close the dialog; Restart in the window.
max_infoshowspump_modeandpump_on_main_thread.max_undorefused - a manual step is on top of the AI's; use the window's Revert (it asks) or Ctrl+Z yourself.Port in use - change it in the window (Save + Restart) and re-copy the client config.
Viewport capture in batch mode - works, but shows the default headless viewport; meaningful only in interactive Max.
Known limitations (found in live testing)
Modal dialogs block the bridge. If a command makes 3ds Max show a modal message box, Max's main thread waits until someone clicks OK. Example: ProBoolean showing "Invalid Boolean". While it waits, every request times out. Prefer operations that do not raise UI, such as building the mesh yourself instead of using a boolean.
Operations that commit their own undo records (ProBoolean, for example) are now merged into the single
MCP: <tool> #idlevel bytheHold.SuperBegin/SuperAccept. Objects created after such an operation in the same command can still end up outside the undo record. Keep these operations in a separate command, or avoid them.Multi-statement MAXScript runs line by line. Statements before a compile error in a later line have already executed.
What makes it different
Several 3ds Max MCP servers already exist, and some are much larger than this one (150–380 tools). This project makes different trade-offs:
The user can see every AI action and roll it back. Each request is listed in a History panel inside Max with its client, code, result and changed objects. The user can return to any listed step with one click. The AI can undo only its own steps (
max_undo): it refuses if a manual user step sits in between. Restoring a scene checkpoint is never exposed as a tool. In the projects we looked at, undo was exposed as a tool the AI calls, and we did not find a user-facing history panel with rollback. This was not an exhaustive survey.Settings live inside Max. Port, bind address, shared key, autostart, AI-undo switch, checkpoints and ready-to-copy client configs are all in one dialog. Other projects use config files, environment variables or an installer.
The tool set is small on purpose (~10 tools, plus MAXScript and Python for everything else). This means less context for the model and a smaller attack surface.
There is no save tool. The bridge never writes over the user's scene file. Checkpoints are copies in a temp folder, and the scene's path and name stay the same.
No dependencies on the Max side. It uses only pymxs, the standard library and Max's bundled PySide6. All work runs on Max's main thread. The project is MIT licensed.
Undo has limits, as it does in every DCC. Effects outside the scene are not reverted by undo: files written, renders started, assets exported. The "Undoable" column in the tool table marks these cases.
Türkçe kısa not
Max'te max_side/max_mcp_start.ms çalıştır (pencereden "Install loader" ile
startup'a yükleyici konur), sonra istemcine python -m max_mcp.server kaydet
(pencerenin "Client configuration" kutusu metni üretir). Köprü sahneyi asla
kaydetmez; her değişiklik MCP: <araç> #<id> adlı bir undo kaydı. max_undo
yalnız yapay zekânın kendi adımlarını geri alır, araya senin adımın girdiyse
reddeder; senin adımlarını da geçen geri dönüş ve kontrol noktası yükleme yalnız
penceredeki onaylı düğmelerle yapılır.
License
MIT - see LICENSE.
Available Tools
10 toolsmax_historyA
Read the bridge's command history (time, client, tool, summary, duration, ok/error, objects added/removed, selection, undo_state). undo_state is 'on_stack' (max_undo can target it), 'undone' or 'gone'. full=True includes complete args and output.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | ||
| tool | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose real behavioral traits: the exact record shape, the three undo_state lifecycle values, and that full=True returns complete args and output. It omits whether history is bounded, truncated by limit, or persisted across sessions, which leaves a gap for a read tool with no safety annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with zero waste; the returned-field list sits in a compact parenthetical and the most decision-relevant fact (undo_state semantics) is pushed early. Nothing is repeated from the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description need not explain returns, and it still supplies the undo_state vocabulary that the schema lacks. Missing only the filtering/limit behavior, which matters for predictable invocation but is a narrow gap given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the two unexplained parameters (`tool`, `limit`) are documented nowhere at all — the agent cannot tell from either source that `tool` filters the history by tool name or that `limit` defaults to 30. The description compensates for `full` only, leaving two of three parameters opaque.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read the bridge's command history') and enumerates the record fields returned, so the agent knows exactly what it gets. It does not position itself against named siblings such as max_info or max_undo beyond the undo_state note, so sibling differentiation is only partial.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the description explains when to set full=True and links 'on_stack' records to max_undo, which is genuinely useful routing. But it never says when to call this tool versus max_info or max_query_objects, and gives no guidance on the `tool` filter or the limit default.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_infoA
Check the connection and return Max version, open scene path, dirty flag, units, object/selection counts, renderer and listener status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the burden; it does signal that this is a connection/state inspection that returns information rather than changing anything. However, it never states outright that it is read-only or non-destructive, nor whether the connection check can fail in a particular way, leaving safety and failure semantics to inference.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence: the action first, then the payload. It is efficient, but the long tail of return fields partly duplicates what the output schema already enumerates, so a few of those clauses add less than they could.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only status tool with a declared output schema, the description is essentially sufficient: an agent knows what calling it yields and can rely on the schema for the exact shape. The only real gap is that it does not say when to prefer it over the more targeted query siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate. The enumerated return fields are extra information, though they overlap with the output schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Check') plus an enumerated set of returned facts (Max version, scene path, dirty flag, units, counts, renderer, listener status), which makes the resource clear. It is implicitly distinguishable from siblings like max_query_objects and max_layers because it returns environment-level state rather than object lists, but it never names those siblings to draw the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Check the connection' hints that this is a good first call to verify the Max session is alive before other operations, but that is left implicit. There is no explicit when-to-use/when-not guidance and no mention of alternatives for narrower queries such as selection or layer inspection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_layersA
List all layers with hidden/frozen/current flags and object counts.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of disclosure; it does convey that this is a non-destructive listing and what fields come back. It says nothing about ordering, scope (all layers vs. active scene), or pagination behavior, which are the remaining behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no waste; every phrase (layers, flags, object counts) maps to information the caller needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and an output schema present, the description needn't explain return structure, and it covers the essentials for a simple listing tool. Missing only minor scoping detail on which layers are enumerated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline of 4 applies. The description correctly implies no filtering arguments are needed, matching the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List') and resource ('layers') and enumerates the returned attributes (hidden/frozen/current flags, object counts). This clearly separates it from the mutating sibling max_set_layer_hidden, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage only: the read-only listing framing suggests when to reach for it, but there is no explicit statement of when to use this versus max_info or max_query_objects, and no exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_query_objectsB
Find scene objects. name_pattern is a MAXScript wildcard ('Wall_*', 'door', case-insensitive); class_name matches classOf (e.g. 'Editable_Poly', 'Box'); layer matches the layer name. detail=True adds bbox, transform, material, user properties.
| Name | Required | Description | Default |
|---|---|---|---|
| layer | No | ||
| limit | No | ||
| detail | No | ||
| class_name | No | ||
| name_pattern | No | ||
| selected_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full load. It discloses that matching is case-insensitive and that detail=True enriches results with bbox, transform, material and user properties, which is genuinely useful. However, it never states that this is a read-only query, nor how the default limit of 100 truncates results, which matters for a scene scan returning potentially thousands of objects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence with the action front-loaded and parameter explanations following. Every clause carries information; the only flaw is the slightly telegraphic phrasing around detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and the enrichment produced by detail is well covered. But for a 6-parameter tool with zero schema descriptions and no annotations, omitting limit and selected_only leaves meaningful gaps in what the agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains name_pattern (wildcard syntax plus examples), class_name (matches classOf with examples), layer, and detail. That leaves limit and selected_only completely undocumented, meaning an agent cannot tell how truncation works or that selection filtering is even available.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource, 'Find scene objects', which tells the agent exactly what the tool returns. It does not distinguish itself from siblings like max_selection, which overlaps when selected_only is used, but the purpose itself is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the filtering semantics (name/class/layer), but there is no explicit statement of when to prefer this over max_selection or max_layers, and no exclusions or prerequisites. An agent must infer the routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_run_maxscriptA
Execute MAXScript inside Max and return the value of the last expression. (format/print output goes to Max's Listener window; return values instead.) undo=True wraps the code in an undo record.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | ||
| undo | No | ||
| timeout | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does real work: it discloses that format/print output goes to Max's Listener rather than being captured, that the last expression's value is what returns, and that undo=True wraps execution in an undo record. The only undisclosed behavior is what timeout actually does when exceeded.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action and return behavior, with the output-redirection caveat and undo semantics following. No filler; only the parenthetical phrasing is slightly awkward.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the Listener caveat is a valuable addition. However, for an arbitrary-code-execution tool with no annotations, the missing timeout semantics and the absent differentiation from max_run_python leave meaningful gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains the effect of `undo` well, but says nothing about the `timeout` parameter (units, default, behavior on expiry) and adds only indirect meaning for `code`. Two of three parameters remain underspecified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: execute MAXScript inside Max, and adds that the last expression's value is returned. It implicitly distinguishes itself from max_run_python by naming the language, but never explicitly says so.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the language ('MAXScript'), with no explicit when-to-use or when-not guidance. The most important routing decision, MAXScript here versus Python via max_run_python, is left entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_run_pythonB
Execute Python (Max's own 3.11 with pymxs) inside Max. rt (pymxs.runtime)
and pymxs are predefined. A single expression returns its value; for
multi-line code assign to result. print() output is returned too.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | ||
| undo | No | ||
| timeout | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose genuinely useful behavior: predefined `rt`/`pymxs` globals, expression-vs-`result` return semantics, and captured print output. It says nothing about side effects on the Max scene, sandboxing, or what the `undo` and `timeout` parameters actually do, which are the risk-relevant traits for arbitrary code execution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action and environment, then the return-value rules. No filler; only minor cost is the slightly cryptic backtick formatting around `rt`.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Return-value explanation is present (and an output schema exists, so that is close to redundant), and the execution environment is covered. For a tool that runs arbitrary code, the omission of undo semantics, timeout behavior, and scene-mutation implications leaves meaningful gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate for all three parameters. It handles `code` well (single expression returns value; multi-line must assign to `result`; print output returned) but never mentions `undo` or `timeout`, leaving two parameters entirely undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Execute Python ... inside Max', plus the runtime context (3.11 with pymxs). It implicitly separates itself from the sibling max_run_maxscript by naming the language, but never explicitly contrasts the two, so an agent must infer which to choose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance and no explicit alternative named, despite max_run_maxscript being an obvious sibling. Nothing tells the agent when Python is preferable to MaxScript, or what the undo/timeout defaults imply for safe use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_selectionB
List the currently selected objects (name, class, layer, position; with detail=True also bbox, transform, parent, material, user properties).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| detail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden; it does disclose that this is a non-mutating listing and that detail=True expands the returned fields (bbox, transform, parent, material, user properties). It omits behavior such as what happens when nothing is selected or whether results are capped/truncated by limit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and resource, with the detail-mode fields cleanly bracketed. The parenthetical field list is dense but every item is informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be explained, and the description covers the detail mode well. The unexplained 'limit' parameter and the absence of any differentiation from max_query_objects leave gaps for a tool in a crowded sibling set.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate: it explains 'detail' well by enumerating the extra fields, but says nothing about 'limit' (default 200), leaving the agent to guess whether it truncates results or is ignored.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List') and resource ('currently selected objects') plus the exact fields returned. It does not explicitly distinguish itself from the sibling max_query_objects, which is the main alternative for listing objects.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this versus max_query_objects (which presumably queries arbitrary objects rather than the live selection), nor any mention of prerequisites such as the selection being non-empty. Usage must be inferred from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_undoA
Undo the bridge's OWN scene changes: either the last steps undo records
or everything down to and including history entry to_history_id. Only
records labelled 'MCP: #' are undone; if a user's manual step
sits in between the call is refused and names it (the user can revert past
it from the settings window). Fails when the target has left the undo
stack or when AI undo is disabled in the settings window.
| Name | Required | Description | Default |
|---|---|---|---|
| steps | No | ||
| to_history_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses the labelling filter, the refusal-on-interleaved-manual-step behavior (including that the error names the step), the stale-target failure, and the 'AI undo disabled' failure. That is exactly the preconditions and failure-mode detail an agent needs before calling a mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then constraint, then failure modes, and no sentence is filler. The middle sentence is multi-clause and dense, but the density is carrying real semantic content rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an unannotated two-parameter mutation tool, the description covers selection semantics, filtering, refusal conditions, and failure states, and an output schema exists so return values need not be explained. Nothing essential to calling it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the prose must compensate, and it largely does: `steps` is defined as a count of most-recent undo records and `to_history_id` as an inclusive history-entry boundary, with "either ... or" implying mutual exclusivity. It does not state what happens if both are supplied or how the defaults (1 and 0) interact.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb + resource ("Undo the bridge's OWN scene changes") with an explicit scope qualifier that separates it from generic history browsing siblings like max_history. The two modes of selection (last `steps` records vs. down to `to_history_id`) are stated up front.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly frames the context: it only undoes records labelled 'MCP: <tool> #<id>' and refuses when a manual step sits in between, pointing the user to the settings window instead. The one gap is that it never tells the agent to consult max_history to discover valid `to_history_id` values.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
max_viewport_captureA
Grab the active viewport to a PNG file and return its path and size. path defaults to %TEMP%/max-mcp/capture_.png. max_size limits the longer edge (0 = keep the viewport resolution).
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| max_size | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the default output path timestamp pattern and how max_size affects resolution, plus that it returns path and size. However, it omits whether files are overwritten, permission needs for the target directory, or failure behavior when no viewport is active.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with the core action front-loaded and zero filler. The default path and size semantics follow logically. Slightly more structure (e.g., explicit param labeling) could help but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return value explanation isn't required, and both optional parameters are documented with defaults. For a simple, side-effect-light capture tool this is nearly complete; only edge-case behavior (no active viewport, unwritable path) is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does: it explains path's default (%TEMP%/max-mcp/capture_<timestamp>.png) and that max_size limits the longer edge with 0 meaning keep viewport resolution. Both undocumented parameters gain meaningful semantics beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Grab the active viewport to a PNG file'. The resource (viewport capture) is inherently distinct from all listed siblings, which are query/script/inspection tools. It doesn't explicitly name a sibling to differentiate, which keeps it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage (capture the current viewport for visual inspection) but never states when to use this versus siblings like max_info or max_query_objects. There are no exclusions or alternatives named, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.2.0- First observed
max_history - First observed
max_info - First observed
max_layers - First observed
max_query_objects - First observed
max_run_maxscript - First observed
max_run_python - First observed
max_selection - First observed
max_set_layer_hidden - First observed
max_undo - First observed
max_viewport_capture
TDQS
Scored across 10 tools
Each tool targets a distinct resource or action: scene info, layers, selection, object querying, layer visibility, viewport capture, MAXScript execution, Python execution, history, and undo. The two execution tools are clearly separated by language, and query vs. selection tools are distinguished by scene-wide filtering vs. current selection. No pair appears to do the same thing.
All names share the max_ prefix and use snake_case, which makes the set predictable. However, some tools are noun-based (max_layers, max_info, max_selection, max_history) while others are verb-based (max_query_objects, max_set_layer_hidden, max_run_maxscript), so the pattern is not fully uniform.
Ten tools is a well-scoped set for a 3ds Max bridge: it covers introspection, selection/query, layer visibility, viewport capture, scripting escape hatches, history, and undo. Each tool has a clear role, and the count avoids both thinness and bloat.
The surface covers core bridge operations well, including scene introspection, object discovery, viewport capture, arbitrary MAXScript/Python execution, command history, and undo. Dedicated tools for common lifecycle actions such as scene save/open, render/export, or direct object creation/transformation are absent, though the scripting tools provide workarounds.
Maintenance
Related MCP Connectors
Control Unreal Engine to browse assets, import content, and manage levels and sequences. Automate…
Build editable 3D scenes, direct characters and cameras, and export AI video references with MCP.
Read and edit the Revit 2024–2027 model on your PC. Needs the free Revit MCP add-in.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables AI assistants to directly control Autodesk 3ds Max through natural language to create models, set materials, adjust lighting, and automate animations. It bridges the Model Context Protocol with 3ds Max via a TCP socket to execute Python and MAXScript commands.2418MIT
- AlicenseNot gradedqualityAmaintenanceConnect AI agents to Autodesk 3ds Max through the Model Context Protocol, enabling natural language control of scene creation, materials, modifiers, rendering, and plugin workflows.253 PyPI348MIT
- AlicenseNot gradedqualityDmaintenanceA local MCP server that enables MCP-compatible AI clients to inspect and control the currently open scene in a running Autodesk VRED Professional 2027 instance via a secure bridge, supporting read-only inspection and gated mutations like selection, visibility, transforms, and screenshots.MIT
- FlicenseBqualityBmaintenanceEnables AI agents to control a live 3ds Max session directly, including creating and editing objects, materials, animation, and scene inspection, with undo support.17-