fxhoudinimcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| LOG_LEVEL | No | Logging level | INFO |
| HOUDINI_HOST | No | Houdini host address | localhost |
| HOUDINI_PORT | No | Houdini hwebserver port | 8100 |
| MCP_TRANSPORT | No | MCP transport (stdio or streamable-http) | stdio |
| FXHOUDINIMCP_PORT | No | Port for the Houdini plugin to listen on | 8100 |
| FXHOUDINIMCP_AUTOSTART | No | Set to 0 to disable auto-start | 1 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| set_keyframeC | Set a single keyframe on a parameter. Args: node_path: Node path. parm_name: Parameter name. frame: Frame number. value: Value at this keyframe. slope: Tangent slope. accel: Acceleration. |
| set_keyframesB | Batch-set multiple keyframes on a parameter. Args: node_path: Node path. parm_name: Parameter name. keyframes: List of dicts with "frame", "value", and optionally "slope"/"accel". |
| delete_keyframeC | Delete a keyframe at a specific frame. Args: node_path: Node path. parm_name: Parameter name. frame: Frame number to delete. |
| get_keyframesC | Get all keyframes on a parameter. Args: node_path: Node path. parm_name: Parameter name. |
| set_frameC | Set the current frame in the timeline. Args: frame: Frame number. |
| get_frameA | Get the current frame and FPS. |
| set_frame_rangeC | Set the global frame range. Args: start: Start frame. end: End frame. |
| set_playback_rangeC | Set the playback range (green bar in the timeline). Args: start: Start frame. end: End frame. |
| playbar_controlB | Control playback: play, stop, or reverse. Args: action: One of "play", "stop", or "reverse". real_time: Enable or disable real-time playback. fps: Frames per second. |
| list_cachesC | List all cache-type nodes under a root path. Args: ctx: MCP context. root_path: Root path to search from. |
| get_cache_statusA | Frames on disk for a cache node, against the range it is set to write. This is what to poll after a background write_cache: Args: ctx: MCP context. node_path: Path to the cache node. |
| clear_cacheA | Delete cached files on disk for a cache node. Args: ctx: MCP context. node_path: Path to the cache node. frame_range: [start, end] frame range to limit deletion. |
| write_cacheA | Execute a cache node, and report whether a cache actually appeared. Foreground by default: Houdini shows its own progress dialog and the user can cancel. The call holds until the write finishes, however long that is; a client that hands a long call to a background task notifies you with the verdict when it lands. Do nothing else in Houdini meanwhile (every other call queues behind the write) and never poll the disk.
Args: ctx: MCP context. node_path: Path to the cache node. frame_range: [start, end] frame range to render. Overrides the node's $FSTART/$FEND expressions for this and later writes. background: Save from a separate Houdini process (File Cache's own "Save to Disk in Background") so Houdini stays usable, at the cost of the user seeing no progress there. Saves the hip first, returns at once with status "launched"; follow it with get_cache_status. Use it only when asked to keep working while a cache writes. A verified foreground write turns the node's Load from Disk on. |
| get_chop_dataC | Get CHOP node track data. Args: node_path: CHOP node path. channel_name: Specific channel to retrieve. start: Start sample index. end: End sample index. |
| create_chop_nodeA | Create a new CHOP node. Before using this, call list_node_types(context='Chop', filter='') to verify the correct node type. CHOPs has many dedicated nodes for motion and timing — noise, wave, spring, jiggle, lag, limit, filter, math, function, blend, shift, stretch, trim, cycle, speed, constraintlookatat, constraintpath — that may already do what you need. Args: parent_path: Parent network path. chop_type: CHOP node type to create. name: Node name override. |
| list_chop_channelsC | List all channels on a CHOP node. Args: node_path: CHOP node path. |
| export_chop_to_parmC | Export a CHOP channel to a parameter via a chop() expression. Args: chop_path: CHOP node path. channel_name: Channel to export. target_node_path: Target node path. target_parm_name: Parameter to receive the export. |
| execute_pythonA | Execute arbitrary Python code inside Houdini. LAST RESORT only. DO NOT use this to:
ONLY use this when no dedicated tool exists for the operation — i.e. hou.* API calls or Python-level state that no other tool exposes. The justification parameter is mandatory: name the dedicated tools you considered and why none covers this operation. Args: code: Python source code to execute. justification: Which dedicated tools you considered and why none covers this operation. return_expression: Python expression to evaluate after execution. |
| execute_hscriptC | Execute an HScript command in Houdini. Args: command: HScript command string to execute. |
| evaluate_expressionB | Evaluate an expression in Houdini and return its result. Args: expression: Expression string to evaluate. language: Expression language, "hscript" or "python". |
| get_env_variableB | Get a Houdini environment variable value. Args: var_name: Name of the environment variable. |
| get_file_referencesC | Every file path the scene references, with the parameter holding it and whether it exists. Args: ctx: MCP context. include_missing_only: Only report paths that are missing on disk. |
| set_update_modeA | Set Houdini's cook update mode, or read it when called with no mode. "manual" before a long build stops every parameter change from re-cooking; set "auto" back afterwards. Args: ctx: MCP context. mode: "auto", "on_mouse_up" or "manual". Omit to read. |
| get_network_overviewA | Get a compact overview of a network. Keep Args: path: Network path. depth: Recursion depth (default 2, keep ≤ 3). |
| get_cook_chainC | Trace the cook dependency chain for a node. Args: node_path: Node path. |
| explain_nodeC | Explain a node in human-readable form. Args: node_path: Node path. |
| get_selectionB | Get the current node selection. |
| set_selectionC | Set the node selection. Args: node_paths: Node paths to select. |
| get_scene_summaryB | Get a high-level summary of the scene. |
| compare_snapshotsC | Take or compare scene state snapshots. Args: action: "take" or "compare". snapshot_name: Snapshot name. |
| get_node_errors_detailedB | Get detailed error analysis for nodes. Args: node_path: Node to analyze, or scan from root_path if omitted. root_path: Root path to scan. |
| get_cop_infoC | Get information about a COP node. Args: node_path: Path to the COP node. |
| get_cop_geometryC | Get geometry representation from a COP node. Args: node_path: Path to the COP node. output_index: Output connector index. |
| get_cop_layerC | Get image layer data from a COP node. Args: node_path: Path to the COP node. output_index: Output connector index. |
| create_cop_nodeA | Create a COP node in the specified network. Before using this, call list_node_types(context='Cop', filter='') for Copernicus nodes (Houdini 20+), or context='Cop2' for legacy COPs. Copernicus is the modern image processing system and is preferred over COP2 (deprecated as of Houdini 20.5). COPs has many dedicated image-processing nodes — blur, sharpen, levels, contrast, over, multiply, luminance, premultiply, channelcopy, noise, ramp, fractalnoise, worleynoise, rasterizegeo, heighttonormal, sdfshape — that may cover the operation without needing a VEX COP or Python. Args: parent_path: Path to the parent COP network. cop_type: COP node type to create. name: Override node name. |
| set_cop_flagsB | Set flags on a COP node. Args: node_path: Path to the COP node. display: Display flag state. export_flag: Render/export flag state. compress: Compress flag state. |
| list_cop_node_typesA | List available COP node types. Args: filter: Substring filter for node type names. |
| get_cop_vdbB | Get VDB volumetric data from a COP node. Args: node_path: Path to the COP node. output_index: Output connector index. |
| get_simulation_infoC | Get DOP network simulation state. Args: node_path: DOP network node path. |
| list_dop_objectsB | List all DOP objects in a simulation. Args: node_path: DOP network node path. |
| get_dop_objectC | Get detailed data for a specific DOP object. Args: node_path: DOP network node path. object_name: DOP object name. |
| get_dop_fieldC | Read a specific field value from a DOP record. Args: node_path: DOP network node path. object_name: DOP object name. data_path: Dot-separated subdata path (e.g. "Geometry", "Forces/Gravity"). field_name: Field name to read. |
| get_dop_relationshipsC | List all relationships between DOP objects. Args: node_path: DOP network node path. |
| step_simulationB | Advance the simulation by a number of frames. Args: node_path: DOP network node path. steps: Number of frames to advance. |
| reset_simulationC | Reset the simulation to its initial state. Args: node_path: DOP network node path. |
| get_sim_memory_usageC | Get detailed memory breakdown for the simulation. Args: node_path: DOP network node path. |
| get_geometry_infoC | Get geometry summary for a SOP node. Args: node_path: Node path. output_index: Which output to read, for nodes with several (FLIP compress, Vellum solver, whitewater source): 0 is the first. |
| get_pointsB | Read point positions and attributes with pagination. Args: node_path: Node path. attributes: Attribute names to read. start: Start index. count: Max points per page. group: Point group filter. |
| get_primsC | Read primitive data and attributes with pagination. Args: node_path: Node path. attributes: Attribute names to read. start: Start index. count: Max prims per page. group: Prim group filter. |
| get_attrib_valuesA | Read attribute values as a flat array with pagination. For spot-checking a few values prefer sample_geometry — it returns a representative spread of points with all their attributes in one call. Use get_attrib_values when you need a specific slice of one attribute. Values are element-major: for a float3 attribute every 3 consecutive values belong to one element. Check has_more and increment start to read subsequent pages. Args: node_path: Node path. attrib_name: Attribute name. attrib_class: "point", "prim", "vertex", or "detail". start: First element index to return. count: Max elements per page (default 200). |
| set_detail_attribA | Set a detail attribute on a SOP node. Appends an Attribute Create SOP after the node and moves the display flag to it; the result includes the new node's path. Args: node_path: Node path. attrib_name: Attribute name. value: Value to set. |
| get_groupsB | List all geometry groups on a SOP node. Args: node_path: Node path. |
| get_group_membersA | Get element indices in a geometry group, with pagination. Check has_more and increment start to read subsequent pages. Args: node_path: Node path. group_name: Group name. group_type: "point", "prim", or "edge". start: First element index to return. count: Max elements per page (default 5 000). |
| get_bounding_boxC | Get the bounding box of a SOP node's geometry. Args: node_path: Node path. |
| get_attribute_infoC | Get metadata for a geometry attribute. Args: node_path: Node path. attrib_name: Attribute name. attrib_class: "point", "prim", "vertex", or "detail". |
| sample_geometryC | Sample evenly distributed points from a SOP node's geometry. Args: node_path: Node path. sample_count: Number of points to sample. seed: Random seed. |
| get_prim_intrinsicsC | Get intrinsic values for primitives. Args: node_path: Node path. prim_index: Primitive index, or None for a summary. |
| find_nearest_pointC | Find the nearest point(s) to a given position. Args: node_path: Node path. position: Query position as [x, y, z]. max_results: Max nearest points to return. |
| get_attrib_statsA | Aggregate statistics for numeric attributes: min, max, mean, sum. Use this to prove something is happening, rather than reading values. get_geometry_info names the attributes; get_attrib_values returns every value, which on a 60k-point cache tells you nothing you can read. Vector attributes also report per-component ranges, so a velocity field's per-axis extremes come back in the same call. Args: node_path: SOP node path. attribs: Attribute names. Omit for every attribute of the class. attrib_class: "point", "prim" or "detail". |
| get_volume_infoA | Per-volume name, resolution, active voxel count and value range. A primitive count cannot tell a correctly named non-empty density field from an empty one, which is the question worth asking before wiring a solver's sourcing. This is the SOP counterpart of get_cop_vdb. Args: node_path: SOP node path holding volume or VDB primitives. max_volumes: Cap on volumes reported. |
| build_networkA | Build a whole node network in ONE atomic call — the PREFERRED way to construct anything of 3+ nodes (massively faster than node-by-node calls, and either the whole network builds or nothing does). Every node type, parameter name, and input reference is validated against the running Houdini BEFORE anything is created; errors come back with did-you-mean suggestions. Use dry_run=True to prove a plan when using unfamiliar node types. The result includes cooked evidence: per-node errors and the display node's geometry counts — read them instead of assuming success. Each node spec dict supports: type (required), name, parms (lists set whole parm tuples), inputs (list of source names — earlier spec names, existing children, or absolute paths; or dicts with index or input_name / source / source_output, where input_name is a connector name or label as get_node_card lists them; or {"indirect_input": n} to wire from connector n of the parent subnet itself), flags (display/render/bypass/ template), color [r,g,b], comment. Args: parent_path: Network to build inside (e.g. "/obj/geo1"). nodes: Ordered node specs (see above). dry_run: Validate the whole spec without creating anything. layout: Also lay out the parent network afterwards (default True; honoured only when auto-layout is enabled). The nodes this call creates are always positioned, each relative to its inputs, regardless of this flag; nodes that already existed keep their exact positions, so building into a hand-arranged network is safe. |
| verify_networkA | Inspect every node in a network at once — errors, warnings, flags, and the display node's cooked geometry counts. Call this after building or modifying a network, the way an artist
middle-clicks nodes: if Args: parent_path: Network to verify (e.g. "/obj/geo1"). |
| get_node_cardA | Get the authoritative documentation card for a node type, straight
from the running Houdini: connectors in order ( Use this BEFORE setting parameters on a node type you have not used in this session — never guess parameter names. Unversioned names resolve to the newest version. Args: node_type: Type name (e.g. "scatter", "rbdbulletsolver"). context: Category — "Sop", "Lop", "Vop" (MaterialX and other shader nodes inside a material network), "Dop", "Cop", "Chop", "Top", "Object", "Driver"; also "Cop2", "Shop", "VopNet". parm_filter: Substring filter for the parameter list. include_help: False drops the help text (about 4 KB per card) when only parameter names or connectors are needed. |
| find_expensive_nodesA | Profile cooking and rank the most expensive nodes — how a senior artist finds the slow node instead of guessing. Records a performance-monitor profile while force-cooking the display outputs under root_path. cook_ms is cumulative (parents include their children), so compare siblings to locate the hotspot. Args: root_path: Network to profile (a geo container, or "/" broadly). frame: Optionally jump to this frame before cooking. limit: Max nodes to return. |
| cook_frame_rangeA | Cook a node frame by frame and report what changed on each frame. This is how you advance a sequential solver and how you prove a simulation is doing something. Frames are cooked in order, so a SOP solver, a DOP network or an animated chain all accumulate correctly, and per-frame cook time, errors, counts and attribute aggregates come back in ONE round trip instead of one per frame. Prefer this over set_frame in a loop, and over stepping by hand: a 100-frame check is one call rather than 100. The frame is left where the cook ended, ready to screenshot. Args: node_path: Node to cook; its output is what gets measured. start: First frame. Defaults to the playbar start. end: Last frame, inclusive. Defaults to the playbar end. step: Frame increment. Keep at 1.0 for any solver, since skipping frames gives it a discontinuous time step and invalid results. attribs: Point attributes to aggregate per frame (min/max/mean/sum). volumes: Also report per-volume name, resolution and value range. |
| get_cook_statusA | Whether a node has cooked, how often, and whether it is time dependent. Note the shape of the limitation: every command runs on Houdini's main thread, so a long cook blocks the bridge and cannot be polled while it runs. This answers the after-the-fact question instead -- did it really recook, is it time dependent, did it end in error -- plus whether the hip has unsaved changes. For asynchronous work use a ROP's background execution and get_render_progress. Args: node_path: Node to report on. |
| list_installed_hdasB | List all installed HDA files and their definitions. Args: ctx: MCP context. filter: Substring filter for type names or file paths. |
| get_hda_infoC | Get detailed information about an HDA definition. Args: ctx: MCP context. node_path: Node path. hda_file: HDA file path. type_name: HDA type name. |
| install_hdaB | Install an HDA file into the current session. Args: ctx: MCP context. file_path: HDA file path. force: Force reinstall even if already loaded. |
| uninstall_hdaC | Uninstall an HDA file from the current session. Args: ctx: MCP context. file_path: HDA file path. |
| reload_hdaC | Reload an HDA file from disk. Args: ctx: MCP context. file_path: HDA file path. |
| create_hdaC | Create a new HDA from an existing subnet node. Args: ctx: MCP context. node_path: Subnet node path. hda_file: Destination HDA file path. type_name: Operator type name. label: Human-readable label. version: Version string. |
| update_hdaC | Save the current node contents back to its HDA definition. Args: ctx: MCP context. node_path: Node path. |
| get_hda_sectionsC | List all sections in an HDA definition. Args: ctx: MCP context. node_path: Node path. |
| get_hda_section_contentC | Read the content of a specific section in an HDA definition. Args: ctx: MCP context. node_path: Node path. section_name: Section name. |
| set_hda_section_contentC | Write content to a specific section in an HDA definition. Args: ctx: MCP context. node_path: Node path. section_name: Section name. content: Section content. |
| list_hda_versionsB | Every installed definition of an HDA node's type: version, file, which is current. Args: ctx: MCP context. node_path: An HDA instance. |
| set_hda_interfaceA | Author an HDA's Type Properties interface in one call. Use this for the asset's TYPE interface — tab folders, strict ranges,
ordered menus, Hide/Disable When. Each entry of Example — a Controls tab whose Bevel disappears for a single stud: [{"name": "controls", "label": "Controls", "type": "folder", "children": [ {"name": "stud_count", "type": "int", "default": 4, "min": 1, "max": 8, "min_strict": True, "max_strict": True}, {"name": "bevel", "type": "float", "default": 0.02, "min": 0.0, "max": 0.1, "hide_when": "{ stud_count == 1 }"}, {"name": "material", "type": "menu", "menu_items": [["plastic", "Plastic"], ["metal", "Metal"]]}]}] It is edit_hda_interface with one insert per entry: names already in the
interface are refused before anything is written, and the reply is read
back off the definition — Args:
ctx: MCP context.
node_path: An instance of the HDA whose definition is edited.
parameters: Interface spec (see above). create_spare_parameters'
spelling (parm_name, parm_type, default_value) is accepted too.
replace: Start from an empty interface. Built-in parameters of the node
type cannot be removed: Houdini puts them back
( |
| edit_hda_interfaceA | Edit an HDA's EXISTING Type Properties interface in one atomic call: insert at a position, remove, hide/show, replace, modify, move. set_hda_interface only appends. Every op here works on the definition's parameter group; all ops are applied to a copy, the result is checked for component-name collisions, and it is written once — a failing op changes nothing. Read the interface first with get_parm_template_tree. Ops (dicts, applied in order): {"op": "insert", "spec": {...}, "after": name | "before": name | "in_folder": label or [labels]} — omit the position to append. spec is a set_hda_interface spec, plus types button (with "callback", Python by default), separator, label, vector, color, file, oppath; and fields naming_scheme (base1|xyzw|rgba|minmax| startend|uvw), default_expression, hidden, join_with_next, callback, tags; folder_type "multiparm" for a multiparm block (children named "item#"). {"op": "remove", "name": name_or_folder_label} {"op": "hide" | "show", "name": ...} {"op": "replace", "name": ..., "spec": {...}} {"op": "modify", "name": ..., <label | help | default | default_expression | min | max | min_strict | max_strict | hide_when | disable_when ("" clears) | hidden | join_with_next | menu_items | callback | naming_scheme | new_name | tags>} ("rename", "set_conditional", "set_default" are aliases) {"op": "move", "name": ..., "after" | "before" | "in_folder": ...} Names are template names ( Args: ctx: MCP context. node_path: An instance of the HDA whose definition is edited. ops: Operations, in order. dry_run: Validate and report the plan without writing. |
| search_helpA | Search the running Houdini's own documentation — concepts, workflows, VEX functions, expression functions, HOM API, and every effects manual SideFX ships. Version-exact, straight from the install. Use this BEFORE improvising: when unsure how a workflow is meant to be done ("pyro shaping", "vellum constraints"), what a VEX or expression function does, or what a Solaris/TOPs concept means. Follow up with get_help_page on a result path. Args: query: Search words (all must match a page). scope: Optional corpus, named after the archive. Every help archive in the install is searchable, which on a full 22.0 is 47 of them. The ones worth knowing by name: "nodes", "vex", "expressions", "hom", "solaris", "tops", plus the workflow manuals "pyro", "fluid", "vellum", "destruction", "grains", "crowds", "model", "copy", "assets", "render", "shade", "anim", "character", "ref", "shelf". Omit to search all. limit: Max results. |
| get_help_pageA | Fetch one page of Houdini's shipped documentation by path. Read the real reference instead of writing from memory — especially the VEX function pages (vex/functions/...) before any justified wrangle, and expression pages (expressions/...) before channel expressions. Args: path: As returned by search_help — e.g. "nodes/sop/scatter", "vex/functions/noise", "expressions/ch". |
| get_workflow_guideA | The server's written guide for a subject: what to build, in what order, which mistakes it exists to prevent, and the shipped help pages to read. Call this BEFORE designing a setup you have not built this session, and again the moment two attempts at the same symptom have failed. Each guide is distilled from that subject's SideFX manual. Args: topic: Help scope name or common alias: pyro, fluid (flip, water, whitewater), vellum (cloth), destruction (rbd), mpm (sand, snow), ocean, solaris, tops, model, copy, render, shade, character, crowds, heightfields, copernicus, assets, troubleshooting, dyno. description: What you are trying to build, for the guide's framing. |
| get_stage_infoC | Get USD stage info from a LOP node. Args: node_path: LOP node path. |
| get_usd_primA | Get detailed info about a USD prim. Array attributes longer than 16 elements (points, faceVertexIndices,
primvars:st, ...) come back as a summary: size, element_type, the first 8
as Args: node_path: LOP node path. prim_path: USD prim path. full: Return array attributes in full instead of summarised. |
| list_usd_primsB | List USD prims on a stage with filtering. Args: node_path: LOP node path. root_path: Root prim path to list from. prim_type: USD type filter (e.g. "Mesh", "Xform"). kind: Kind filter (e.g. "component", "group"). depth: Max traversal depth. |
| get_usd_attributeA | Read a USD attribute value from a prim. A long array (over 16 elements) answers with Args:
node_path: LOP node path.
prim_path: USD prim path.
attr_name: Attribute name.
time: Time code (frame number).
full: Return the whole array as |
| get_usd_layersC | List all layers in a USD stage. Args: node_path: LOP node path. |
| get_usd_prim_statsB | Get prim counts by USD type under a root path. Args: node_path: LOP node path. prim_path: Root prim path to gather stats from. |
| get_last_modified_primsC | Get prims modified by the last LOP node cook. Args: node_path: LOP node path. |
| create_lop_nodeA | Create a new LOP node. Before using this, call list_node_types(context='Lop', filter='') to verify the correct node type. Solaris ships many specialized LOPs — sublayer, reference, materiallibrary, assignmaterial, karmarendersettings, editproperties, xform, prune, configurelayer, collection, addvariant — that may not be obvious from their names. Args: parent_path: Parent node path. lop_type: LOP node type (e.g. "sphere", "sublayer", "merge"). name: Node name. prim_path: USD prim path to set on the node. |
| set_usd_attributeB | Set a USD attribute value via an inline Python LOP. Args: node_path: LOP node path to connect after. prim_path: USD prim path. attr_name: Attribute name. value: Value to set. |
| get_usd_bound_materialA | The material each prim renders with, resolved the way the renderer
resolves it (ComputeBoundMaterials), and where the binding comes from:
Batched: pass every prim of interest in one call. Args: node_path: LOP node whose stage to read. prim_paths: Prim paths to resolve. purpose: "full" (default; what Karma renders, falling back to an all-purpose binding), "preview", or "all" (all-purpose bindings only). |
| get_usd_materialsA | List all USD materials on a stage. Each material reports surface_shaders keyed by render context: "surface" is the universal output, a UsdPreviewSurface for viewports and Storm, and "mtlx" is the MaterialX shader Karma renders. surface_shader is the mtlx one when present, so it agrees with get_material_info on the same material.
Args: node_path: LOP node path. |
| find_usd_primsB | Search USD prims by path pattern. Args: node_path: LOP node path. pattern: Glob pattern (supports *, **) or substring. |
| get_usd_compositionC | Get composition arcs for a USD prim. Args: node_path: LOP node path. prim_path: USD prim path. |
| get_usd_variantsA | Get variant sets and selections for a USD prim. Args: node_path: LOP node path. prim_path: USD prim path. |
| inspect_usd_layerC | Inspect a USD layer by index. Args: node_path: LOP node path. layer_index: Layer index (0 = root layer). |
| create_lightB | Create a USD light in a LOP network. Args: parent_path: Parent LOP network path. light_type: "dome", "distant", "rect", "sphere", "disk", or "cylinder". name: Light node name. intensity: Light intensity. color: [r, g, b] color values. position: [x, y, z] world position. |
| list_lightsC | List all USD lights on a LOP stage. Args: node_path: LOP node path. |
| set_light_propertiesC | Set properties on a USD light prim via an inline Python LOP. Args: node_path: LOP node path to connect after. prim_path: USD light prim path. properties: Property name-value pairs to set. |
| create_light_rigA | Create a preset lighting rig in a LOP network. Args: parent_path: Parent LOP network path. preset: "three_point", "studio", "outdoor", or "hdri". intensity_mult: Multiplier for all light intensities. |
| list_materialsC | List all material nodes under a root path. Args: ctx: MCP context. root_path: Root path to search for materials. |
| get_material_infoA | Get detailed information about a material node. assignments lists the nodes under /obj and /stage whose material-path parameters name this material; only those parameters are read, so the call costs the same on a 4,000-node scene as on an empty one (assignment_scan reports how many nodes were visited). Args: ctx: MCP context. node_path: Absolute path to the material node. |
| create_material_networkA | Create a new material network in /mat. The keys base_color ([r, g, b]), roughness, metalness and opacity are accepted on both shader types and mapped to the shader's own parameter names (base_colorr/g/b and specular_roughness on MaterialX, basecolor, rough, metallic and opac on Principled). Any other key must be the shader's real parameter name; a list sets the whole parm tuple. The reply lists what was applied and, under "skipped", every key that matched no parameter, with the reason. Args: ctx: MCP context. name: Name for the new material node. shader_type: "principled" (principledshader::2.0), "materialx" (mtlxstandard_surface), or any material node type name. params: Parameter name-value pairs to set on the shader. |
| list_material_typesA | List available VOP/material node types. Args: ctx: MCP context. filter: Substring to filter type names and labels by. |
| create_nodeA | Create a node inside a parent network. Before using this, call list_node_types(context='', filter='') to verify a dedicated node exists for the operation. Houdini has thousands of nodes — many common operations (boolean, scatter, copy to points, fracture, ocean, hair, vellum, pyro, etc.) have dedicated nodes that are better than writing VEX or Python. Args: ctx: MCP context. parent_path: Parent network path. node_type: Node type (e.g. 'geo', 'box', 'grid'). name: Node name. position: [x, y] network editor position. |
| delete_nodeC | Delete a node. Args: ctx: MCP context. node_path: Node path. |
| rename_nodeC | Rename a node. Args: ctx: MCP context. node_path: Node path. new_name: New node name. |
| copy_nodeC | Copy a node, optionally into a different parent network. Args: ctx: MCP context. node_path: Source node path. dest_parent: Destination parent path. new_name: Name for the copy. |
| move_nodeC | Move a node to a different parent network. Args: ctx: MCP context. node_path: Node path. dest_parent: Destination parent path. |
| get_node_infoA | Get type, connections, flags, errors, cook time, and non-default parameters for a node. Returns only parameters that differ from their defaults (non_default_parameters) plus a total_param_count. Use get_parameter_schema to inspect the full parameter list. Args: ctx: MCP context. node_path: Node path. |
| list_childrenA | List children of a network node. Avoid Args: ctx: MCP context. parent_path: Parent network path. recursive: Include all descendants (use sparingly on large scenes). filter_type: Node type filter (e.g. 'box', 'merge'). |
| find_nodesA | Search for nodes by name pattern, type, or context. Narrow the search: use Args: ctx: MCP context. pattern: Glob pattern for node names (e.g. 'box*'). node_type: Node type filter (e.g. 'box', 'null'). context: Category filter (e.g. 'Sop', 'Object'). inside: Root path to search within (default '/'). |
| list_node_typesA | List available node types for a context category. IMPORTANT: Any context can have hundreds of node types (SOPs alone can
exceed 800 in a production install). Always pass a Args: ctx: MCP context. context: Category name (e.g. 'Sop', 'Lop', 'Dop', 'Top', 'Cop2'). filter: Substring to filter type name or label (case-insensitive). limit: Max entries to return (default 200, max recommended 200). |
| change_node_typeA | Change a node's type in place, keeping wires, name, position, flags, parameter values and (for subnets/assets) network contents. This is how an HDA instance is moved to an installed newer version
( Args: node_path: Node to change. new_type: Type name in the node's own category. keep_name: Keep the node's name. keep_parms: Carry parameter values over by name. keep_network_contents: Keep a subnet's/asset's children (False resets an asset to its definition's contents, also on a node that is already of new_type). |
| press_buttonA | Press a button parameter — "Stash Input", "Reload Geometry", an asset's own Build button — and read the node's errors and warnings afterwards. The call holds until the callback returns, with no deadline. A callback that opens a dialog blocks Houdini's main thread and this bridge with it; read the button's script first if in doubt. For a Save to Disk or a render use write_cache / start_render, which report a verdict. A press usually only dirties the node, so Args: node_path: Node that owns the button. parm_name: The button parameter's name. arguments: Optional kwargs handed to the callback script; values must be int, bool, float or str. cook: Cook the node after the press so errors describe the result. |
| connect_nodesA | Connect two nodes together. To feed a node INSIDE a subnet from one of the subnet's own input connectors (a SubnetIndirectInput — not a node, it has no path), pass the subnet as source_path and the connector index as indirect_input. Args: ctx: MCP context. source_path: Upstream node path; with indirect_input, the subnet whose input connector is the source. dest_path: Downstream node path. output_index: Source output index. input_index: Destination input index. input_name: Destination connector name or label (e.g. "base_color" on a VOP shader); wins over input_index. indirect_input: Index of the subnet input connector at source_path to wire from (dest_path must live inside that subnet). |
| connect_nodes_batchA | Connect multiple node pairs in a single call. Args: connections: List of connections. Each dict has keys: source_path (str), dest_path (str), output_index (int, default 0), input_index (int, default 0), input_name (str, optional: connector name or label, wins over input_index), indirect_input (int, optional: source_path is then a subnet and this is the index of its input connector to wire from — for the first node of a chain built inside that subnet). |
| disconnect_nodeC | Disconnect one or all inputs of a node. Args: ctx: MCP context. node_path: Node path. input_index: Input index to disconnect. disconnect_all: Disconnect all inputs. |
| reorder_inputsB | Reorder the input connections of a node. Args: ctx: MCP context. node_path: Node path. new_order: New input ordering (e.g. [1, 0] swaps first two). |
| set_node_flagsC | Set flags on a node. Args: ctx: MCP context. node_path: Node path. display: Display flag. render: Render flag. bypass: Bypass flag. template: Template flag. lock: Lock flag. |
| layout_childrenA | Auto-layout children of a network node. Does nothing when auto-layout is disabled via FXHOUDINIMCP_AUTO_LAYOUT=0. Args: ctx: MCP context. parent_path: Parent network path. spacing: Spacing multiplier between nodes. |
| set_node_positionC | Set a node's position in the network editor. Args: ctx: MCP context. node_path: Node path. x: Horizontal position. y: Vertical position. |
| set_node_colorB | Set a node's color in the network editor. Args: ctx: MCP context. node_path: Node path. r: Red (0.0-1.0). g: Green (0.0-1.0). b: Blue (0.0-1.0). |
| create_network_boxA | Draw a titled network box around nodes, to document a graph you built. Args: ctx: MCP context. parent_path: Network the box lives in. node_paths: Sibling nodes to enclose; the box fits around them. comment: Title shown on the box. color: RGB in 0..1. |
| create_sticky_noteA | Leave a sticky note in a network. Args: ctx: MCP context. parent_path: Network the note lives in. text: Note text. position: [x, y] in network editor units. size: [width, height] in network editor units. color: RGB in 0..1. |
| set_object_transformA | Set an object's translate, rotate, scale and/or parent in one call. Only the arguments you pass change. Object-level nodes under /obj only; SOP transforms are a Transform SOP, not this. Args: ctx: MCP context. node_path: Object node, e.g. "/obj/geo1". translate: [tx, ty, tz]. rotate: [rx, ry, rz] in degrees. scale: [sx, sy, sz]. parent: Object to parent under, or "" to unparent. |
| get_parameterC | Get the value and metadata of a parameter. Args: node_path: Node path. parm_name: Parameter name. |
| set_parameterC | Set a parameter value. Args: node_path: Node path. parm_name: Parameter name. value: New value (int, float, string, bool, or list). |
| set_parametersB | Batch-set multiple parameters on a node. Args: node_path: Node path. params: Mapping of parameter names to values. |
| get_parameter_schemaA | Get the template schema for parameter(s) on a node. Most nodes have dozens of parameters; many have 100+. Always use
Args: node_path: Node path. parm_name: Exact parameter name for a single-parameter lookup. filter: Substring to match against parameter name or label (case-insensitive). Use instead of dumping all params. |
| get_parm_referencesB | Who references a parameter, and what it references — in one call.
Args: node_path: Node to inspect. parm_name: One parameter instead of all of them. direction: "both", "incoming" or "outgoing". limit: Cap on reported entries. |
| get_parm_template_treeA | The whole parameter interface as a tree, the way Type Properties shows
it: folders (with folder_type — tabs, collapsible, multiparm), every
parameter in order with defaults, default expressions, ranges, menu
items, Hide/Disable When conditionals, callbacks, naming scheme; a
multiparm's get_hda_info shows only the top folders and get_parameter_schema flattens the structure away; read this before editing an interface. Give node_path for a node (its instance interface, spares included) or type_name + context for a type. Args: node_path: Node whose interface to read. type_name: Node type instead (with context). context: Category of type_name — "Sop", "Object", "Lop", ... folder: Narrow to one folder by label, or a list of nested labels. max_entries: Cap on entries (depth-first); the reply says when it cut. |
| set_expressionC | Set an expression on a parameter. Args: node_path: Node path. parm_name: Parameter name. expression: Expression string. language: "hscript" (default) or "python". |
| get_expressionC | Get the expression on a parameter. Args: node_path: Node path. parm_name: Parameter name. |
| revert_parameterB | Revert a parameter to its default value. Args: node_path: Node path. parm_name: Parameter name. |
| link_parametersA | Create a channel reference from one parameter to another. The destination gets an HScript expression that reads the source as its own type: chs() for a String parameter, ch() for numbers, toggles and menus. The path is relative to the destination node (chs("../CTRL/mat")), so the link survives moving the pair, collapsing into a subnet or instancing an HDA. The reply carries the expression, the function used and the destination's evaluated value. Args: source_path: Source node path. source_parm: Source parameter name. dest_path: Destination node path. dest_parm: Destination parameter name. |
| lock_parameterA | Lock or unlock a parameter. Args: node_path: Node path. parm_name: Parameter name. locked: True to lock, False to unlock. |
| create_spare_parameterB | Add a spare parameter to a node. Args: node_path: Node path. parm_name: Internal parameter name. parm_type: "float", "int", "string", "toggle", or "menu". label: UI label. default_value: Default value. min_val: Minimum value (float/int only). max_val: Maximum value (float/int only). |
| create_spare_parametersA | Batch-create multiple spare parameters in one call, optionally in a folder tab. Args: node_path: Node path. parameters: List of parameter specs. Each dict has keys: parm_name (str), parm_type (str: "float"/"int"/"string"/"toggle"/"menu"), label (str), default_value (optional), min_val (optional), max_val (optional). folder_name: If provided, wraps all parameters in a named folder tab. folder_type: Folder style: "Tabs", "Collapsible", or "Simple". |
| get_parametersA | Read many parameter values at once, matched by name or label substring. The batch counterpart of set_parameters. Several unrelated groups of settings ("flame", "wind", "buoy") come back in one call instead of one call each, and unlike get_node_card these are the live values on this node rather than the defaults for its type. Args: node_path: Node to read. patterns: Substrings matched against parameter name and label. Omit for everything, up to the cap. include_defaults: Also report whether each value is still the default. |
| render_viewportA | Capture the current 3D viewport to an image file. Args: output_path: Image file path. resolution: [width, height] in pixels. camera: Camera node path. settle_seconds: Wait this long before capturing, without blocking Houdini, so a Karma viewport can converge after a change. Use this instead of a shell sleep between calls. Capped at 120. |
| render_quad_viewA | Capture all four viewport panes to separate images. Args: output_path: Base image path; viewport names are appended. resolution: [width, height] in pixels. |
| list_render_nodesA | List all render (ROP/Driver) nodes in the scene. |
| get_render_settingsA | Get render settings from a ROP node. Args: node_path: ROP node path. |
| set_render_settingsB | Set render parameters on a ROP node. Args: node_path: ROP node path. settings: Parameter name-value pairs. |
| create_render_nodeB | Create a new render (ROP) node in /out. Args: renderer: Renderer type ('karma', 'opengl', 'mantra', 'rop_geometry', 'rop_alembic', 'usdrender', 'fetch', 'merge', 'rop_fbx', 'rop_gltf'). name: Node name. camera: Camera node path. output_path: Output file path. |
| start_renderA | Execute any node that renders or writes files. Foreground by default: Houdini shows its own progress dialog and the user can cancel. The call holds until the render finishes, however long that is; a client that hands a long call to a background task notifies you with the verdict. Do nothing else in Houdini meanwhile and never poll the disk. Not just /out ROPs: a LOP usdrender_rop (which is how Solaris renders), a SOP ROP Geometry, or a File Cache's Save to Disk all work, because what matters is whether the node can be executed rather than its category. The result reports the output path it wrote to and whether anything is actually on disk there, so a render that succeeds and writes nowhere is visible instead of silent. Args: node_path: Any node with a render() or an 'execute' button. frame_range: [start, end] or [start, end, increment]. background: Render in a separate hython on the saved hip and return at once with status "launched"; get_render_progress reports the process, its log tail and the files. The user sees no progress in Houdini, so use it only when asked to keep working while a render runs. |
| render_node_networkA | Capture a screenshot of a node's network editor view. Args: node_path: Node path to focus on. output_path: Image file path. |
| get_render_progressA | Progress of a render or write started with start_render. Accepts every node start_render accepts (a LOP usdrender_rop or Karma
LOP, a SOP ROP, a File Cache), not only /out ROPs. Reports the node's
errors with Args: node_path: The node given to start_render. |
| get_houdini_connection_statusA | Check the Codex-to-Houdini bridge without raising on disconnect. Returns structured connection diagnostics, including the configured bridge URL and Houdini health payload when reachable. Use this before live viewport workflows when Houdini may have restarted or its hwebserver may not be running. |
| get_scene_infoB | Get information about the current Houdini scene. |
| new_sceneA | Create a new empty Houdini scene. Args: save_current: Save the current scene before clearing. |
| save_sceneB | Save the current Houdini scene to disk. Args: file_path: Destination path; defaults to the current hip file. |
| load_sceneA | Open a Houdini hip file, or merge it — or named nodes from it — into the current scene. Load warnings (missing assets and the like) come back in Args: file_path: Path to the hip file to open. merge: Merge into the current scene instead of replacing it. node_paths: With merge, the absolute node paths to merge; default everything. overwrite_on_conflict: With merge, overwrite same-named nodes instead of renaming the merged copy. |
| import_fileB | Import a geometry, USD, or Alembic file into the scene. Args: file_path: Path to the file to import. parent_path: Network path for the import node. node_name: Name for the created node. |
| export_fileA | Export a node's output to a file on disk, and report whether it landed. SOPs are saved directly, LOPs export their USD stage, and a /out ROP is
pointed at file_path and executed (its own output path is restored
afterwards). Reports Args: node_path: Path to the node to export. file_path: Destination file path. For a ROP this overrides its output parameter for the duration of the export. frame_range: Frame range as [start, end] or [start, end, step]. |
| get_context_infoC | Get information about a Houdini network context. Args: context: Context path, e.g. "/obj", "/stage", "/out". |
| undoA | Undo the last change(s) made in Houdini. Every tool call is one undo step, however many nodes it touched, so one undo reverses one build_network or set_parameters call. Needs a graphical Houdini: hython keeps no undo history. Args: ctx: MCP context. steps: How many steps to undo (default 1). |
| redoA | Redo the last undone change(s) in Houdini. Args: ctx: MCP context. steps: How many steps to redo (default 1). |
| list_shelf_toolsA | Find shelf tools by name, label or keyword. Use this when a setup exists as a shelf tool rather than as a node: oceans, quick sims, rigging setups. A full install ships around 8,000 of them, so always filter. Args: filter: Substring matched against name, label and keywords. limit: Maximum tools to return. |
| get_shelf_tool_scriptA | Read the script a shelf tool runs, plus its help and imports. This is how you learn SideFX's own recipe instead of reinventing it. Most scripts are two or three lines calling a worker in a toolutils module, and the reported imports name exactly what to read next. Args: tool_name: Internal tool name, from list_shelf_tools. |
| run_shelf_toolA | Run a shelf tool and report the nodes it created. Tools that wait for a viewport selection or a dialog (the FLIP ocean layer, collide-with, most "select the object then..." tools) are refused up front: through the bridge they would block Houdini until someone clicks. Read the recipe with get_shelf_tool_script and build the nodes with build_network instead. Tools that only create nodes run fine. Args: tool_name: Internal tool name, from list_shelf_tools. kwargs: Overrides merged into the synthetic kwargs the script reads. parent_path: An extra network to watch for new nodes. /obj, /stage, /out, /mat and /img are always watched, because a shelf tool is free to build in more than one of them: largeOcean creates both a geo in /obj and a LOP in /stage. |
| list_takesA | List all takes in the scene with their hierarchy. |
| get_current_takeB | Get the current take and its overridden parameters. |
| set_current_takeB | Set the current take by name. Args: name: Take name to make current. |
| create_takeC | Create a new take, optionally under a parent take. Args: name: Name for the new take. parent_name: Parent take name (defaults to current take). |
| get_top_network_infoC | Get an overview of a TOP network. Args: ctx: MCP context. node_path: TOPnet or TOP node path. |
| cook_top_nodeB | Cook a TOP node to execute its work items. Args: ctx: MCP context. node_path: TOP node path. block: Wait for cooking to complete. generate_only: Only generate work items, do not cook. |
| cancel_top_cookC | Cancel active cooking on a TOP network. Args: ctx: MCP context. node_path: TOP node or TOPnet path. |
| pause_top_cookC | Pause cooking on a TOP network. Args: ctx: MCP context. node_path: TOP node or TOPnet path. |
| dirty_work_itemsA | Dirty work items on a TOP node so they can be regenerated. Args: ctx: MCP context. node_path: TOP node path. remove_outputs: Also remove output files from disk. |
| get_work_item_statesB | Get work item state counts for a TOP node. Args: ctx: MCP context. node_path: TOP node path. |
| get_work_item_infoC | Get detailed information about a specific work item. Args: ctx: MCP context. node_path: TOP node path. work_item_index: Work item index within the node. |
| get_pdg_graphC | Get the PDG dependency graph structure for a TOP network. Args: ctx: MCP context. node_path: TOPnet or TOP node path. |
| generate_static_itemsB | Generate static work items on a TOP node without cooking. Args: ctx: MCP context. node_path: TOP node path. |
| get_top_scheduler_infoC | Get information about TOP scheduler nodes in a network. Args: ctx: MCP context. node_path: TOP scheduler or TOPnet path. |
| get_failed_work_itemsB | List the work items that failed on a TOP node, with the tail of each log. Args: ctx: MCP context. node_path: TOP node path. limit: Maximum items returned. |
| get_top_logsA | Cook logs for a TOP node, or the scheduler log of one work item. Args: ctx: MCP context. node_path: TOP node path. work_item_index: Work item index; omit for the node's own errors and warnings. tail: Maximum characters of log text, taken from the end. |
| create_wrangleA | Create an Attribute Wrangle node with VEX code. LAST RESORT. VEX is for attribute math that no node expresses — NEVER for modeling, scattering, copying, deforming, grouping, or randomizing, which all have dedicated nodes. Building geometry in a wrangle when a native node exists is a failure, not a shortcut. The justification parameter is mandatory: state which list_node_types searches you ran and why none of the results can do this. If you cannot write that sentence honestly, you have not checked — check first. Args: parent_path: Parent SOP network path. vex_code: VEX snippet to set. justification: Which native nodes you checked (the actual list_node_types filters used) and why none can express this logic. run_over: Element to run over ("Points", "Vertices", "Primitives", "Detail", "Numbers"). name: Node name. |
| set_wrangle_codeB | Set VEX code on an existing Attribute Wrangle node. Args: node_path: Path to the wrangle node. vex_code: VEX snippet to set. |
| get_wrangle_codeB | Read the VEX code from an Attribute Wrangle node. Args: node_path: Path to the wrangle node. |
| create_vex_expressionC | Set a VEX expression on a parameter. Args: node_path: Path to the node. parm_name: Parameter name. vex_code: VEX expression code. |
| validate_vexA | Validate VEX code by cooking the node and checking for errors. Args: node_path: Path to the wrangle node. |
| list_panesA | List all visible pane tabs in the Houdini UI. |
| get_viewport_infoC | Get viewport settings for a pane tab. Args: pane_name: Pane tab name. |
| set_viewport_cameraA | Set the viewport to look through a specific camera. Args: camera_path: Camera node path, or a USD camera prim path for a Solaris viewport. The result reports the camera the viewport is actually looking through, and fails if it did not take. pane_name: Pane tab name. |
| set_viewport_displayC | Set the viewport shading mode. Args: display_mode: One of 'wireframe', 'shaded', 'smooth', 'smooth_wire', 'hidden_line', 'flat', 'flat_wire', 'matcap', 'matcap_wire'. pane_name: Pane tab name. |
| set_viewport_rendererA | Set the viewport's Hydra rendering delegate for live preview. Use this during lookdev to preview materials and lighting directly in the viewport instead of writing full renders to disk. Args: renderer: Renderer name. The result reports the delegate that is actually active afterwards, read back from Houdini rather than inferred from a setter not raising. renderer: Renderer name — "GL", "Storm", "Karma CPU", "Karma XPU", etc. Case-insensitive partial match. pane_name: Pane tab name. |
| frame_selectionB | Frame the current selection in the viewport. Args: pane_name: Pane tab name. |
| frame_allC | Frame all geometry in the viewport. Args: pane_name: Pane tab name. |
| set_viewport_directionA | Set the viewport to a standard viewing direction. Args: direction: "front", "back", "top", "bottom", "left", "right", or "perspective". pane_name: Pane tab name. |
| capture_screenshotA | Capture a screenshot of the viewport or a specific pane tab. The image is written to disk only; open Args: output_path: Image file path. pane_name: Pane tab name. settle_seconds: Wait this long before capturing, without blocking Houdini, so a Karma viewport can converge after a change. Use this instead of a shell sleep between calls. Capped at 120. |
| capture_network_editorA | Capture a screenshot of the network editor. The image is written to disk only; open Args: output_path: Image file path. node_path: Node path to navigate to before capture. |
| set_current_networkC | Navigate the network editor to a specific network path. Args: network_path: Network path to navigate to. |
| find_error_nodesC | Find all nodes with errors or warnings in the scene. Args: root_path: Root node path to search from. |
| log_statusA | Display a status message in Houdini's status bar. Call this at the START of every major step so the user can follow along in real time without having to inspect tool call logs. Examples: "Creating base geometry...", "Wiring SOP chain...", "Setting up pyro simulation...", "Assigning materials...". Args: message: Status message to display (keep it short and human-readable). severity: "message" (default), "important", "warning", or "error". |
| set_viewer_contextA | Point the Scene Viewer at a network, and optionally a node inside it. set_current_network moves the network EDITOR; this moves the VIEWER. That is what decides whether a scene graph view exists, so it is the prerequisite for previewing a USD stage or setting a Hydra delegate: call this with "/stage" before set_viewport_renderer or before binding a USD camera prim. The result reports is_scene_graph_view, which is the question you are usually really asking. Args: network_path: Network for the viewer to display, e.g. "/stage". current_node: Node inside it to make current, which selects the stage a Solaris viewport shows. pane_name: Pane tab name. |
| setup_pyro_simA | Build a Pyro smoke/fire simulation network from source geometry. Preferred over manual DOP wiring — builds the entire pyro network in one call. For custom setups beyond what this provides, use create_node with DOP nodes (pyrosolver, smokeobject, volumesource, etc.). Args: source_geo: Source SOP path. container: Container type. res_scale: Resolution scale multiplier. substeps: DOP substeps. name: Top-level geo node name. |
| setup_rbd_simA | Build an RBD rigid-body simulation network with fracture and solver. Preferred over manual DOP wiring — builds the entire RBD network in one call. For source geometry, build SOP chains with native nodes (voronoifracture, booleanfracture, rbdmaterialfracture) instead of VEX. Args: geo_path: Source geometry object path. ground: Add a ground plane. pieces_type: Fracture method ("voronoi"). name: Top-level geo node name. |
| setup_flip_simA | Build a FLIP fluid simulation network from source geometry. Preferred over manual DOP wiring — builds the entire FLIP network in one call. Use FLIP Source SOP or Volume Source DOP for custom sourcing. Args: source_geo: Source SOP path. domain: Domain type. particle_sep: Particle separation distance. name: Top-level geo node name. |
| setup_vellum_simA | Build a Vellum simulation network with configure node and solver. Preferred over manual DOP wiring — builds the entire Vellum network in one call. Use Vellum Drape SOP to let cloth settle before the main simulation. Args: geo_path: Source geometry object path. sim_type: Simulation type ("cloth", "hair", "grain", "softbody"). substeps: Solver substeps. name: Top-level geo node name. |
| create_materialA | Create a material in /mat with configurable surface properties. Args: name: Material node name. mat_type: Material type ("principled", "materialx"). base_color: [R, G, B] base color, 0-1 per channel. roughness: Surface roughness, 0-1. metallic: Metallic factor, 0-1. opacity: Opacity, 0-1. |
| assign_materialC | Assign a material to a geometry node via a Material SOP. Args: geo_path: Target geometry node path. material_path: Material to assign. |
| build_sop_chainA | Build a sequential chain of SOP nodes wired together in a single call. PREFERRED over individual create_node calls for linear SOP chains — builds and wires the entire chain in one round-trip, which is significantly faster. Each step dict: {"type": str, "name": str (optional), "params": dict (optional)}. Nodes are created in order and each is automatically connected to the previous. Example: steps=[ {"type": "box"}, {"type": "polybevel", "params": {"offset": 0.05}}, {"type": "scatter", "params": {"npts": 200}}, {"type": "copy_to_points", "name": "copy1"}, ] Args: parent_path: Parent SOP network path. steps: List of step dicts defining the chain. |
| setup_renderA | Set up a render configuration with camera and ROP node. Args: renderer: Renderer type ("karma", "mantra"). camera: Camera node path; creates one if omitted. output_path: Output image path (supports Houdini variables). resolution: [width, height] resolution. samples: Render sample count. name: ROP node name in /out. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| procedural_modeling_workflow | Guide for building a procedural modeling network in SOPs. Args: description: What geometry to create (e.g. "a rocky terrain with scattered trees") output_context: Where to create the geo container |
| usd_scene_assembly | Guide for building a USD scene in Houdini's LOPs/Solaris. Args: scene_description: Description of the USD scene to build |
| simulation_setup | Guide for setting up a dynamics simulation. Dispatches to the solver-specific guide when one exists, because a single generic file had to cover pyro, FLIP, Vellum, RBD and MPM at once and so could not say more than a table row about any of them. Houdini ships a separate manual per solver, and these files mirror that split. Anything without its own guide falls back to dyno.md, the general dynamics one. Args: sim_type: Type of simulation (pyro, flip, rbd, vellum, mpm, pop) description: Additional context about the simulation |
| pdg_pipeline | Guide for building a PDG/TOPs pipeline. Args: task_description: What the pipeline should accomplish |
| hda_development | Guide for creating a Houdini Digital Asset. Args: asset_description: What the HDA should do context: Node context for the HDA (Sop, Lop, Object, etc.) |
| copernicus_workflow | Guide for image work in Copernicus (COPs). Args: description: What to build (e.g. "a tileable rust texture") |
| heightfield_terrain | Guide for building terrain with heightfields. Args: description: The terrain to build (e.g. "an eroded desert mesa") |
| houdini_workflow | Guide for any Houdini subject the shipped manual documents. One entry point rather than a function per subject, so a new corpus needs a markdown file and nothing else. `topic` is the SideFX help scope name, which is also the markdown filename: character, render, shade, crowds, copy, props, dopparticles, io, anim, ocean, grains, muscles, finiteelements, feathers, fur, ml, composite, heightfields_cop, plus every subject that has its own named prompt (pyro, fluid, vellum, destruction, mpm, solaris, tops, model, assets, copernicus, heightfields, dyno, troubleshooting). Args: topic: Help scope name for the subject, e.g. "character" or "render" description: What you are trying to build |
| debug_scene | Systematic approach to debugging a Houdini scene. Args: problem_description: What problem the user is experiencing |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| scene_info | Current Houdini scene information including hip file, version, frame range, and node counts. |
| scene_tree | Top-level node tree of the current scene. |
| scene_errors | All nodes with errors or warnings in the scene. |
| installed_hdas | List of installed Houdini Digital Assets. |
TDQS
Scored across 206 tools
With 206 tools, many clusters have unclear boundaries: get_scene_summary/get_scene_info/get_network_overview, create_material/create_material_network, capture_screenshot/render_viewport, and the various get_cop_*/get_work_item_* tools all overlap in purpose. Individual descriptions help, but an agent will frequently have difficulty choosing the correct tool from these near-synonymous groups.
Most tools follow a clear get_/set_/create_/list_ verb_noun snake_case pattern, but there are notable deviations like playbar_control, undo, and redo. The list/get prefix is also used inconsistently for collection reads (get_parameters vs list_caches), and singular/plural forms vary (list_node_types vs get_work_item_info), making the naming pattern predictable but not uniform.
206 tools is an extreme mismatch for a single MCP server. Even for a comprehensive Houdini automation surface, this is far beyond the recommended 3-15 range and would overwhelm an agent's context window and tool-selection space. Many of these tools could be consolidated or grouped behind a smaller set of flexible operations.
The tool surface covers virtually every Houdini domain: node lifecycle, parameters, animation, geometry, USD/LOP, simulation (DOP and TOPs), COPs, CHOPs, HDAs, materials, rendering, viewport control, shelf tools, help documentation, and workflow guides. Both high-level setup tools (setup_pyro_sim, build_network) and atomic operations (set_keyframe, delete_node) are present, so there are no obvious dead ends or critical missing operations.