MotionBuilderBridge is a lightweight TCP bridge that lets external agents run
Python inside Autodesk MotionBuilder through pyfbsdk.
It mirrors the useful parts of UnrealBridge:
- length-prefixed JSON over TCP
- UDP multicast discovery plus endpoint-cache fallback, so the TCP port does not need to be hardcoded
- optional token auth for non-loopback binds
- persistent in-application Python namespace
- stdout/stderr capture per execution
- helper APIs for scene files, models, selection, skeletons, animation keys, characters, playback, and takes
- agent-facing skill/docs layout under
.claude/skills/motionbuilder-bridge
Recommended: install the user-level startup loader once:
powershell -ExecutionPolicy Bypass -File tools\install_mobu_startup.ps1 -MotionBuilderVersion 2024 -Scope User -AutoStartBridge -OpenPanelAfter that, MotionBuilder starts the bridge automatically on launch, registers
MotionBuilderBridge Control Panel under Python Tools, and opens the control
panel. No administrator rights are required for -Scope User. The user-level
installer writes the loader to the common Documents and AppData startup folders
and appends a repo-local startup folder to MOTIONBUILDER_PYTHON_STARTUP
because different MoBu installs resolve their user startup path differently,
especially when Documents is redirected to OneDrive.
Manual fallback: open MotionBuilder's Python Shell and run:
exec(open(r"D:/LAFAN/MotionBuilderBridge/scripts/start_bridge.py").read())Optional graphical control panel:
exec(open(r"D:/LAFAN/MotionBuilderBridge/py/mb_bridge_tool.py").read())The panel can start, stop, restart, refresh status, copy common commands, run a smoke test, and open the API docs.
Expected log:
[MBBridge] listening on 127.0.0.1:<ephemeral-port>
[MBBridge] discovery on 239.255.43.42:8997
The TCP port is OS-assigned by default. Clients discover it through UDP. The server also writes a local endpoint cache at startup, so clients can still find the current port when UDP multicast is delayed or blocked.
For a fixed TCP port:
import sys
sys.path.insert(0, r"D:/LAFAN/MotionBuilderBridge/py")
from mb_bridge_server import start_bridge
start_bridge(port=8997)cd D:\LAFAN\MotionBuilderBridge
python scripts\bridge.py pingpython scripts\bridge.py exec "import pyfbsdk as fb; print(fb.FBSystem().Version)"
python scripts\bridge.py exec-file scripts\example.pyFor multi-line one-shot scripts:
@'
from mb_helpers import get_scene_info, dump_json
dump_json(get_scene_info())
'@ | python scripts\bridge.py exec --stdinStop the server:
python scripts\bridge.py stopTCP frames are UnrealBridge-style length-prefixed JSON:
Request: [4-byte big-endian length][JSON {"id":"...","script":"...","timeout":30,"token":"optional"}]
Response: [4-byte big-endian length][JSON {"id":"...","success":true,"output":"...","error":""}]
Inline commands:
| Command | Purpose |
|---|---|
ping |
TCP liveness check |
stop |
Stop the in-MotionBuilder bridge |
Discovery uses UDP multicast:
Group: 239.255.43.42:8997
Probe: {"v":1,"type":"probe","request_id":"...","filter":{"project":"*"}}
Response: {"v":1,"type":"response","app":"motionbuilder","tcp_bind":"127.0.0.1","tcp_port":...}
At startup the server also writes endpoint cache files:
D:\LAFAN\MotionBuilderBridge\Saved\MotionBuilderBridge\endpoint.json
%LOCALAPPDATA%\MotionBuilderBridge\endpoint.json
The CLI tries UDP discovery first, then automatically validates and uses the
cached endpoint. Set MB_BRIDGE_DISABLE_CACHE=1 to disable that fallback.
Server configuration precedence is explicit start_bridge(...) argument, then
environment variable, then default.
| Argument | Environment | Default | Effect |
|---|---|---|---|
host |
MB_BRIDGE_BIND |
127.0.0.1 |
TCP bind interface |
port |
MB_BRIDGE_PORT |
0 |
TCP port; 0 means OS-assigned |
token |
MB_BRIDGE_TOKEN |
empty | Optional auth token |
discovery_group |
MB_BRIDGE_DISCOVERY_GROUP |
239.255.43.42:8997 |
UDP discovery group |
discovery_enabled |
MB_BRIDGE_DISCOVERY |
1 |
0 disables UDP discovery |
If the server binds a non-loopback interface and no token was supplied, it generates one and writes it to:
D:\LAFAN\MotionBuilderBridge\Saved\MotionBuilderBridge\token.txt
Client overrides:
| CLI / Env | Purpose |
|---|---|
--endpoint HOST:PORT / MB_BRIDGE_ENDPOINT |
Skip discovery and connect directly |
--project NAME_OR_PATH / MB_BRIDGE_PROJECT |
Select one discovered instance |
--token TOKEN / MB_BRIDGE_TOKEN |
Auth token |
--discovery-group HOST:PORT / MB_BRIDGE_DISCOVERY_GROUP |
Override multicast group |
MB_BRIDGE_ENDPOINT_CACHE |
Override endpoint cache file path |
MB_BRIDGE_DISABLE_CACHE=1 |
Disable endpoint-cache fallback |
MotionBuilderBridge/
py/
mb_bridge_server.py # In-MotionBuilder TCP server + discovery responder
mb_bridge_protocol.py # Length-prefixed JSON helpers
mb_helpers.py # Agent-friendly pyfbsdk wrappers
mb_fps_helpers.py # FPS animation rig/pose/loop helper layer
mb_bridge_plugin.py # Loader that auto-starts the bridge
mb_bridge_tool.py # Optional MotionBuilder UI control panel
scripts/
bridge.py # External CLI client
start_bridge.py # Script to exec inside MotionBuilder
example.py # Read-only smoke script
docs/
motionbuilder-bridge-api.md
.claude/skills/motionbuilder-bridge/
SKILL.md
scripts/bridge.py
Create a clean zip:
powershell -ExecutionPolicy Bypass -File tools\package_release.ps1Install the agent skill globally for Claude and Codex:
powershell -ExecutionPolicy Bypass -File tools\install_agent_skill.ps1 -Target BothOptional MotionBuilder auto-start/control-panel loader:
powershell -ExecutionPolicy Bypass -File tools\install_mobu_startup.ps1 -MotionBuilderVersion 2024 -Scope User -AutoStartBridge -OpenPanelSee docs/packaging.md for the full distribution flow.
from mb_helpers import (
get_scene_info,
list_models,
create_null,
select_models,
list_skeleton_roots,
get_skeleton_hierarchy,
get_skeleton_pose,
set_skeleton_pose,
get_character_skeleton,
get_character_link_map,
characterize_biped,
list_animatable_properties,
get_property_animation_keys,
get_transform_curves,
set_curve_key,
set_model_transform_key,
dump_json,
)FPS animation helpers:
from mb_fps_helpers import (
get_fps_rig_context,
suggest_weapon_rig,
generate_aim_offset_set,
check_aim_offset_smoothness,
generate_cover_variants,
analyze_locomotion_loop,
fix_locomotion_loop,
auto_align_weapon_switch,
retarget_with_style,
)Examples:
python scripts\bridge.py exec "from mb_fps_helpers import suggest_weapon_rig; from mb_helpers import dump_json; dump_json(suggest_weapon_rig('assault_rifle'))"@'
from mb_fps_helpers import generate_aim_offset_set, check_aim_offset_smoothness
from mb_helpers import dump_json
aim = generate_aim_offset_set(yaw_range=(-45, 45), pitch_range=(-30, 30), granularity=15)
dump_json(check_aim_offset_smoothness(aim))
'@ | python scripts\bridge.py exec --stdinSee docs/motionbuilder-bridge-api.md for the current helper surface.
- Read-only inspection is safe by default.
- Destructive operations such as deleting models, modifying files, or saving scenes should only be done after explicit user confirmation.
execruns on MotionBuilder's main Python/UI context. A longwhileloop ortime.sleepinside one script can freeze the application until it returns.
- Autodesk MotionBuilder with Python 3 and
pyfbsdk - External client Python 3.9+