Custom Skills
Learn how to build custom Skills for DCC applications — from the recommended Skills-First approach to the low-level registry API.
Recommended: Skills-First Approach
The Skills-First approach discovers SKILL.md packages via environment variables and is the recommended way to build DCC tools:
- Zero boilerplate — no manual handler registration, tools are auto-discovered
- Auto-exposed as MCP tools — the skill manager exposes each tool to AI via the MCP protocol
- Hot-reload — changes to
SKILL.mdtake effect without restart
Step 1: Create a SKILL.md Package
markdown
---
name: maya-geometry
description: Maya geometry creation tools
version: 1.0.0
dcc: maya
tags: [geometry, create]
tools:
- name: create_sphere
description: Create a polygon sphere
input_schema: |
{
"type": "object",
"required": ["radius"],
"properties": {
"radius": {"type": "number", "minimum": 0.1},
"name": {"type": "string"}
}
}
scripts:
- create_sphere.py
---
# Maya Geometry Tools
A toolset for creating and editing geometry in Maya.Step 2: Implement the Script
create_sphere.py:
python
import maya.cmds as cmds
from dcc_mcp_core import success_result, error_result
def create_sphere(radius: float = 1.0, name: str | None = None):
try:
sphere = cmds.polySphere(r=radius, n=name)[0]
return success_result(
message=f"Created sphere: {sphere}",
context={"object_name": sphere, "radius": radius}
)
except Exception as e:
return error_result(str(e))Step 3: Register via Environment Variable and Start
python
import os
from dcc_mcp_core import create_skill_server
os.environ["DCC_MCP_MAYA_SKILL_PATHS"] = "/path/to/my/skills"
# One line: auto-discovers skills, starts MCP HTTP server
server = create_skill_server("maya", McpHttpConfig(port=8765))Skills-First is the recommended pattern
All new DCC tools should use SKILL.md packages first. Only fall back to the registry API when you need runtime dynamic control over handler logic.
Low-Level Registry API
When you need programmatic control over handler registration at runtime, use the ToolRegistry + ToolDispatcher API.
Full Example
python
import json
from dcc_mcp_core import ToolRegistry, ToolDispatcher
# 1. Register action metadata with JSON Schema
reg = ToolRegistry()
reg.register(
name="create_sphere",
description="Create a polygon sphere in Maya",
category="geometry",
tags=["geo", "create", "mesh"],
dcc="maya",
version="1.0.0",
input_schema=json.dumps({
"type": "object",
"required": ["radius"],
"properties": {
"radius": {
"type": "number",
"minimum": 0.1,
"description": "Sphere radius"
},
"segments": {
"type": "integer",
"minimum": 4,
"default": 16,
"description": "Subdivision segments"
},
"name": {
"type": "string",
"description": "Optional sphere name"
}
}
}),
)
# 2. Create dispatcher and register handler
dispatcher = ToolDispatcher(reg)
def handle_create_sphere(params):
radius = params.get("radius", 1.0)
segments = params.get("segments", 16)
name = params.get("name")
# Call Maya API (example using maya.cmds)
import maya.cmds as cmds
sphere_name = cmds.polySphere(r=radius, sx=segments, sy=segments, n=name)[0]
return {
"created": True,
"object_name": sphere_name,
"radius": radius,
"segments": segments,
}
dispatcher.register_handler("create_sphere", handle_create_sphere)
# 3. Dispatch using JSON (wire format)
import json
result = dispatcher.dispatch("create_sphere", json.dumps({"radius": 2.0, "segments": 32}))
print(result["output"]["object_name"]) # "pSphere1"Key Takeaways
- Use
ToolRegistry.register()— pass name, description, tags, DCC, version, and JSON Schema - Implement a handler function — receives
params: dict, returns a result dictionary - Use
ToolDispatcherto register handlers — connects an action name to a Python callable - Use JSON Schema for validation —
ToolDispatchervalidates JSON input before calling the handler - Dispatch with JSON strings — the wire format uses JSON, not Python dicts
Handler Function Signature
python
def my_handler(params: dict) -> Any:
"""
Args:
params: Validated parameters (parsed from JSON input)
Returns:
A dictionary to be used as the action result (serializable to JSON)
"""
passValidation with ToolValidator
Validate inputs before dispatching:
python
from dcc_mcp_core import ToolValidator
validator = ToolValidator.from_action_registry(reg, "create_sphere", dcc_name="maya")
ok, errors = validator.validate('{"radius": 1.5}')
if not ok:
print(f"Validation failed: {errors}")
# Handle errorVersioned Actions
Use VersionedRegistry for backward compatibility:
python
from dcc_mcp_core import VersionedRegistry
vr = VersionedRegistry()
# v1: basic sphere
vr.register_versioned(
"create_sphere", dcc="maya", version="1.0.0",
description="Basic sphere creation",
)
# v2: add subdivision parameter
vr.register_versioned(
"create_sphere", dcc="maya", version="2.0.0",
description="Sphere with subdivision control",
)
# Automatically resolve the best version
result = vr.resolve("create_sphere", "maya", "^1.0.0")
print(result["version"]) # "2.0.0"JSON Schema Tips
- Use
$reffor reusable schemas (ToolValidator does not support this — inline all definitions) "default"fields set defaults when keys are missing from input- Use
"minimum"/"maximum"for numeric constraints - Use
"minLength"/"maxLength"for string length constraints - Use
"enum"to restrict string choices
python
input_schema = json.dumps({
"type": "object",
"required": ["radius"],
"properties": {
"radius": {
"type": "number",
"minimum": 0.1,
"maximum": 1000.0,
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 64,
},
"align_to_world": {
"type": "boolean",
"default": False,
}
}
})