Skip to content

FAQ

Frequently asked questions about DCC-MCP-Core.

General

What is DCC-MCP-Core?

DCC-MCP-Core is a foundational Rust library with Python bindings that provides:

  • ToolRegistry — Thread-safe tool registration and lookup
  • SkillCatalog — Progressive skill discovery and loading; scripts auto-registered as MCP tools via SKILL.md
  • EventBus — A publish-subscribe event system for DCC lifecycle hooks
  • MCP Protocol Types — Type definitions for the Model Context Protocol (Tools, Resources, Prompts)
  • Transport Layer — IPC and network communication for distributed DCC integration
  • MCP HTTP Server — A streamable HTTP server exposing DCC tools to AI clients

What DCC applications are supported?

dcc-mcp-core is DCC-agnostic — the core library provides the infrastructure. DCC-specific integrations are separate projects:

  • Maya — via dcc-mcp-maya
  • Unreal Engine — via dcc-mcp-unreal (in development, Python embedded)
  • Photoshop — via dcc-mcp-photoshop (in development, WebSocket bridge)
  • ZBrush — via dcc-mcp-zbrush (in development, HTTP bridge)
  • Blender, Houdini, 3ds Max — community/third-party integrations using this library

The core library works with any Python 3.7+ environment.

What Python versions are supported?

Python 3.7–3.13 are tested in CI. Wheels are built with abi3-py38 for maximum compatibility.

Does it have any Python runtime dependencies?

No. The library has zero Python runtime dependencies. Everything is compiled into the Rust core.

Installation

How do I install dcc-mcp-core?

From PyPI:

bash
pip install dcc-mcp-core

From source (requires Rust 1.85+ and maturin):

bash
git clone https://github.com/loonghao/dcc-mcp-core.git
cd dcc-mcp-core
pip install maturin
maturin develop

Tools

How do I register a tool?

python
from dcc_mcp_core import ToolRegistry, ToolDispatcher
import json

reg = ToolRegistry()

# Register tool metadata with an optional JSON Schema
reg.register(
    name="create_sphere",
    description="Create a polygon sphere",
    category="geometry",
    tags=["create", "mesh"],
    dcc="maya",
    version="1.0.0",
    input_schema=json.dumps({
        "type": "object",
        "required": ["radius"],
        "properties": {"radius": {"type": "number", "minimum": 0.0}},
    }),
)

# Attach a Python handler
dispatcher = ToolDispatcher(reg)
dispatcher.register_handler("create_sphere", lambda params: {"name": "sphere1"})
result = dispatcher.dispatch("create_sphere", '{"radius": 1.0}')
print(result["output"])  # {"name": "sphere1"}

How do I return structured results from a tool?

python
from dcc_mcp_core import success_result, error_result, from_exception

# Success
result = success_result("Sphere created", context={"name": "sphere1"})
print(result.success)   # True
print(result.context)   # {"name": "sphere1"}

# Error
result = error_result("Failed to create sphere", error="No active scene")
print(result.success)   # False

# From exception
try:
    raise ValueError("radius must be > 0")
except Exception:
    result = from_exception("Invalid radius")

How do I validate tool input?

python
from dcc_mcp_core import ToolValidator

validator = ToolValidator.from_schema_json('{"type":"object","required":["radius"],"properties":{"radius":{"type":"number"}}}')
ok, errors = validator.validate('{"radius": 1.0}')
assert ok

ok, errors = validator.validate('{}')
assert not ok
print(errors)  # ['missing required field: radius']

Events

How does the event system work?

python
from dcc_mcp_core import EventBus

bus = EventBus()

# Subscribe — returns a subscription ID
def on_save(file_path: str):
    print(f"Saving to: {file_path}")

sub_id = bus.subscribe("dcc.save", on_save)

# Publish
bus.publish("dcc.save", file_path="/tmp/scene.usd")

# Unsubscribe
bus.unsubscribe("dcc.save", sub_id)

Async handlers

The EventBus does not natively support async def callbacks. Wrap async logic in a synchronous handler that schedules it with your event loop.

Skills

What is the quickest way to expose scripts as MCP tools?

Use create_skill_server (v0.12.12+) — one call does everything:

python
import os
from dcc_mcp_core import create_skill_server, McpHttpConfig

os.environ["DCC_MCP_MAYA_SKILL_PATHS"] = "/path/to/skills"
server = create_skill_server("maya", McpHttpConfig(port=8765))
handle = server.start()
print(handle.mcp_url())  # http://127.0.0.1:8765/mcp

This automatically creates an ToolRegistry, ToolDispatcher, SkillCatalog, and McpHttpServer, and discovers skills from DCC_MCP_MAYA_SKILL_PATHS and DCC_MCP_SKILL_PATHS.

What is the Skills system?

The Skills system allows zero-code script registration. Place scripts in a directory with a SKILL.md file and they are automatically discovered and registered as MCP tools:

markdown
---
name: maya-geometry
description: "Geometry creation tools"
version: "1.0.0"
dcc: maya
tags: ["geometry"]
tools:
  - name: create_sphere
    description: "Create a sphere"
    source_file: scripts/create_sphere.py
---

How do I discover and load skills?

python
from dcc_mcp_core import SkillScanner, SkillCatalog
import os

os.environ["DCC_MCP_SKILL_PATHS"] = "/path/to/skills"

scanner = SkillScanner()
catalog = SkillCatalog(scanner)

# Discover skills
catalog.discover(dcc_name="maya")

# Load a skill
ok = catalog.load_skill("maya-geometry")
print(ok)  # True

What's the tool naming convention for skill tools?

Tools from skills are named {skill_name_underscored}__{tool_name}, e.g.:

  • skill maya-geometry, tool create_sphere → tool maya_geometry__create_sphere

How do I scan for skills without loading them?

python
from dcc_mcp_core import scan_and_load_lenient

skills, skipped = scan_and_load_lenient(extra_paths=["/my/skills"])
for skill in skills:
    print(f"{skill.name} ({len(skill.tools)} tools)")

Transport Layer

What transport options are available?

  • TCP — Network communication (TransportAddress.tcp(host, port))
  • Named Pipes — Low-latency local communication on Windows (TransportAddress.named_pipe(name))
  • Unix Domain Sockets — Low-latency local communication on Linux/macOS (TransportAddress.unix_socket(path))

Use TransportAddress.default_local(dcc_type, pid) to automatically select the best IPC transport for the current platform.

How do I register a DCC service and connect to it?

DCC-side (server):

python
from dcc_mcp_core import IpcChannelAdapter, DccLinkFrame

# Server: create named IPC endpoint and wait for client
server = IpcChannelAdapter.create("maya-2025")
server.wait_for_client()

Agent-side (client):

python
from dcc_mcp_core import IpcChannelAdapter, DccLinkFrame

# Client: connect to the DCC's IPC endpoint
client = IpcChannelAdapter.connect("maya-2025")
request = DccLinkFrame(msg_type=1, seq=0, body=b'{"method":"ping"}')
client.send_frame(request)
reply = client.recv_frame()

MCP HTTP Server

How do I expose DCC tools via HTTP for AI clients?

python
from dcc_mcp_core import ToolRegistry, McpHttpServer, McpHttpConfig

registry = ToolRegistry()
registry.register("get_scene_info", description="Get scene info", category="scene", dcc="maya")

server = McpHttpServer(registry, McpHttpConfig(port=8765))
handle = server.start()
print(handle.mcp_url())  # http://127.0.0.1:8765/mcp
# Connect your AI client to this URL
handle.shutdown()

Gateway

How do I run multiple DCC instances with a single endpoint?

Use the Gateway feature. Set gateway_port on McpHttpConfig to a well-known port (default: 9765). The first process to bind that port becomes the gateway; all others register as plain DCC instances:

python
from dcc_mcp_core import ToolRegistry, McpHttpServer, McpHttpConfig

registry = ToolRegistry()
config = McpHttpConfig(port=0, server_name="maya-mcp")
config.gateway_port = 9765
config.dcc_type = "maya"

server = McpHttpServer(registry, config)
handle = server.start()
print(handle.is_gateway)  # True if this process won the gateway port

Agents always connect to http://localhost:9765/mcp and use list_dcc_instances / connect_to_dcc to discover and route to specific DCC processes.

What is BridgeKind?

BridgeKind describes how a DCC communicates when it does not have an embedded Python interpreter:

  • Http — HTTP REST bridge (e.g. ZBrush)
  • WebSocket — WebSocket JSON-RPC bridge (e.g. Photoshop UXP)
  • NamedPipe — Named pipe bridge (e.g. 3ds Max COM)

Set DccCapabilities(bridge_kind="http", bridge_endpoint="http://localhost:1234", has_embedded_python=False) for bridge-based DCCs.

On-Demand Skill Discovery

How does on-demand skill discovery work?

When create_skill_server() starts, it only discovers skills (reads SKILL.md files) — it does not load them. The tools/list response shows:

  1. 6 core discovery tools (always present)
  2. Loaded skill tools with full schemas
  3. Unloaded skill stubs as __skill__<name> (name + one-line description only)

Agents use search_skills(query="keyword") to find relevant skills, then load_skill(skill_name="...") to activate them. This keeps the initial tool list small and loads schemas only when needed.

Troubleshooting

My tool registration is not working. What should I check?

  1. Make sure the ToolRegistry instance used for registration is the same one used for lookup
  2. Call reg.list_actions() to verify the tool was registered
  3. Use reg.get_action("my_action") to check the stored metadata
  4. If using ToolDispatcher, verify dispatcher.handler_count() > 0

How do I enable debug logging?

Set the DCC_MCP_LOG environment variable before importing:

bash
export DCC_MCP_LOG=debug

Or configure via TelemetryConfig:

python
from dcc_mcp_core import TelemetryConfig

cfg = TelemetryConfig("my-service").with_stdout_exporter()
cfg.init()

How do I report a bug or request a feature?

Please open an issue on GitHub with:

  • DCC application and version
  • Python version (python --version)
  • dcc-mcp-core version (python -c "import dcc_mcp_core; print(dcc_mcp_core.__version__)")
  • Minimal reproduction code
  • Expected vs actual behavior

Contributing

How do I contribute to the project?

See the CONTRIBUTING.md guide. Key steps:

  1. Install Rust 1.85+ and Python 3.8+
  2. Clone the repository
  3. Run vx just dev to build and install in dev mode
  4. Run vx just test to run the test suite

Is there a community chat?

Join the discussion on GitHub Discussions.

Released under the MIT License.