mcp-for-maya

io.github.Xxx91n由 GitHub 帳號 Xxx91n 發布v0.7.0更新於 Oct 30, 2026

AI agents' spatial awareness inside Autodesk Maya: audit, rollback safety, visual loop (Beta)

已驗證STDIO僅桌面開發者工具媒體與設計

概覽

AI 產生的概覽

讓 AI 代理透過本機命令埠檢查、規劃、建模並審查 Autodesk Maya 3D 場景的 MCP 伺服器。

可以做什麼
  • 讀取與量測場景:整場景空間快照、物件檢查、間距與重疊量測、節點與場景圖檢視
  • 規劃與審查:場景規劃、11 項確定性檢查並給出 0-100 評分、自訂規則驗證與狀態斷言
  • 建構與修改:在 Maya 中執行任意 Python、注入可重用模組,以及建立攝影機與環繞動畫
  • 保護成果:記憶體檢查點、回復與檢查點清單
  • 截圖與匯出:GUI 工作階段下的視埠截圖與單格算圖預覽,以及 FBX/OBJ/USD 匯出
  • 取得資產與管理連線:Poly Haven 模型搜尋與匯入,以及 Maya 工作階段探索與安裝引導
適用情境
適合希望助理在執行中的 Maya 工作階段裡完成 3D 建模、場景配置、攝影機設定或品質審查,並依空間與工程檢查驗證自身變更、而非盲目修改的情況。
執行需求
本機 Python 套件(需 Python 3.10 以上),以 uvx 或 pip 執行,支援 Windows、Linux、macOS。需要 Autodesk Maya 2023 或更新版本並開啟 Python 命令埠(例如 7001),可手動設定或透過安裝引導。視覺截圖工具需要 GUI 版 Maya 工作階段。另有選用環境變數可調整埠掃描與策略模式。
安裝前請注意
此伺服器依設計會在 Maya 內執行任意 Python;其驗證、限流與稽核流程被描述為安全網,而非對惡意用戶端的邊界,因此連線的代理被視為可信任。選用旗標可停用程式碼執行工具或啟用 AST 白名單。資產工具在呼叫時會向 Poly Haven 發出 HTTPS 請求。場景匯出僅在明確允許時才會覆寫既有檔案。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 mcp-for-maya,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

English | 简体中文

[mcp-for-maya — Give AI agents eyes inside Autodesk Maya]

mcp-for-maya

MCP server giving AI agents spatial awareness of Autodesk Maya scenes

[CI] [PyPI] [License: MIT] [Python]

What this is

mcp-for-maya is a Model Context Protocol (MCP) server that lets LLM agents (Codex, Claude, etc.) drive Autodesk Maya for 3D modeling, scene planning, and engineering-grade delivery.

Forked from chadrik/maya-mcp-server. The fork keeps the upstream connection stack and adds a scene-intelligence layer: spatial awareness, deterministic auditing, transactional safety, and a visual loop. The agent stops writing blind — it reads spatial state, materials, and object relationships, then verifies changes against engineering rules.

[!WARNING] This server executes arbitrary Python inside Maya — a designed capability, not a bug. The validation / rate-limit / audit pipeline is a safety net for accidents and injected instructions, not a boundary against a malicious client; the connected agent is trusted. See docs/threat-model.md.

[Live Demo — captured by the product itself]

Every asset below is a real capture produced by this project's own tool chain — no mockups: scenes were built procedurally through execute_code / write_module (plus one live asset_import), frames rendered through scene_render_preview, the audit pair via scene_review + scene_viewport_snapshot, and the orbit sequence captured frame-by-frame with playblast (Maya 2024 GUI session).

PromptResult
write_module → t20_movement.build() — "parametric involute gear train caliber: true involute teeth, Geneva-striped plates, blue-steel screws, ruby jewels, spiral hairspring"[parametric watch movement: involute gears, Geneva striping, balance + hairspring]
write_module → t20_bonsai.build() — "low-poly L-system bonsai: recursive branching, faceted foliage pads, pot + moss + stones"[low-poly L-system bonsai: recursive branching, foliage pads, pot + moss + stones]
asset_import("vintage_pocket_watch") + asset_import("metal_tool_chest") → t20_workbench.build() — "horologist's workbench: imported assets with textures wired, procedural involute spares"[horologist workbench: imported pocket watch + tool chest, procedural gear spares]
write_module → t20_street.build() — "low-poly corner block: 11 parametric buildings, gable roofs, awnings, street furniture, parked vans"[low-poly street block: 11 parametric buildings, awnings, street furniture]
write_module → t20_teapot.build() — "Utah teapot recreation: revolve-profile body, Bezier tapered spout, ear handle, checkered floor"[Utah teapot recreation: lathe body, bezier tapered spout, checkered floor]
scene_review() on a bench littered with junk → scene_plan(auto_fix=True) + cleanup → scene_review() again — score 53.7 → 64.2[scene_review before: default-named junk piled on the metrology bench][scene_review after: violations removed, bench restored]

[movement orbit — 20 real playblast frames, 120° sweep]

Reproduce every frame with the scripts in .github/assets-src/.

vs blender-mcp

Three-tier comparison with ahujasid/mcp-for-blender (measured 2026-09):

TierContents
Unique to this projectICEV enforced workflow (in server instructions), CoS notation output, checkpoint/rollback transactional safety, scene_plan holistic planning (zone mapping + layout suggestions), multi-session management, 11 deterministic audit checks, playblast render preview with metadata
Unique to blender-mcpAsset ecosystem breadth (Sketchfab/Hyper3D/Hunyuan3D), first-class object CRUD tools, AI-generated-model integrations, community scale
SharedMCP tool surface, Poly Haven asset source, viewport screenshot feedback, arbitrary Python execution, local socket connection

Poly Haven model search + import shipped in 0.2.0 (issue #2 thin slice: FBX + texture wiring; HDRIs and texture packs remain roadmap). AI generation and first-class object CRUD are out of scope — the latter is already covered by execute_code.

On the shared asset-download path, this project's controls are enforced in code: downloads happen host-side only — https + host allowlist, per-file md5, size caps, filenames sanitized from the URL's last segment (polyhaven.py) — and Maya itself never touches the network. Enforcement detail: docs/threat-model.md.

[Capability Matrix]
CapabilityToolsNotes
🧊 Spatial awarenessscene_snapshot scene_inspect scene_measureOne-call full-scene spatial model; precise distance/overlap/gap measurement
🎨 Aesthetic analysisscene_aesthetics5 dimensions: color theory (60-30-10), spatial composition (golden ratio / rule of thirds), proportion & scale (ergonomics), lighting quality (three-point / fill ratio / temperature / decay), visual flow
🎬 Camera planningcamera_create camera_orbit8 industry-standard shot types + orbit animation
🛡️ Disaster recoveryscene_checkpoint scene_rollback scene_checkpoint_listexportAll in-memory snapshots; rollback explicitly rebinds the original path
🧠 Scene planningscene_planOrganization health, zone balance, layout suggestions, conflict prevention, natural-language planning
📋 Engineering auditscene_review scene_validate scene_assert11 deterministic checks (0-100 score) + custom constraint validation + state assertions
⚡ Code executionexecute_code write_moduleRun arbitrary Python in Maya / inject reusable modules
👁️ Visual loopscene_viewport_snapshot scene_render_previewWYSIWYG viewport capture + single-frame playblast preview (GUI sessions only)
🔌 Session managementlist_sessions add_session maya_setup_guideMulti-session discovery/attach + connection diagnosis/install/fallback guidance
📦 Asset libraryasset_search asset_importPoly Haven CC0 models — host-side HTTPS download (host allowlist, md5 verify, size caps, platformdirs cache), Maya-side FBX import with texture wiring, polycount/dims guards, GRP_asset_<id> dedup
📤 Scene exportscene_exportFBX/OBJ/USD export — whole scene or named objects; format inferred from extension (conflict is an error, never a guess), parent dirs auto-created, overwrite opt-in, selection restored
🔎 Scene-graph introspectionscene_describe scene_nodesAPI-level node self-description (exact type, per-attribute metadata: keyable/connectable/enum/ranges, connection wiring — size-bounded, *_truncated disclosure, limit up to 1000) + bounded enumeration incl. non-DAG nodes (materials/tool nodes) with has_more/next_cursor pagination

25 MCP tools in total.

[Quick Start]

1. Install

bash
# Install from PyPI (recommended)pip install mcp-for-maya
# or run straight away with uvxuvx mcp-for-maya
# alternative: install from git with uvuv tool install git+https://github.com/Xxx91n/mcp-for-maya.git
# or clone the sourcegit clone https://github.com/Xxx91n/mcp-for-maya.gitcd mcp-for-mayapip install -e .

[!NOTE] Three-layer naming: dist name mcp-for-maya (PyPI shelf name) → installs import package maya_mcp_server (kept from upstream); script name mcp-for-maya (old name maya-mcp-server remains as a compat alias). uvx mcp-for-maya resolves precisely because the command name matches the dist name.

2. Connect Maya

Option A: automatic (recommended)

With the MCP server running, the agent calls maya_setup_guide to walk the connection:

  1. Make sure Maya is running
  2. Give the agent any instruction (e.g. "look at my Maya scene")
  3. If unconnected, the agent runs diagnostics and can install userSetup.py (idempotent marker-block merge, timestamped backup before writing)
  4. After restarting Maya, the command port opens automatically
Option B: manual

In Maya's Script Editor (Python mode, not MEL):

python
import maya.cmds as cmds
cmds.commandPort(name=":7001", sourceType="python")
Option C: persistent auto-connect

Save this as userSetup.py in your Maya scripts directory:

PlatformPath
Windows%MAYA_APP_DIR%\<version>\scripts\
Linux~/maya/<version>/scripts/
macOS~/Library/Preferences/Autodesk/maya/<version>/scripts/
python
import maya.cmds as cmds
cmds.evalDeferred('cmds.commandPort(name=":7001", sourceType="python")', lowestPriority=True)
Multiple Maya instances

A commandPort is a single listening socket bound to one host:port — a second instance fails to bind the same port, so each Maya instance needs its own port. Typical topology:

Maya instancecommandPortNotes
Instance A:7001 pythonprimary
Instance B:7002 pythonsecond instance
Instance A:7011 melMEL port (auto-detected and exempted — no error spam)

Run cmds.commandPort(name=":<port>", sourceType="python") inside each instance (its Script Editor or its own userSetup.py). Auto-scan is the primary path — the server periodically enumerates listening Maya ports and bootstraps them; if a session is missed, add_session(host, port) is the manual fallback. If scanning probes a non-Maya TCP service on the box, bound the probe set with MAYA_MCP_INCLUDE_PORTS=7001,7002 (comma-separated, 7005-7010 ranges allowed) or exclude offenders via MAYA_MCP_EXCLUDE_PORTS=<port>.

Note: a commandPort does not persist across sessions — it dies with Maya; for persistence write it into userSetup.py (Option C).

Troubleshooting
ProblemFix
list_sessions returns emptycall maya_setup_guide(action="diagnose")
Port in useclose other Maya instances or pick another port
userSetup.py not loadingcheck it sits in the right scripts dir, restart Maya
Firewall blocksensure localhost:7001 is reachable
Second Maya instance not listedeach instance needs its own commandPort (same port = bind conflict); if scanning still misses it, call add_session(host, port)
Script Editor spams syntax errorslegacy symptom of probing a MEL port — current versions auto-exempt non-Python ports; if it persists, exclude the port via MAYA_MCP_EXCLUDE_PORTS

3. Configure the MCP client

Codex ~/.codex/config.toml:

toml
[mcp_servers.maya]command = "uvx"args = ["mcp-for-maya"]tool_timeout_sec = 120

For the git source use args = ["--from", "git+https://github.com/Xxx91n/mcp-for-maya.git", "mcp-for-maya"]; for a source checkout use command = "python", args = ["-m", "maya_mcp_server"], and point PYTHONPATH at <repo>/src under env.

4. Use it

Talk naturally:

"Look at what's in my Maya scene, then create a display shelf at the entrance"

The agent calls scene_snapshot() → understands the scene → models → scene_review() audits the result.

[ICEV Workflow]

Every scene modification follows the ICEV loop (also shipped as an agent process card, see skills/icev-workflow):

┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐│ INSPECT  │ ──→ │ COMPUTE  │ ──→ │ EXECUTE  │ ──→ │ VERIFY   ││ snapshot │     │  plan    │     │  apply   │     │  audit   │└──────────┘     └──────────┘     └──────────┘     └──────────┘
  1. INSPECT: scene_snapshot() for full-scene spatial data
  2. COMPUTE: plan positions, sizes, clearances from that data
  3. EXECUTE: execute_code() applies Maya Python
  4. VERIFY: scene_assert() + scene_review() confirm the result; on GUI sessions the visual tools give pixel-level confirmation

Tools reference

Spatial

python
scene_snapshot(detail="compact", format="cos")  # full scene in one callscene_inspect(target="wall_entrance", include_neighbors=True)scene_measure(obj_a="wall_north", obj_b="counter_A", mode="clearance")scene_assert(expectations='{"wall": {"exists": true, "position": [0,0,500]}}')

Audit

python
scene_review()  # 11 deterministic checks, 0-100 scorescene_validate(rules='[{"type": "min_clearance", "value": 180}]')

Cameras

python
camera_create(target="product_display", shot_type="medium", azimuth=30, elevation=15)# extreme_wide / wide / medium / close / extreme_close / bird_eye / low_angle / over_shouldercamera_orbit(center=[0, 100, 0], radius=500, frames=120)

Disaster recovery

python
scene_checkpoint(name="before_renovation")  # exportAll in-memory snapshot; no undo historyscene_checkpoint_list()scene_rollback(filename="cp_before_renovation.ma")# auto safety snapshot first, then rebinds the scene name to the original path# call scene_snapshot() after a rollback — snapshots carry no undo history# self-contained: references are flattened (no write-back); one scene file per session assumed

Assets (Poly Haven, host-side download)

python
asset_search(query="camera", asset_type="models", limit=20)  # Poly Haven indexasset_import(asset_id="Camera_01", resolution="1k")# HTTPS-only download into a platformdirs cache (per-file md5 verify + sha256 audit),# then Maya imports the local FBX under GRP_asset_<asset_id> (repeat calls dedup;# force=True re-imports). Textures auto-wire by filename suffix# (diff/rough/metal/nor_gl/ao/disp...) with sRGB/Raw color spaces and bump2d normals.# Single-part assets ship bare map names (Diffuse/Rough/Metal...) — those are# recognised too and wired onto the asset's single material.# Guards: 100k-face polycount cap (allow_high_polycount override), dims sanity report.

Scene export

python
scene_export(path="D:/out/scene.fbx")  # whole scene; format inferred from .fbxscene_export(path="/tmp/kit", format="obj")  # missing extension is appended -> kit.objscene_export(path="D:/out/kit.usd", objects=["GEO_box"])  # exportSelected; prior selection restored# format {fbx,obj,usd}: an extension/format conflict is an error, never a guess.# An existing file is rejected unless overwrite=True. prompt=False is forced# (no modal can hang the channel); the scene's modified flag is untouched.# Alembic is not supported — AbcExport is not a cmds.file surface.

Visual loop (GUI sessions only)

python
scene_viewport_snapshot(    max_size=800, format="jpeg")  # HUD/selection included — what the artist seesscene_render_preview(camera="CAM_hero", width=640, height=360)  # clean single-frame playblast# both return [image, JSON metadata]; headless sessions get a gui_session_required error# prefer format="png" for wireframe/line-art review; trust returned metadata for actual size

CoS notation

Default output uses Chain-of-Symbol notation to compress scene data. The format's paper reports ~65% token savings vs JSON on its demo scenes (arXiv:2305.10276, −65.8%) — this project implements the notation; that figure is the paper's measurement, not a benchmark of this project.

SCENE[164obj, 5zones] UNIT=cm UP=yshell (23obj) @(-11.8,178.8,145.7)  GRP_floor[mesh]@(0,0,0) 1121.5x20x1530.5

Agent skills

Two Experimental process cards ship in skills/:

SkillPurpose
skills/icev-workflowICEV discipline: every scene mutation goes through Inspect→Compute→Execute→Verify
skills/scene-review-playbookAudit playbook: what the 11 checks weigh and how to map findings to fixes

Evaluated on Claude Code only; untested on Codex/Gemini CLI/Cursor. Cross-model evaluation is tracked in issue #3.

[Audit & Trust]

scene_review() provides 11 universal checks (score normalized to 0-100):

CheckMax ptsWhat it looks at
spatial10object/camera/light presence
overlaps10bbox collisions (parent-child excluded)
conflicts10penetration between unrelated objects
zones5naming-rule zone coverage
naming5production naming convention
components10GRP_ grouping + nesting depth ≤ 4
orphans5empty groups / default names
aesthetics155-dimension aesthetics (color/composition/scale/lighting/flow)
lighting10three-point setup, fill ratio, decay
organization10overall hierarchy health
constraints5custom rule violations

Trust & privacy

  • Zero telemetry: no phone-home — the project ships no telemetry or unsolicited outbound traffic; verify in source. The ONLY outbound calls are the two asset tools: HTTPS to api.polyhaven.com / dl.polyhaven.org|.com (host allowlist + md5 + size caps in polyhaven.py), and only when you call them.
  • Local, single-user: the command port binds localhost only; the connected MCP client is trusted.
  • Safety net: a unified pipeline (pipeline.py + security.py) validates arguments + token-bucket rate limits (~100/60s reads, ~20/60s writes, per session) + pattern scan (warn-only by default) + an independent JSONL audit log across all 25 tools. It catches accidents, not malicious clients — full model in docs/threat-model.md.
  • Transactional safety: scene_checkpoint/scene_rollback give in-memory snapshots and explicit rollback (no undo history; references flattened).
  • Strict policy mode (optional): set MAYA_MCP_DISABLE_EXECUTE=1, MAYA_MCP_DISABLE_WRITE_MODULE=1, or MAYA_MCP_DISABLE_ARBITRARY=1 (all three) to remove the escape-hatch tools from tools/list and deny the call with [policy_disabled]. Read-only tools are unaffected. These are misuse guardrails, not a hostile-agent boundary — an agent that still holds execute_code is already inside the trust boundary; what they buy is a smaller blast radius for a demo, a mistake, or a CI sandbox. Rationale: docs/threat-model.md. Per-code reference: docs/guide/error-codes.md.
  • safe_mode AST gate (optional): set MAYA_MCP_SAFE_MODE=1 (default off) and the two code-bearing tools stay listed but their code payloads pass a deny-by-default AST allowlist: v1 import roots (maya/math/json/re/collections/itertools/functools/dataclasses/typing), no denied builtin names — every reference rejects, not just calls (eval/exec/open/__import__/getattr/setattr/…), no __builtins__, no dunder attribute access, and unparseable input rejects ("cannot decide ⇒ deny"). Rejections raise [safe_mode_rejected] (a host isError failure) naming the rule id and are audited rejected; successful responses carry mode: "safe" and the tool descriptions gain one Boundary: line. DISABLE flags still remove tools first — safe_mode only narrows what remains. Same posture as the DISABLE flags: a safety net, not a boundary. Rationale: docs/threat-model.md. Per-code reference: docs/guide/error-codes.md.
  • Vulnerability reporting: SECURITY.md.

Versioning

This project follows Semantic Versioning:

  • 0.x (through 0.3.x, Alpha): the tool surface could still change; minor bumps carried features, no compatibility freeze.
  • Beta (0.4.0 onward; current release 0.7.0): feature-complete tier — external testing begins here (classifier 4 - Beta).
  • 1.0.0: public API freeze — tool surface and output schemas stable per semver; breaking changes require 2.0.0. Promoted together with the 5 - Production/Stable classifier in one commit; gated by the #7 real-machine checklist.

The public API is the MCP tool surface: tool names, their input/output shapes, the two-layer error contract (host isError failures vs {error:{code,message,suggestion}} domain results), and tool-annotation semantics (docs/threat-model.md §5). Additive changes (new tools, new optional response fields) ship as minor releases; breaking changes ship as a major bump. 1.0.0 freezes this surface — it is not a quality certification; the remaining real-machine verification surface is tracked explicitly in #7.

Releases are milestone-driven — no fixed cadence. Roadmap lives in GitHub issues: #2 Poly Haven integration (model slice shipped in 0.2.0; scene_plan recommendation residual split to #31), #3 Skills program (v1.x), #4 security & permission model (v1.x), #5 scene export + introspection (both shipped in 0.3.0), #6 more asset sources (exploratory), #7 real-machine checklist + v1.0 feedback (pinned).

Requirements

EnvironmentRequirement
Host (runs the MCP server)Python >= 3.10 (requires-python); Windows / Linux / macOS
Injected helper (runs inside Maya)Maya >= 2023 (bundled Python >= 3.9; relies on ast.unparse — older versions get an explicit refusal at injection)
Verified againstMaya 2024 GUI

The two visual-loop tools need a GUI session (headless/mayapy returns a structured capability error). On the first capture the server probes the VP2 readback direction per-session (a disposable scene probe, net-zero side effects); MAYA_MCP_VP2_BOTTOM_UP=0|1 forces it when a driver misreports.

Development

bash
uv sync --frozen                  # locked dev env from uv.lock (alt: pip install -e . --group dev, pip>=25.1)python -m pytest tests/ -q       # testsruff check src tests             # lintmypy src                         # typecheckpython -m maya_mcp_server -vv    # run with DEBUG logs (-v=INFO, -vv=DEBUG)

See CONTRIBUTING.md for the PR flow and CHANGELOG.md for the change log.

Credits

Forked from chadrik/maya-mcp-server — upstream MIT copyright retained (see LICENSE); this project adds the scene-intelligence layer on top of its connection stack.

How each upstream open issue maps to a disposition and release version in this fork: docs/upstream-issue-status.md.

來源:README.md,提交 f5a3858

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

3
  1. v0.7.0最新Oct 29, 2026
  2. v0.6.0Oct 26, 2026
  3. v0.5.0Sep 30, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分