Houdini MCP Server
Provides tools for controlling SideFX Houdini via hrpyc, enabling AI assistants to interact with Houdini sessions for scene management, node operations, rendering, and more.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Houdini MCP ServerCreate a sphere node at origin with radius 5"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Houdini MCP Server
An MCP (Model Context Protocol) server for controlling SideFX Houdini via hrpyc, enabling AI assistants like Claude, Cursor, and Letta agents to interact with Houdini sessions.
Architecture
+-----------------+ MCP (HTTP) +------------------+ hrpyc:18811 +-------------+
| Claude/Cursor | <------------------> | MCP Server | <------------------> | Houdini |
| Letta Agents | | (Python/FastMCP)| | Session |
+-----------------+ +------------------+ +-------------+Related MCP server: BlenderMCP
Features
43 MCP tools across 15 modular categories
Full hou module access - Execute any Houdini Python code remotely
Scene management - Create, load, save scenes
Node operations - Create, delete, modify nodes and parameters
Rendering - Viewport renders, quad views, Karma GPU/CPU support
Pane screenshots - Capture NetworkEditor, SceneViewer, and other panes
Scene serialization - Diff scene states before/after operations
Connection management - Auto-reconnect with exponential backoff + jitter
Error handling - Consistent error responses with recovery hints
Response optimization - Size limits, truncation, AI summarization
In-memory caching - Node type cache with TTL for performance
Prerequisites
Houdini with RPC enabled - Start Houdini's RPC server:
In Houdini:
Windows > Python Shell, then run:import hrpyc hrpyc.start_server(port=18811)Or add to your
123.pystartup script for automatic startup
Network access - The MCP server must be able to reach Houdini's RPC port (default: 18811)
Installation
Option 1: Houdini Plugin (stdio mode)
The Houdini plugin runs the MCP server directly inside Houdini, using stdio transport. This is the simplest setup with no network configuration required.
Installation:
Copy the
houdini_pluginfolder to your Houdini packages directory:# Windows copy houdini_plugin %USERPROFILE%\Documents\houdini20.5\packages\houdini_mcp # Linux/Mac cp -r houdini_plugin ~/houdini20.5/packages/houdini_mcpCopy the package JSON:
# Windows copy houdini_plugin\houdini_mcp.json %USERPROFILE%\Documents\houdini20.5\packages\ # Linux/Mac cp houdini_plugin/houdini_mcp.json ~/houdini20.5/packages/Install FastMCP in Houdini's Python:
# Windows (from Houdini's Python) hython -m pip install fastmcp # Or from Houdini's Python Shell import subprocess subprocess.run(["pip", "install", "fastmcp"])Restart Houdini and find the "Houdini MCP" shelf
Usage:
Click "Start MCP" on the shelf to start the server
Configure your MCP client (Claude Desktop, Cursor, etc.) to use stdio transport
Click "Stop MCP" to stop the server
MCP Client Configuration (stdio mode):
{
"mcpServers": {
"houdini": {
"command": "hython",
"args": ["-c", "from houdini_mcp_plugin import start_server; start_server(use_thread=False)"]
}
}
}Option 2: Docker (Remote mode)
For production use or when Houdini runs on a different machine, use the Docker-based remote mode. This connects to Houdini via hrpyc/RPyC.
Step 1: Start hrpyc in Houdini
If you have the Houdini MCP plugin installed:
Click "Start Remote" on the Houdini MCP shelf
Note the IP and port shown in the dialog
Or manually in Houdini's Python Shell:
import hrpyc
hrpyc.start_server(port=18811)Step 2: Run the Docker MCP server
# Clone the repository
git clone https://github.com/oculairmedia/houdini-mcp.git
cd houdini-mcp
# Copy and configure environment
cp .env.example .env
# Edit .env with your Houdini host IP (from Step 1)
# Run with Docker Compose
docker compose up -dStep 3: Configure your MCP client
{
"mcpServers": {
"houdini": {
"url": "http://localhost:3055"
}
}
}Benefits of Remote Mode:
Houdini can run on a different machine (e.g., render farm)
MCP server runs in Docker for easy deployment
Full tool set with advanced features
Server-side processing capabilities
Local Development
# Clone and install
git clone https://github.com/oculairmedia/houdini-mcp.git
cd houdini-mcp
pip install -r requirements.txt
# Run
HOUDINI_HOST=192.168.50.90 python -m houdini_mcpConfiguration
Environment variables:
Variable | Default | Description |
|
| Houdini machine IP/hostname |
|
| hrpyc server port |
|
| MCP server HTTP port |
|
| Transport type (http, stdio, sse) |
|
| Logging level |
Tool Categories (43 Tools)
The server is organized into 15 modular tool categories in houdini_mcp/tools/:
Scene & Nodes (scene.py, nodes.py)
Tool | Description |
| Get current scene info (file, version, nodes) |
| Serialize scene structure for diffs |
| Create empty scene |
| Save current scene |
| Load a .hip file |
| Create a new node |
| Delete a node by path |
| Get node details, parameters, connections, errors |
| List child nodes with connection details |
| Find nodes by name pattern or type |
| List available node types by category |
Wiring & Layout (wiring.py, layout.py)
Tool | Description |
| Wire nodes together |
| Break a connection |
| Reorder node inputs |
| Set display/render/bypass flags |
| Auto-layout child nodes |
| Set node position in network |
| Set node color |
| Create network box around nodes |
Parameters (parameters.py)
Tool | Description |
| Set a parameter value |
| Get parameter metadata (types, ranges, menus) |
Geometry & Materials (geometry.py, materials.py)
Tool | Description |
| Get geometry statistics and metadata |
| Create a new material |
| Assign material to geometry |
| Get material parameters and shaders |
Rendering (rendering.py)
Tool | Description |
| Render viewport with camera control |
| Render Front/Left/Top/Perspective views |
| List all ROPs in /out |
| Get ROP configuration |
| Modify ROP settings |
| Create new ROP with settings |
Pane Screenshots (pane_screenshot.py)
Tool | Description |
| Capture any Houdini pane as PNG |
| List capturable panes |
| Batch capture multiple panes |
| Navigate to node and capture network |
Code Execution (code.py, hscript.py)
Tool | Description |
| Execute Python with |
| Execute HScript commands |
Error Handling (errors.py)
Tool | Description |
| Find all nodes with cook errors |
Help & Summarization (help.py, summarization.py)
Tool | Description |
| Get help for node types |
| AI-summarize large responses |
| Estimate token count |
| Get summarization config |
Infrastructure (_common.py, cache.py)
Error handling:
@handle_connection_errorsdecoratorConnection retry: Exponential backoff with jitter
Response size: Thresholds, truncation, metadata
Caching: Node type cache with TTL
Parallel execution:
semaphore_gather,batch_items
Common Patterns
Creating SOP Chains
Build a complete SOP network from scratch:
# 1. Create geo container
geo = create_node("geo", "/obj", "my_geo")
# 2. Create SOP nodes
sphere = create_node("sphere", geo["node_path"], "sphere1")
xform = create_node("xform", geo["node_path"], "xform1")
color = create_node("color", geo["node_path"], "color1")
out = create_node("null", geo["node_path"], "OUT")
# 3. Wire nodes together
connect_nodes(sphere["node_path"], xform["node_path"])
connect_nodes(xform["node_path"], color["node_path"])
connect_nodes(color["node_path"], out["node_path"])
# 4. Set display flag
set_node_flags(out["node_path"], display=True, render=True)Inserting Nodes Into Existing Chains
Insert a new node between existing connections:
# 1. Discover existing network
children = list_children("/obj/geo1")
# Find grid and noise nodes from children
# 2. Get current connections
noise_info = get_node_info("/obj/geo1/noise1", include_input_details=True)
# See that noise is connected to grid
# 3. Create new node
mountain = create_node("mountain", "/obj/geo1", "mountain1")
# 4. Rewire: grid → mountain → noise
disconnect_node_input("/obj/geo1/noise1", 0) # Break noise ← grid
connect_nodes("/obj/geo1/grid1", "/obj/geo1/mountain1") # grid → mountain
connect_nodes("/obj/geo1/mountain1", "/obj/geo1/noise1") # mountain → noiseSetting Parameters Intelligently
Use parameter schema to set values correctly:
# 1. Discover parameter metadata
schema = get_parameter_schema("/obj/geo1/sphere1", parm_name="rad")
param = schema["parameters"][0]
# 2. Check parameter type
if param["type"] == "vector":
# Set vector parameter correctly
set_parameter("/obj/geo1/sphere1", "rad", [3.0, 3.0, 3.0])
elif param["type"] == "menu":
# Use menu items
first_option = param["menu_items"][0]["value"]
set_parameter("/obj/geo1/sphere1", "type", first_option)Verifying Results
Always verify geometry after operations:
# Get comprehensive geometry summary
summary = get_geo_summary(
"/obj/geo1/OUT",
max_sample_points=10,
include_attributes=True
)
# Check cook state
if summary["cook_state"] != "cooked":
# Handle errors
node_info = get_node_info("/obj/geo1/OUT", include_errors=True)
errors = node_info["cook_info"]["errors"]
# Fix errors...
# Verify geometry metrics
assert summary["point_count"] > 0
assert summary["primitive_count"] > 0
# Check bounding box
bbox = summary["bounding_box"]
# Verify expected size/positionError Handling Best Practices
Check Cook State Before Reading Geometry
# 1. Check cook state first
node_info = get_node_info(
node_path,
include_errors=True,
force_cook=True
)
cook_state = node_info["cook_info"]["cook_state"]
# 2. Handle different states
if cook_state == "error":
# Examine errors
errors = node_info["cook_info"]["errors"]
for err in errors:
print(f"Error: {err['message']}")
# Fix errors...
elif cook_state == "cooked":
# Safe to access geometry
geo = get_geo_summary(node_path)Validate Parameter Types
# Always check parameter schema before setting
schema = get_parameter_schema(node_path, parm_name="rad")
param = schema["parameters"][0]
if param["type"] == "vector":
# Use list/tuple for vector parameters
set_parameter(node_path, "rad", [5.0, 5.0, 5.0])
else:
# Use scalar for single parameters
set_parameter(node_path, "rad", 5.0)Handle Connection Errors
# Connection validation
result = connect_nodes(src_path, dst_path)
if result["status"] == "error":
if "incompatible" in result["message"].lower():
# Different node categories (e.g., SOP vs OBJ)
print("Can't connect nodes of different types")
elif "not found" in result["message"].lower():
# Node doesn't exist
print("Source or destination node not found")Debugging with Error Introspection
# Use include_errors=True to diagnose issues
node_info = get_node_info(
node_path,
include_errors=True,
force_cook=True
)
cook_info = node_info["cook_info"]
# Check for errors
if cook_info["errors"]:
print(f"Node has {len(cook_info['errors'])} errors:")
for error in cook_info["errors"]:
print(f" - {error['message']}")
# Check for warnings
if cook_info["warnings"]:
print(f"Node has {len(cook_info['warnings'])} warnings:")
for warning in cook_info["warnings"]:
print(f" - {warning['message']}")Example Workflows
Complete working examples are available in the examples/ directory:
build_from_scratch.py- Build sphere → xform → color → OUT from scratchaugment_existing_scene.py- Insert mountain between grid → noiseparameter_workflow.py- Discover → set → verify parameterserror_handling.py- Detect → fix → verify errors
Run examples:
cd examples
python build_from_scratch.py
python augment_existing_scene.py
python parameter_workflow.py
python error_handling.pyUsage Examples
With Claude/Cursor
Add to your MCP client configuration:
{
"mcpServers": {
"houdini": {
"url": "http://localhost:3055"
}
}
}With Letta
Add as an MCP server in Letta's configuration to give agents Houdini control.
Example Prompts
"Create a sphere → transform → color → OUT network"
"Insert a mountain node between the grid and noise"
"Discover what parameters are available on the sphere node"
"Check if the noise node has any cook errors"
"Set the sphere radius to 3.0 using the parameter schema"
Development
# Install dev dependencies
pip install -r requirements.txt pytest
# Run tests
pytest tests/
# Run server locally
python -m houdini_mcpTroubleshooting
Connection refused
Verify Houdini is running with hrpyc server started
Check firewall allows port 18811
Verify HOUDINI_HOST is correct
Authentication errors
hrpyc uses no authentication by default
Ensure you're on a trusted network
Project Structure
houdini_mcp/
├── server.py # FastMCP server with 43 tool wrappers
├── connection.py # RPyC connection with retry/backoff
└── tools/ # Modular tool implementations
├── _common.py # Shared utilities, error handling
├── cache.py # Node type caching with TTL
├── code.py # Python/HScript execution
├── errors.py # Error node detection
├── geometry.py # Geometry introspection
├── help.py # Houdini help access
├── hscript.py # HScript command execution
├── layout.py # Node layout tools
├── materials.py # Material creation/assignment
├── nodes.py # Node CRUD operations
├── pane_screenshot.py # Pane capture tools
├── parameters.py # Parameter get/set
├── rendering.py # Viewport/Karma rendering
├── scene.py # Scene management
├── summarization.py # AI response summarization
└── wiring.py # Node connection tools
houdini_plugin/ # Houdini plugin for stdio mode
├── python/houdini_mcp_plugin/
├── toolbar/ # Shelf tools
└── houdini_mcp.json # Package descriptor
tests/ # 418 tests (406 passing)
docs/ # Implementation documentation
examples/ # Working example scriptsCredits
Based on hrpyc integration patterns from OpenWebUI Houdini Pipeline
Inspired by capoomgit/houdini-mcp
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/oculairmedia/houdini-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server