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:
pip install dcc-mcp-coreFrom source (requires Rust 1.85+ and maturin):
git clone https://github.com/loonghao/dcc-mcp-core.git
cd dcc-mcp-core
pip install maturin
maturin developTools
How do I register a tool?
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?
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?
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?
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:
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/mcpThis 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:
---
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?
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) # TrueWhat's the tool naming convention for skill tools?
Tools from skills are named {skill_name_underscored}__{tool_name}, e.g.:
- skill
maya-geometry, toolcreate_sphere→ toolmaya_geometry__create_sphere
How do I scan for skills without loading them?
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):
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):
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?
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:
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 portAgents 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:
- 6 core discovery tools (always present)
- Loaded skill tools with full schemas
- 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?
- Make sure the
ToolRegistryinstance used for registration is the same one used for lookup - Call
reg.list_actions()to verify the tool was registered - Use
reg.get_action("my_action")to check the stored metadata - If using
ToolDispatcher, verifydispatcher.handler_count()> 0
How do I enable debug logging?
Set the DCC_MCP_LOG environment variable before importing:
export DCC_MCP_LOG=debugOr configure via TelemetryConfig:
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:
- Install Rust 1.85+ and Python 3.8+
- Clone the repository
- Run
vx just devto build and install in dev mode - Run
vx just testto run the test suite
Is there a community chat?
Join the discussion on GitHub Discussions.