Skip to content

graph

graph

MCP tools for graph-level intelligence.

Atomic network building with validation, network verification, node documentation cards, and cook profiling — the senior-artist toolset.

Functions:

Name Description
build_network

Build a whole node network in ONE atomic call — the PREFERRED way

cook_frame_range

Cook a node frame by frame and report what changed on each frame.

find_expensive_nodes

Profile cooking and rank the most expensive nodes — how a senior

get_cook_status

Whether a node has cooked, how often, and whether it is time dependent.

get_node_card

Get the authoritative documentation card for a node type, straight

verify_network

Inspect every node in a network at once — errors, warnings, flags,

Functions:

build_network async

build_network(
    ctx: Context,
    parent_path: str,
    nodes: list[dict[str, Any]],
    dry_run: bool = False,
    layout: bool = True,
) -> dict

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/source/ source_output), flags (display/render/bypass/template), color [r,g,b], comment.

Parameters:

Name Type Description Default
parent_path
str

Network to build inside (e.g. "/obj/geo1").

required
nodes
list[dict[str, Any]]

Ordered node specs (see above).

required
dry_run
bool

Validate the whole spec without creating anything.

False
layout
bool

Lay out the parent network afterwards.

True

cook_frame_range async

cook_frame_range(
    ctx: Context,
    node_path: str,
    start: float | None = None,
    end: float | None = None,
    step: float = 1.0,
    attribs: list[str] | None = None,
    volumes: bool = False,
) -> dict

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.

Parameters:

Name Type Description Default
node_path
str

Node to cook; its output is what gets measured.

required
start
float | None

First frame. Defaults to the playbar start.

None
end
float | None

Last frame, inclusive. Defaults to the playbar end.

None
step
float

Frame increment. Keep at 1.0 for any solver, since skipping frames gives it a discontinuous time step and invalid results.

1.0
attribs
list[str] | None

Point attributes to aggregate per frame (min/max/mean/sum).

None
volumes
bool

Also report per-volume name, resolution and value range.

False

find_expensive_nodes async

find_expensive_nodes(
    ctx: Context,
    root_path: str = "/",
    frame: float | None = None,
    limit: int = 15,
) -> dict

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.

Parameters:

Name Type Description Default
root_path
str

Network to profile (a geo container, or "/" broadly).

'/'
frame
float | None

Optionally jump to this frame before cooking.

None
limit
int

Max nodes to return.

15

get_cook_status async

get_cook_status(ctx: Context, node_path: str = '/obj') -> dict

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.

Parameters:

Name Type Description Default
node_path
str

Node to report on.

'/obj'

get_node_card async

get_node_card(
    ctx: Context,
    node_type: str,
    context: str = "Sop",
    parm_filter: str | None = None,
) -> dict

Get the authoritative documentation card for a node type, straight from the running Houdini: real connector labels, real parameter names/defaults/menus, and the node's own shipped help text.

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.

Parameters:

Name Type Description Default
node_type
str

Type name (e.g. "scatter", "rbdbulletsolver").

required
context
str

Category — "Sop", "Lop", "Dop", "Cop", "Chop", "Top", "Object", "Driver".

'Sop'
parm_filter
str | None

Substring filter for the parameter list.

None

verify_network async

verify_network(ctx: Context, parent_path: str) -> dict

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 healthy is false or error_nodes is non-empty, fix those nodes before telling the user anything is done.

Parameters:

Name Type Description Default
parent_path
str

Network to verify (e.g. "/obj/geo1").

required