Houdini MCP Connection Skill
Current local installation — Houdini 22 / Codex (2026-09-06)
Use this installation for Houdini 22. The Houdini 21 paths and port 9876 below are legacy notes; the old plugin files were absent when checked on 2026-09-06.
- Houdini:
H:\Program Files\Side Effects Software\Houdini 22.0.368\bin\houdini.exe(Python 3.13). - Plugin root and complete instructions:
C:\Users\nieyi\Documents\houdini22.0\houdini-mcp\INSTALLATION.md. - Plugin package:
<root>\scripts\python\houdinimcp; independent Python 3.12 bridge at<root>\.venv\Scripts\python.exe. - Codex registration:
~/.codex/config.toml,[mcp_servers.houdini], bridge argument--port 9877. Host127.0.0.1. 9876 is reserved for Blender MCP. - Autostart: package
Documents\houdini22.0\packages\houdinimcp.jsonadds root to Houdini path;python3.13libs/uiready.pycalls<root>\start_mcp.py. Also installed package entries under~\houdini22.0\packagesfor alternate preference resolution. - Current upstream
__init__.pydoes not autostart on import: explicitly callinitialize_plugin()thenstart_server(host='127.0.0.1', port=9877). - Current patched server uses
server_socket, not the legacysocketfield. Event polling useshou.ui.addEventLoopCallback; FastMCP usesinstructions=. Protocol is 4-byte big-endian length followed by UTF-8 JSON. - Local SHFS assets are on C: while Houdini is on H:.
packages/shfs-location.jsonpoints SHFS toC:/Program Files/Side Effects Software/shfs, fixing the startup warning. - Verified actual GUI autostart, stdio handshake, 25 tools, scene reads, and read-only Python execution. Results:
<root>\validation-ui.json,<root>\validation-mcp.json. Six OPUS tools require optional RapidAPI configuration. - Manual load into an already running Houdini Python Shell (one line):
exec(compile(open(r'C:/Users/nieyi/Documents/houdini22.0/houdini-mcp/start_mcp.py', encoding='utf-8').read(), 'start_mcp.py', 'exec')). - Read the installation instructions before reusing the legacy recipes below. First install requires restarting Codex to load newly registered tools.
This skill restores or sets up Claude → Houdini MCP control on this Windows box. The full architecture and file paths are in the user's memory houdini_mcp_integration.md — read that first if context is missing.
Architecture (one-screen recap)
Claude Code ──stdio──▶ bridge venv python (.venv\Scripts\python.exe houdini_mcp_server.py)
│
│ TCP localhost:9876
▼
Houdini UI process
(houdinimcp Python plugin)
- Bridge process is spawned by Claude Code per session via
mcpServersconfig in~/.claude/settings.json(or~/.claude.json). - Houdini-side plugin auto-loads via
Documents\houdini21.0\scripts\123.pyand listens on 9876 inside the running UI process. - Houdini must be the UI process (
houdini.exe/hindie.exe/houdinifx.exe), nothython.exe— plugin uses Qt which only exists in UI session.
Diagnostic flow (run in this order)
When the user reports "MCP doesn't work" or wants to verify:
Is Houdini running?
Get-Process | ? Name -match 'hindie|houdini|houdinicore|houdinifx' | Format-Table Id,NameIf empty → ask user to start Houdini, stop here.
Is port 9876 listening?
Get-NetTCPConnection -LocalPort 9876 -ErrorAction SilentlyContinueIf empty → plugin isn't loaded; jump to Reload plugin.
Smoke test the round-trip: call
mcp__houdini__get_scene_info(no args). Returns scene JSON → done. Returnsmcp_server_send_command_timeout→ plugin loaded but tick mechanism is broken; jump to Apply patches.
Reload plugin (one-liner)
Have the user paste this single-line snippet into Houdini's Python Shell (multi-line paste breaks the Houdini REPL):
import sys; hou.session.houdinimcp_server.stop() if getattr(hou.session,'houdinimcp_server',None) else None; [sys.modules.pop(m) for m in list(sys.modules) if m=='houdinimcp' or m.startswith('houdinimcp.')]; hou.session.houdinimcp_server=None; import houdinimcp; print('reloaded; cb registered=', hou.session.houdinimcp_server._loop_callback_registered)
Expected output ends with cb registered= True and HoudiniMCP server started on localhost:9876.
Apply patches (when capoom upstream is freshly downloaded)
The vanilla capoomgit/houdini-mcp server.py uses PySide2 and a free-floating QtCore.QTimer. Both fail under Houdini 21 (PySide6 only) and the QTimer never auto-fires reliably from the Python Shell context. Two patches needed in Documents\houdini21.0\scripts\python\houdinimcp\server.py:
Patch 1 — PySide6 fallback (line ~12)
Replace:
from PySide2 import QtWidgets, QtCore
with:
try:
from PySide6 import QtWidgets, QtCore
except ImportError:
from PySide2 import QtWidgets, QtCore
Patch 2 — Use Houdini's UI event loop (replace start() and stop() methods)
The whole start() / stop() / _io_loop() cluster gets replaced. Use hou.ui.addEventLoopCallback(self._process_server) — Houdini's official UI tick. The legacy _process_server() method below it stays untouched as the actual handler.
Replace start() body with:
def start(self):
"""Begin listening on the given port; register a callback on Houdini's UI event loop."""
self.running = True
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
self.socket.bind((self.host, self.port))
self.socket.listen(1)
self.socket.setblocking(False)
hou.ui.addEventLoopCallback(self._process_server)
self._loop_callback_registered = True
print(f"HoudiniMCP server started on {self.host}:{self.port}")
except Exception as e:
print(f"Failed to start server: {str(e)}")
self.stop()
Replace stop() body with:
def stop(self):
"""Stop listening; unregister callback and close sockets."""
self.running = False
if getattr(self, '_loop_callback_registered', False):
try:
hou.ui.removeEventLoopCallback(self._process_server)
except Exception:
pass
self._loop_callback_registered = False
if self.socket:
try: self.socket.close()
except Exception: pass
if self.client:
try: self.client.close()
except Exception: pass
self.socket = None
self.client = None
print("HoudiniMCP server stopped")
After patching, run the Reload plugin one-liner above.
What does NOT work (avoid suggesting)
QtCore.QTimer()without parent under PySide6: created but never fires when triggered from Python Shell context.QtCore.QTimer(hou.qt.mainWindow()):hou.qt.mainWindow()returnsNonein some startup contexts → same problem.hdefereval.executeDeferredAfterWaiting(cb, 0.1)self-rescheduling: only fires when user UI is actually idle — never in a self-loop.- Background thread +
hdefereval.executeInMainThreadWithResult: dispatch hangs because main-thread callback delivery shares the same broken trigger. - Only
hou.ui.addEventLoopCallbackis fully reliable for periodic main-thread polling under Houdini 21.
Cold-install from scratch (rare)
If the plugin directory doesn't exist yet, do this:
mkdir -p "C:/Users/nieyi/Documents/houdini21.0/scripts/python/houdinimcp" "C:/Users/nieyi/Documents/houdini21.0/toolbar"- Curl 5 files from
https://raw.githubusercontent.com/capoomgit/houdini-mcp/main/:__init__.py,pyproject.toml,server.py,HoudiniMCPRender.py,houdini_mcp_server.py - Write
urls.envwith emptyRAPIDAPI_KEY= - Apply the two patches above to
server.py - Install uv:
powershell -c "irm https://astral.sh/uv/install.ps1 | iex" cdto plugin dir,uv venv,uv pip install "mcp[cli]>=1.4.1" requests python-dotenv- Write
Documents\houdini21.0\scripts\123.pycontaining:try: import houdinimcp print("[houdinimcp] auto-started on localhost:9876") except Exception as e: print(f"[houdinimcp] auto-start failed: {e}") - Add to
~/.claude/settings.jsonunder top-levelmcpServers:"mcpServers": { "houdini": { "command": "C:\\Users\\nieyi\\Documents\\houdini21.0\\scripts\\python\\houdinimcp\\.venv\\Scripts\\python.exe", "args": ["C:\\Users\\nieyi\\Documents\\houdini21.0\\scripts\\python\\houdinimcp\\houdini_mcp_server.py"] } } - User restarts Claude Code session → new MCP server picked up. User starts Houdini → plugin auto-starts via 123.py.
Tools exposed once connected
mcp__houdini__get_scene_info— scene metadata + node listmcp__houdini__create_node— create a single node (node_type,parent_path,name)mcp__houdini__execute_houdini_code— most powerful: arbitraryhou.*Python; use this for anything beyond simple node creationmcp__houdini__render_single_view/render_quad_views/render_specific_camera— viewport / Karma renders.render_pathis treated as base directory, not file name.mcp__houdini__opus_*— exposed but will error at call time (no RapidAPI key).
Gotchas
- Path discrepancy:
hindie.exeusesDocuments/houdini21.0/,hython.exeuses~/houdini21.0/. Plugin lives under the UI dir; never trusthythonfor path resolution. - Multi-line paste in Houdini Python Shell: lines get concatenated and break syntax. Always use single-line one-liners (with
;). - Bridge connects fine without Houdini:
claude mcp listshows ✓ even when Houdini is closed. Only individual tool calls fail with "Could not connect to Houdini on port 9876".