Architecture
tdmcp is three programs that talk to each other on your machine:
AI assistant tdmcp server TouchDesigner
(Claude / Cursor) ──▶ (Node / TypeScript) ──▶ (the Python bridge inside TD)
"make a feedback MCP tools + the creates / connects /
tunnel from noise" operator knowledge base inspects / previews nodes- The AI assistant is any MCP-capable client — Claude Desktop, Claude Code, Codex, or Cursor. It's where you describe what you want.
- The tdmcp server is a small Node program. It exposes a set of TouchDesigner "tools" and an embedded operator knowledge base to the AI over the Model Context Protocol.
- The bridge is a Python package that runs inside TouchDesigner (behind a Web Server DAT). It's what actually drives TD. See Bridge & REST API.
MCP client ──stdio──▶ tdmcp server (Node/TS) ──HTTP──▶ TouchDesigner bridge (Python)
├── Layer 1 artist tools (create_visual_system, …)
├── Layer 2 building blocks (create_node_chain, …)
├── Layer 3 atomic ops (create_td_node, …)
├── Knowledge base (MCP resources)
├── Recipes (validated network templates)
└── Feedback engine (errors / preview / performance)The three tool layers
Tools are organized into layers so the AI can pick the right altitude for a task. See the full, always-current list in the Tools reference.
- Layer 1 — artist tools. Describe a result (
create_feedback_network,create_audio_reactive,create_generative_art, …) and get a whole network, wired and arranged, often with a control panel ready to perform. - Layer 2 — building blocks. Mid-level pieces (
create_node_chain,connect_nodes,create_control_panel,animate_parameter,create_external_io, …) for assembling and controlling networks by hand. - Layer 3 — atomic operations. Single-node CRUD plus inspection, analysis, rendering and the Python escape hatches (
create_td_node,find_td_nodes,get_td_node_errors,execute_python_script, …).
A separate group of vault tools bridges an Obsidian vault and TouchDesigner.
The create → verify → preview loop
Every high-level build follows the same loop so the AI can see and fix its own work instead of guessing:
- Create the network from a recipe, GLSL pattern, or generated Python.
- Verify by reading cook/compile errors (
get_td_node_errors,summarize_td_errors). - Preview by capturing the output TOP as an inline image (
get_preview).
Generated networks are auto-arranged into a readable left→right layout (arrange_network) instead of piling nodes on top of each other.
Knowledge base
The server ships with an embedded, offline reference so the AI uses real operators rather than inventing them: 629 operators, 68 Python classes, workflow patterns, GLSL techniques and tutorials. These are exposed as MCP resources the AI can read on demand:
tdmcp://operators/{category|name} · tdmcp://python-api/{class} · tdmcp://patterns/{name} · tdmcp://glsl/{name} · tdmcp://recipes/{name} · tdmcp://tutorials/{name}
The knowledge base is committed to the repo, so a fresh clone needs only npm install && npm run build. npm run import:bottobot regenerates it from @bottobot/td-mcp and is only needed to refresh it.
Recipes
Recipes are validated network templates (JSON) the AI can instantiate with apply_recipe. They cover common starting points — feedback tunnels, reaction-diffusion, particle galaxies, audio spectrum bars, projection mapping and more. See the Recipe gallery for what each one builds, and Contributing to add your own.
Transports & events
The server speaks two MCP transports:
- stdio (default) — for local clients like Claude Desktop and Claude Code.
- Streamable HTTP (
TDMCP_TRANSPORT=http) — serves MCP atPOST/GET/DELETE /mcpon loopback with stateful sessions, for remote/headless setups. See Deployment.
It can also subscribe to a WebSocket event stream from TD (node.created / node.deleted / node.error / project.saved / timeline.frame / node.cook) and forward events as MCP logging notifications. High-frequency events (timeline.frame, node.cook) are dropped unless explicitly opted in. Toggle with TDMCP_EVENTS.
Security
The TouchDesigner bridge runs arbitrary Python inside your TD process — that is what lets the assistant build networks for you. Treat it like an open door to the machine TD runs on:
- The Web Server DAT listens on its port (default
9980) on all network interfaces. Anyone who can reachhttp://<your-ip>:9980can run code on that machine. Only run it on a trusted network, and/or firewall the port to localhost. - Turn on bridge auth for untrusted networks: set
TDMCP_BRIDGE_TOKENto a shared secret in both the server's environment and TouchDesigner's environment. The bridge then rejects any request without a matchingAuthorization: Bearer <token>(HTTP401). Unset (default) keeps the zero-config local flow. TDMCP_RAW_PYTHON=offhides only the two raw-Python MCP tools (execute_python_script,exec_node_method) where the client authors the code. It is not a code-execution kill-switch: many higher-level tools still send their own templated Python to/api/exec, and a direct network caller could hit/api/execand node-methodregardless. To actually close code execution, setTDMCP_BRIDGE_ALLOW_EXEC=0in TouchDesigner's environment — the authoritative gate (defense in depth that holds even without a token); the structured endpoints keep working.- The MCP server binds to loopback (
127.0.0.1) for both transports and enables DNS-rebinding protection on HTTP. - The bridge refuses browser cross-origin requests. Any request carrying an
Originheader that isn't loopback is rejected (HTTP401), so a malicious web page can't quietly POST to the bridge (CSRF / DNS-rebinding → drive-by code execution). The MCP server sends noOrigin, so normal use is unaffected. - The local copilot chat UI (
tdmcp chat) applies the same guard. It binds to loopback and rejects (HTTP403) any request whoseHostorOriginisn't a loopback name, so a page the artist visits can't drive node CRUD against the live project viahttp://127.0.0.1:<chat-port>/chat.
All of these are configured through environment variables.
Known limitations
- WebSocket events are forwarded as MCP logging notifications on both transports; high-frequency events are dropped unless opted in.
- Audio / particle / 3D builders and the exotic recipes (kinect, LED, projection) produce valid, connected networks but use best-effort TD parameter names — fine-tuning may be needed, and they emit warnings to that effect.
- Preview returns the TOP at its native resolution (the requested size is advisory).
- The bridge ships as Python modules plus a callbacks template (a binary
.toxcan't be generated from source); the one-line installer assembles it for you.