Skip to content

Tools Reference

Envoy exposes 62 MCP tools for interacting with TouchDesigner, plus 20 bridge meta-tools: 4 TD-lifecycle tools and 16 convoy_* LAN work-relay tools (all listed below). All tools use the standard MCP protocol and can be called by any compatible client.

Two of the 62 (convoy_lifecycle_state, convoy_lifecycle_quit) are internal Convoy host-lifecycle tools: they refuse any session other than the Convoy host app's dedicated loopback session and are not for agent use.

Every mutating TD-authoring tool call is wrapped in a TouchDesigner undo block. Press Ctrl+Z in TD to revert an agent change; a batch_operations call is one undo step for the whole batch.

Responses are compact by default; opt-in flags such as include_defaults and details return full detail when needed.

Operator Management

Tool Parameters Description
create_op parent_path, op_type, name? Create a new operator (e.g., baseCOMP, noiseTOP, textDAT, gridPOP)
create_extension parent_path, class_name, name?, code?, promote?, ext_name?, ext_index?, existing_comp? Create a TD extension: baseCOMP + text DAT + extension wiring, initialized and ready to use
delete_op op_path, override? Delete an operator. Also purges its externalization tracking (any strategy) and the externalized file — unless the file is clone-owned or still referenced by another operator. Refused while another live session claims the scope or wrote it in the last minute; override=True bypasses
copy_op source_path, dest_parent, new_name? Copy operator to new location
rename_op op_path, new_name Rename an operator
get_op op_path, include_defaults? Get operator info. Parameters are NON-DEFAULT only by default; pass include_defaults=True for all parameters. Parameter-heavy COMPs are expensive in full detail, so prefer read_tdn for structure reads
query_network parent_path?, recursive?, op_type?, include_utility? List operators in a container. Child rows are compact: path, type, family, depth (name is derivable from the last path segment). Set include_utility=True to include annotations
find_children op_path, name?, type?, depth?, tags?, text?, comment?, include_utility? Advanced search using TD's findChildren — filter by name pattern, type, depth, tags, text content, or comment
cook_op op_path, force?, recurse? Force-cook an operator

Parameter Control

Tool Parameters Description
set_parameter op_path, par_name, value?, mode?, expr?, bind_expr? Set a parameter's value, expression, bind expression, or mode (constant/expression/export/bind). Invalid Menu values are rejected with valid menuNames; sequence-block names auto-grow their sequence (const5name grows numBlocks to 6)
get_parameter op_path, par_name?, search?, search_in?, depth?, max_results?, details? Get one parameter compactly, or search parameters by glob/substring across a subtree. Search fields: name, value, expr, or any

Search mode omits par_name and passes search. It scans the target operator and children to depth (default 2) using fnmatch glob semantics; patterns without *?[ become contains searches. Results are {root, pattern, search_in, count, results, truncated?}, where each hit includes op, par, value, mode, and expr or bindExpr when present.

search_in='value' evaluates every parameter it scans (expressions included), so expression side effects and cooking cost are on the caller; search_in='any' only evaluates constant-mode values and matches expression/bind parameters by text.

Single-parameter mode returns path, parameter, value, mode, label, mode-specific refs (expression, bindExpr, bindMaster, exportOP), and menuNames for Menu parameters. Pass details=True to include defaults, custom/read-only/style metadata, numeric ranges, menuLabels, and menuIndex. Search mode ignores details.

Example -- find expressions under /project1 that reference absolute paths in that subtree:

{"op_path": "/project1", "search": "*/project1/*", "search_in": "expr", "depth": 10, "max_results": 100}

DAT Content

Tool Parameters Description
get_dat_content op_path, format? Get DAT text or table data ("text", "table", or "auto")
set_dat_content op_path, text?, rows?, clear?, confirm_wipe? Full-replace DAT content. Wipe guardrail refuses text="", rows=[], or clear=True with no content unless confirm_wipe=True is passed. For partial edits to text DATs, prefer edit_dat_content -- it sends only the changed substring.
edit_dat_content op_path, old_string, new_string, replace_all?, confirm_wipe? Surgical text edit on a DAT (mirrors Claude Code's Edit tool). Replaces old_string with new_string. By default old_string must appear exactly once -- pass replace_all=True to replace every occurrence. Token-efficient: only the changed substring crosses the wire. Text DATs only; use set_dat_content(rows=...) for tables.

Operator Flags

Tool Parameters Description
get_op_flags op_path Get all flags: bypass, lock, display, render, viewer, current, expose, selected, allowCooking
set_op_flags op_path, bypass?, lock?, display?, render?, viewer?, current?, expose?, allowCooking?, selected? Set one or more flags on an operator

Positioning & Layout

Tool Parameters Description
get_op_position op_path Get operator position, size, color, and comment
get_network_layout comp_path, include_annotations? Get compact positions of ALL operators (and annotations) in a COMP in one call. Operators include path, type, nodeX, nodeY, nodeWidth, nodeHeight; centers are derivable as nodeX+nodeWidth/2 and nodeY+nodeHeight/2. Annotation text is capped at 160 chars. Returns bounding_box
set_op_position op_path, x?, y?, width?, height?, color?, comment? Set operator position, size, color ([r,g,b] floats 0-1), or comment
layout_children op_path Auto-layout all children in a COMP

Annotations

Tool Parameters Description
create_annotation parent_path, mode?, text?, title?, x?, y?, width?, height?, color?, opacity?, name? Create an annotation. Modes: "annotate" (default, has title bar), "comment", "networkbox". Created utility=True (matching TD UI-drawn annotations): visible to get_annotations, hidden from query_network/find_children unless include_utility=True. Every op-path tool still resolves it by path; delete with delete_op (durable), never a raw .destroy()
get_annotations parent_path List all annotations in a COMP with their properties and enclosed operators
set_annotation op_path, text?, title?, color?, opacity?, width?, height?, x?, y? Modify properties of an existing annotation
get_enclosed_ops op_path Get operators enclosed by an annotation, or annotations enclosing an operator

Connections

Tool Parameters Description
connect_ops source_path, dest_path, source_index?, dest_index?, comp? Wire two operators together. Set comp=True for COMP connectors (top/bottom)
disconnect_op op_path, input_index?, comp? Disconnect an operator's input. Set comp=True for COMP connectors (top/bottom)
get_connections op_path Get all input/output connections (includes COMP connections for COMPs)

Performance Monitoring

Tool Parameters Description
get_op_performance op_path, include_children? Get CPU/GPU cook times, memory usage, cook counts
get_project_performance include_hotspots? Get project-level FPS, frame time, GPU/CPU memory, dropped frames, active ops, GPU temp. Optional hotspot ranking of top N COMPs by cook time

Code Execution

Tool Parameters Description
execute_python code Execute Python in TD; set the result variable to return values. Auto-lints newly-created ops and emits a LAYOUT WARNING when they are left at (0,0) or overlapping (unlike create_op, raw comp.create() does not auto-position)

Introspection & Diagnostics

Tool Parameters Description
get_td_info (none) Get TD version, build, OS, and Envoy version
get_op_errors op_path, recurse? Get error and warning messages for an operator and its children
exec_op_method op_path, method, args?, kwargs? Call a method on an operator (e.g., appendRow, cook)
get_td_classes (none) List all Python classes/modules in the td module
get_td_class_details class_name Get methods, properties, and docs for a TD class
get_module_help module_name Get Python help text for a module (supports dotted names like td.tdu)
get_docs query, section?, source?, max_chars? Look up official TouchDesigner docs. source is auto (offline then web), offline, or web; normal responses carry title, source, sections_available, content, and optional url/truncated; ambiguous offline lookups return source + matches only
get_guidance topic? Serve this project's checked-in TouchDesigner doctrine (.claude/rules/*.md and .claude/skills/*/SKILL.md) over MCP, so agents on any client -- Codex, Cursor, opencode -- get the same rules Claude Code loads. Bare call lists topics; topic returns that document. Answered worker-side (no TD round-trip)
get_focus (none) What the user is looking at: current pane network, selected operator(s), current op, and rollover. When the user says "this operator" they mean the SELECTED/current op -- rollover is incidental mouse position and must not be acted on

Embody Integration

Tool Parameters Description
externalize_op op_path, tag_type? Tag and externalize operator to disk (auto-detects type if omitted)
remove_externalization_tag op_path, delete_file? Remove externalization tracking (tag + row + TDN breadcrumb); delete_file=True also deletes the file (best-effort). Returns removed_tags, removed_rows, removed_anything, summary -- an operator can have a tracked row but NO tag, so check removed_anything, not removed_tags, to confirm cleanup
get_externalizations (none) List all externalized operators with status
save_externalization op_path Force save an externalized operator to disk
get_externalization_status op_path Get dirty state, build number, timestamp, file path

TDN Format

Tool Parameters Description
read_tdn comp_path?, include_dat_content?, max_depth?, embed_all? Preferred for reading ≥3 operators. Return the live network as a TDN dict (in-memory, never written to disk). ~20-90× fewer tokens than a get_op walk thanks to default-omission, type_defaults, and par_templates compaction
export_network root_path?, include_dat_content?, output_file?, max_depth?, embed_all? Write a .tdn file to disk. Same payload as read_tdn plus file I/O and stale-file cleanup. Set embed_all=True to recurse into TDN-tagged COMPs instead of skipping their children (self-contained export)
import_network target_path, tdn, clear_first?, override? Recreate a network from a .tdn file. With clear_first=True, gated against live peer sessions like delete_op
diff_tdn target?, max_changed_ops?, max_bytes? What is UNSAVED in TDN networks -- the live in-memory network vs the on-disk .tdn, the view git cannot give. Omit target for a whole-project summary (every live TDN COMP, which changed + counts); pass a COMP path OR a .tdn file path/bare filename for one COMP in full per-field detail (old=disk, new=live). For committed/history diffs use plain git diff -- Embody installs a .tdn diff driver that keeps those clean. Read-only, non-interactive

TOP Capture

Tool Parameters Description
capture_top op_path, format?, quality?, max_resolution?, inline?, sample_grid? Capture a TOP's output as an image. Saves to a temp file and returns the path -- Read that path to view it. Inline base64 previews are token-heavy, so they are off by default (inline=False); pass inline=True to also embed a small preview. Small images (<20 KB) include the inline MCP ImageContent preview when requested. Default: JPEG at 80% quality, max 640px long edge. Pass sample_grid>=2 to return a downsampled NxN RGBA grid instead of an image: row 0 is the top of the image, stats are computed over the full-resolution texture, the requested grid clamps to 2..32, the returned grid is further capped to the TOP's width/height and can drop below 2 on tiny textures, and image params are ignored. Channel padding: RG -> b=0/a=1, mono -> replicated/a=1, monoalpha -> replicated + real alpha; channels reports the raw plane count. Every capture also returns a Quality verdict from the raw float pixels (is_black / is_flat / fully_transparent / pass + fail_reasons), surfaced as a Quality: OK\|FAIL line so you can tell an empty/black/transparent render from a real one without reading the image (black and fully-transparent are failures; a uniform fill is advisory, flat_frame).

Multi-Session Awareness

Concurrent AI sessions (multiple Claude Code windows, other MCP clients) working on the same project are tracked, warned about each other, and gated away from destroying each other's work. See Multi-Session Coordination for the full picture.

Tool Parameters Description
get_sessions List connected AI sessions: label (repo@branch), idle time, recent_scopes it modified, claims it holds, plus you (the caller's own session id). May include worktrees: in-flight durable worktree tasks, visible even after their session ended
claim_scope scope, note?, ttl? Cooperative write lease on an op-path prefix, a file: path, or a project: scope. Peers' overlapping claims are refused while yours is live; their destructive operations on it are gated. Auto-renews on your own writes; expires on TTL or session silence
release_scope scope Release a lease you hold. Polite — expiry also handles it
announce_task title, scopes?, note? Announce a unit of work to the shared task ledger so parallel sessions see what is in progress and what is finished-but-uncommitted; active entries ride on get_sessions
update_task task_id, status?, note?, commit? Transition a ledger task (done_uncommitted / committed with sha / abandoned); any session may update any task, non-owner writes record updated_by
preflight_landing worktree_path Landing safety check for a git-worktree diff: intersects the files it would land with main-tree dirt, peer file: claims/touches, and unsaved live TDN state. Run before porting any worktree diff; a conflicts verdict means reconcile first

Auto-piggybacked peer advisories

A _peers field rides on any response whose request touches territory another session modified in the last ~10 minutes — one entry per peer: {label, scope, tool, age_s, conflict}. conflict: true means a peer wrote an overlapping scope within the last minute and your operation is also a write — stop and coordinate.

Destructive-operation gate

delete_op, import_network with clear_first=True, run_tests, and batches containing them are refused with a MULTI-SESSION GATE error (naming the holder or recent writer) while a live peer session claims the scope or wrote it within the last minute. Pass override=True only when you are certain.

Logging

Tool Parameters Description
get_logs level?, count?, since_id?, source? Get recent log entries from ring buffer. Filter by level, source, or use since_id for incremental polling
run_tests suite_name?, test_name?, override?, background? Run test suites. background=True (recommended for full runs) returns a job id immediately and parks results in .embody/jobs/ -- poll get_job_status; the synchronous mode is severed by the watchdog suites' server restart. Gated while a peer session holds project:tests

Auto-piggybacked logs

When a tool call generates WARNING or ERROR entries since the previous call, the response carries a _logs field with up to the last 8 of them. INFO/DEBUG/SUCCESS history does not ride along — fetch it on demand with get_logs. Warning cursors are tracked per session, so concurrent AI sessions each receive their own copy — one session polling first no longer consumes a warning meant for everyone.

Auto-attached recovery hints

When a tool returns an error, Envoy attaches a recovery_hints list — each entry {cause, action, next_tools}, matched to the real error string (path-not-found -> query_network/find_children, parameter-not-found -> get_op, wrong family, empty capture -> get_op_performance, thread conflict, timeout -> get_project_performance). Additive, never clobbers, never raises — follow the hint instead of retrying the same failing call.

Background Jobs

Long operations that outlive the 30-second operation timeout run as disk-backed jobs: the starting tool returns a job_... handle immediately, results park in .embody/jobs/ (surviving server restarts and extension reinits), and get_job_status polls.

Tool Parameters Description
get_job_status job_id? One job record (status running/done/error, result when done, stale when a running record stopped updating), or the 16 newest records without job_id. A finished run_tests job carries the summary with failures listed first; a finished save_project job carries version_before/version_after
save_project (none) Save the project as a tracked job. Refused while a test run is active (a mid-run save bakes test-forced parameters into the export); idempotent -- a second call while a save is in flight returns the existing handle. The next call after a save may fail once while the bridge reconnects

Bridge Meta-Tools

These tools run locally on the STDIO bridge script, not inside TouchDesigner. They work even when TD is not running — this is how Claude Code can launch or restart TD without an active Envoy connection.

Tool Parameters Description
get_td_status (none) Check if TD is running, Envoy reachable, crash detection, process liveness, restart attempts remaining
launch_td timeout?, project_path? Launch TD with the project's .toe file. Waits for Envoy to become reachable (default: 120s). Pass project_path (absolute, or relative to the git root) to open a different .toe
restart_td timeout?, project_path? Gracefully quit TD and relaunch. Waits for exit before relaunching (default: 120s). Pass project_path to relaunch with a different .toe. Targets only the active instance's verified process — other running TouchDesigner instances are never touched
switch_instance instance?, all_sessions? List all registered TD instances (omit instance) or re-pin this session's bridge to a different running instance; other sessions are untouched unless all_sessions=true. See Multiple Instances

Convoy Tools (LAN work relay)

The remaining 16 meta-tools drive Convoy, relaying work to Convoy-enabled Embody nodes on the trusted LAN through the local per-user host app. Status and inventory calls never wake TouchDesigner.

Tool Description
get_convoy_status Is the local Convoy host app available, and what does it know
convoy_list_nodes Local and reachable remote nodes
convoy_list_controllers Live client sessions, selected targets, leases, and active work
convoy_ping One node's liveness through its host app, without waking TouchDesigner
convoy_select_node Pin this session to one exact node so ordinary Envoy tools run there (clear=true to unpin)
convoy_call One-off registered operation on an explicit target, without changing the selection
convoy_batch The same ordered batch on one or more explicit targets, reported per target
convoy_get_job Check durable work that outlives the original call or reconnect
convoy_ack_job Acknowledge a finished delivery so the target can release its protected result artifacts
convoy_cancel_job Request cancellation from the exact owning host
convoy_forget_node Delete a stale node row on THIS machine's host app (refuses only while a delivery has not FINISHED, naming the blocking delivery ids; a finished result never holds a row); dead and long-unseen rows are also evicted automatically
convoy_get_artifact Retrieve and verify a large result into a temporary local file by artifact reference
convoy_save_artifact Verify an artifact and save it into the current project (overwrite=true required to replace)
convoy_start_node Reopen a previously registered, currently offline node
convoy_restart_node Safely replace one exact running TouchDesigner process (requires the current runtime id and an idempotency key)
convoy_owlette Optional read-mostly bridge to an Owlette site; fails closed without credentials

Bridge architecture

Claude Code connects to Envoy via a STDIO bridge script (.embody/envoy-bridge.py). The bridge translates between Claude Code's STDIO transport and Envoy's HTTP endpoint. It handles MCP protocol handshake locally when TD is down, so these meta-tools are always available. See Architecture for details.

Batch Operations

Tool Parameters Description
batch_operations operations Execute multiple operations in a single request. Reduces latency and token overhead

operations is a list of {"tool": str, "params": dict} objects. Each entry maps to an existing tool name and its parameters. Stops on first error.

When to use: 3+ calls to the same tool type (positioning, connecting, parameter setting, flags). Use execute_python instead when you need conditionals, loops, or computed values between operations.

Example — position 4 operators + connect them in one call:

{"operations": [
  {"tool": "set_op_position", "params": {"op_path": "/project1/noise1", "x": 400, "y": 0}},
  {"tool": "set_op_position", "params": {"op_path": "/project1/comp1", "x": 800, "y": 0}},
  {"tool": "set_op_position", "params": {"op_path": "/project1/level1", "x": 1200, "y": 0}},
  {"tool": "set_op_position", "params": {"op_path": "/project1/null1", "x": 1600, "y": 0}},
  {"tool": "connect_ops", "params": {"source_path": "/project1/noise1", "dest_path": "/project1/comp1"}},
  {"tool": "connect_ops", "params": {"source_path": "/project1/comp1", "dest_path": "/project1/level1"}},
  {"tool": "connect_ops", "params": {"source_path": "/project1/level1", "dest_path": "/project1/null1"}}
]}

MCP Prompts

Prompt Parameters Description
search_op op_name, op_type? Guide for searching operators by name
check_op_errors op_path Guide for inspecting and resolving operator errors
connect_ops (none) Guide for wiring operators together
create_extension_guide (none) Guide for creating TD extensions with proper patterns