Houdini远程控制服务器

通过MCP协议控制SideFX Houdini的服务器,实现AI助手与Houdini会话的交互,提供场景管理、节点操作、渲染等功能。

  • by oculairmedia
  • Python
  • 本地部署
  • 83 星标
  • 更新于
在 GitHub 查看 oculairmedia/houdini-mcp

使用说明

Houdini MCP服务器

用于通过以下方式控制SideFX Houdini的MCP(模型上下文协议)服务器 hrpyc,使Claude、Cursor和Letta代理等AI助手能够与Houdini会话进行交互。

建筑学

+-----------------+      MCP (HTTP)       +------------------+      hrpyc:18811      +-------------+
|  Claude/Cursor  | <------------------> |   MCP Server     | <------------------> |   Houdini   |
|  Letta Agents   |                      |  (Python/FastMCP)|                      |   Session   |
+-----------------+                      +------------------+                      +-------------+

架构决策

架构决策记录(ADR) docs/adr/:

  • ADR 0001:语言和过程边界 --为什么服务器仍然使用Python hou 语义和FastMCP网关 模块边界和允许的依赖方向以及测量的阈值 这将证明未来非Python sidecar的合理性。

特性

  • 43个MCP工具 横跨15个模块化类别
  • 完全后模块访问 -远程执行任何Houdini Python代码
  • 场景管理 -创建、加载、保存场景
  • 节点操作 -创建、删除、修改节点和参数
  • 渲染 -视口渲染、四视图、Karma GPU/CPU支持
  • 窗格截图 -捕获网络编辑器、场景查看器和其他窗格
  • 场景序列化 -操作前后不同的场景状态
  • 连接管理 -指数回退+抖动自动重新连接
  • 错误处理 -具有恢复提示的一致错误响应
  • 响应优化 -大小限制、截断、AI摘要
  • 内存缓存 -具有TTL的节点类型缓存以提高性能

先决条件

  1. 启用RPC的Houdini -启动Houdini的RPC服务器:

    • 在胡迪尼: Windows > Python Shell,然后运行:
      import hrpyc
      hrpyc.start_server(port=18811)
      
    • 或添加到您的 123.py 自动启动的启动脚本
  2. 网络接入 -MCP服务器必须能够访问Houdini的RPC端口(默认值:18811)

安装

有关Windows上的Codex桌面,请参阅中的专用设置说明 docs/codex-windows-setup.md.

选项1:Houdini插件(stdio模式)

Houdini插件使用stdio传输直接在Houdini内部运行MCP服务器。这是最简单的设置,不需要网络配置。

安装:

  1. 复制 houdini_plugin 文件夹到您的Houdini包目录:

    # Windows
    copy houdini_plugin %USERPROFILE%\Documents\houdini20.5\packages\houdini_mcp
    
    # Linux/Mac
    cp -r houdini_plugin ~/houdini20.5/packages/houdini_mcp
    
  2. 复制包JSON:

    # Windows
    copy houdini_plugin\houdini_mcp.json %USERPROFILE%\Documents\houdini20.5\packages\
    
    # Linux/Mac
    cp houdini_plugin/houdini_mcp.json ~/houdini20.5/packages/
    
  3. 在Houdini的Python中安装FastMCP:

    # Windows (from Houdini's Python)
    hython -m pip install fastmcp
    
    # Or from Houdini's Python Shell
    import subprocess
    subprocess.run(["pip", "install", "fastmcp"])
    
  4. 重新启动Houdini并找到“Houdini MCP”机框

用途:

  • 点击机框上的“启动MCP”以启动服务器
  • 配置您的MCP客户端(Claude Desktop、Cursor等)以使用stdio传输
  • 点击“停止MCP”停止服务器

MCP客户端配置(stdio模式):

{
  "mcpServers": {
    "houdini": {
      "command": "hython",
      "args": ["-c", "from houdini_mcp_plugin import start_server; start_server(use_thread=False)"]
    }
  }
}

选项2:Docker(远程模式)

对于生产使用或当Houdini在不同的机器上运行时,请使用基于Docker的远程模式。这通过hrpyc/RPyC连接到Houdini。

第一步:在Houdini中启动hrpyc

如果您安装了Houdini MCP插件:

  • 点击 “远程启动” 在Houdini MCP货架上
  • 使用 “远程状态” / “远程自检” 确认实际界限 端点、可达性和防火墙指导
  • 默认情况下,侦听器绑定到 127.0.0.1 (仅限环回)。让a 远程客户端(例如另一台主机上的Docker网关)连接,设置 HOUDINI_RPC_BIND_HOST 和 选择加入 HOUDINI_RPC_TRUSTED_NETWORK=1 或 HOUDINI_RPC_TOKEN。参见 docs/remote-listener.md.

或者在Houdini的Python Shell中手动操作(未更改,仍受支持):

import hrpyc
hrpyc.start_server(port=18811)

步骤2:运行Docker MCP服务器

# 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 -d

步骤3:配置MCP客户端

{
  "mcpServers": {
    "houdini": {
      "url": "http://localhost:3055"
    }
  }
}

远程模式的优点:

  • Houdini可以在不同的机器上运行(例如,渲染农场)
  • MCP服务器在Docker中运行,便于部署
  • 具有高级功能的全套工具
  • 服务器端处理能力

本地开发

# 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_mcp

配置

环境变量:

变量 默认值 描述
HOUDINI_HOST localhost Houdini机器IP/主机名
HOUDINI_PORT 18811 hrpyc服务器端口
MCP_PORT 3055 MCP服务器HTTP端口
MCP_TRANSPORT http 传输类型(http、stdio、sse)
LOG_LEVEL INFO 日志记录级别

工具类别(43种工具)

服务器分为15个模块化工具类别 houdini_mcp/tools/:

场景和节点(scene.py, nodes.py)

工具 说明
get_scene_info 获取当前场景信息(文件、版本、节点)
serialize_scene 序列化差异的场景结构
new_scene 创建空场景
save_scene 保存当前场景
load_scene 加载.hip文件
create_node 创建新节点
delete_node 按路径删除节点
get_node_info 获取节点详细信息、参数、连接、错误
list_children 列出具有连接详细信息的子节点
find_nodes 按名称模式或类型查找节点
list_node_types 按类别列出可用节点类型

接线和布局(wiring.py, layout.py)

工具 说明
connect_nodes 将节点连接在一起
disconnect_node_input 断开连接
reorder_inputs 重新排序节点输入
set_node_flags 设置显示/渲染/绕过标志
layout_children 自动布局子节点
set_node_position 设置网络中的节点位置
set_node_color 设置节点颜色
create_network_box 在节点周围创建网络框

参数(parameters.py)

工具 说明
set_parameter 设置参数值
get_parameter_schema 获取参数元数据(类型、范围、菜单)

几何形状和材料(geometry.py, materials.py)

工具 说明
get_geo_summary 获取几何统计数据和元数据
create_material 创建新材质
assign_material 为几何体指定材质
get_material_info 获取材质参数和着色器

渲染图(rendering.py)

工具 说明
render_viewport 使用摄影机控制渲染视口
render_quad_view 渲染前/左/上/透视图
list_render_nodes 列出所有进出ROP
get_render_settings 获取ROP配置
set_render_settings 修改ROP设置
create_render_node 使用设置创建新的ROP

窗格截图(pane_screenshot.py)

工具 说明
capture_pane_screenshot 将任何Houdini窗格捕获为PNG
list_visible_panes 列出可捕获窗格
capture_multiple_panes 批量捕获多个窗格
render_node_network 导航到节点并捕获网络

代码执行(code.py, hscript.py)

工具 说明
execute_code 使用以下命令执行Python hou 可用
execute_hscript 执行HScript命令

错误处理(errors.py)

工具 说明
find_error_nodes 查找所有存在cook错误的节点

帮助和摘要(help.py, summarization.py)

工具 说明
get_houdini_help 获取节点类型的帮助
summarize_response AI总结大量响应
estimate_tokens 估计令牌计数
get_summarization_status 获取摘要配置

基础设施(_common.py, cache.py)

  • 错误处理: @handle_connection_errors 装饰器
  • 连接重试:具有抖动的指数回退
  • 响应大小:阈值、截断、元数据
  • 缓存:带TTL的节点类型缓存
  • 并行执行: semaphore_gather, batch_items

常见模式

创建SOP链

从头开始构建一个完整的SOP网络:

# 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)

将节点插入到现有链中

在现有连接之间插入新节点:

# 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 → noise

智能设置参数

使用参数架构正确设置值:

# 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)

验证结果

操作后始终验证几何图形:

# 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/position

错误处理最佳实践

读取几何图形前检查烹饪状态

# 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)

验证参数类型

# 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)

处理连接错误

# 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")

使用错误自检进行调试

# 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']}")

示例工作流

完整的工作示例可在 examples/ 目录:

  • build_from_scratch.py -构建球体→ 变换→ 颜色→ 从头开始
  • augment_existing_scene.py -在网格之间插入山→ noise
  • parameter_workflow.py -发现→ set → 验证参数
  • error_handling.py -检测→ fix → 验证错误

运行示例:

cd examples
python build_from_scratch.py
python augment_existing_scene.py
python parameter_workflow.py
python error_handling.py

使用示例

与克劳德/光标

添加到MCP客户端配置中:

{
  "mcpServers": {
    "houdini": {
      "url": "http://localhost:3055"
    }
  }
}

与莱塔

在Letta的配置中添加为MCP服务器,以赋予代理Houdini控制权。

示例提示

  • “创建球体→ 转化→ 颜色→ OUT网络”
  • “在网格和噪波之间插入一个山节点”
  • “发现球体节点上可用的参数”
  • “检查噪声节点是否有任何烹饪错误”
  • “使用参数模式将球体半径设置为3.0”

发展

# Install dev dependencies
pip install -r requirements.txt pytest

# Run tests
pytest tests/

# Run server locally
python -m houdini_mcp

故障排除

连接被拒绝

  • 验证Houdini是否在hrpyc服务器启动的情况下运行
  • 检查防火墙是否允许端口18811
  • 验证HOUDINI_HOST是否正确

身份验证错误

  • hrpyc默认不使用身份验证
  • 确保您在受信任的网络上
  • 插件拒绝绑定非环回地址,除非您明确选择 in(HOUDINI_RPC_TRUSTED_NETWORK=1)或设置共享密钥 (HOUDINI_RPC_TOKEN).看 docs/remote-listener.md 对于完整的安全模型及其局限性。

项目结构

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 scripts

鸣谢

许可证

麻省理工学院