Skip to main content
Glama
README.md
# td-mcp

A lean, token-efficient [MCP](https://modelcontextprotocol.io) server for
driving [TouchDesigner](https://derivative.ca) from AI assistants like Claude.

Build whole node networks in one call, search CHOP channels by glob, inspect
operators compactly, and screenshot any TOP so the assistant can *see* what it
built. Battle-tested by building audio-reactive and hand-tracking projects
end to end.

## Why another TouchDesigner MCP?

Compared to a conventional per-node tool surface, td-mcp is designed to
minimize round trips and context tokens:

- **`td_build`** - create a whole network (operators + parameters +
  expressions + wires) in ONE call.
- **`td_find_channels`** - glob-search every CHOP in the project
  (e.g. `*pinch*`) instead of dumping node trees.
- **`td_get`** - returns only NON-default parameters.
- **`td_screenshot`** - saves any TOP to PNG for visual verification.
- **`td_ensure_cook`** - one call installs a per-frame force-cook (fixes the
  classic "GLSL/feedback network renders once then freezes" gotcha).
- Wrong parameter names return close-match suggestions instead of bare errors.
- Operator paths self-locate by name if the exact path moved.
- One-line tool descriptions - tool schemas are loaded into every session,
  so short docs are cheaper.

## Architecture

```
Claude / MCP client
   |  stdio (MCP)
server.py  (Python, FastMCP)
   |  HTTP POST 127.0.0.1:9980/api  (JSON)
TouchDesigner: /project1/td_mcp
   |- webserver   (Web Server DAT, port 9980)
   |- callbacks   (Text DAT - HTTP handler)
   |- dispatcher  (Text DAT - 16 command handlers, TD Python API)
```

The bridge is installed **by script** (no .tox drag-drop): re-runnable,
self-healing, and the DAT contents always match the repo sources.

## Setup

Requirements: [uv](https://docs.astral.sh/uv/), TouchDesigner (any recent
build; tested on 2025.3x macOS).

1. Clone and install:

   ```sh
   git clone https://github.com/YOURNAME/td-mcp && cd td-mcp && uv sync
   ```

2. Install the bridge inside TouchDesigner - open the textport
   (Alt+T / Option+T) and run (adjust the path to your clone):

   ```python
   exec(open('/path/to/td-mcp/td/install_bridge.py').read())
   ```

   Verify from a terminal:
   `curl -s http://127.0.0.1:9980/api -d '{"cmd":"status"}'`

3. Register the server with your MCP client. For Claude Code, in
   `.mcp.json`:

   ```json
   {
     "mcpServers": {
       "td": {
         "command": "uv",
         "args": ["--directory", "/path/to/td-mcp", "run", "python", "server.py"]
       }
     }
   }
   ```

4. Restart the client and ask it to `td_status`.

## Tools

| Tool | Purpose |
|---|---|
| `td_status` | TD + bridge status |
| `td_build` | whole network in one call (ops, params, exprs, wires) |
| `td_create` / `td_delete` | single operator create / delete |
| `td_set` | set params; `{"expr": ...}` for expressions, `"PULSE"` to pulse |
| `td_connect` | wire two operators |
| `td_get` / `td_list` | compact inspection |
| `td_find_channels` | glob-search CHOP channels project-wide |
| `td_read_chop` | live channel values |
| `td_ensure_cook` | per-frame force-cook (anti-freeze) |
| `td_screenshot` | save a TOP to PNG |
| `td_save` / `td_load_tox` | save project / load a .tox |
| `td_errors` | all erroring operators under a path |
| `td_exec` | escape hatch: run Python inside TD |

## Field notes (learned the hard way)

- TD's Python `open()` defaults to ASCII - the bridge sources are pure ASCII.
- `ParMode` is not on the `td` module inside DAT modules; the dispatcher uses
  `type(par.mode).EXPRESSION` instead (version-proof).
- Feedback TOPs need an actual input connection, not just a Target TOP.
- COMP-to-COMP wiring requires matching connector families (a CHOP output
  cannot feed a DAT input) - check `outputConnectors[i].outOP` types.
- After building feedback networks, pulse `resetpulse` once to flush any
  pre-expression frames the loop may have latched.

## Credits

Bridge-over-Web-Server-DAT architecture inspired by
[8beeeaaat/touchdesigner-mcp](https://github.com/8beeeaaat/touchdesigner-mcp).

## License

MIT

TDQS

B3.4/5.0

Scored across 16 tools

Disambiguation5/5

Each tool targets a distinct operation: status checks connection, build creates networks, create makes single ops, set modifies params, connect wires, get inspects, list enumerates children, delete removes, find_channels/read_chop handle CHOP data, ensure_cook forces cooking, screenshot captures images, save/load handle files, errors finds problems, and exec runs arbitrary Python. No two tools have overlapping purposes.

Naming Consistency5/5

All tools follow a consistent `td_verb` or `td_noun` pattern, with verbs like create, set, connect, get, list, delete, find, read, save, load, and exec. The two noun-like names (td_status, td_errors) are intuitive and don't break the overall naming scheme.

Tool Count4/5

16 tools is comprehensive but not excessive for a TouchDesigner MCP server that needs to support network building, parameter manipulation, inspection, debugging, file I/O, and execution. It's one tool over the typical '5-15' range but still well-scoped for the diversity of operations.

Completeness4/5

The tool set covers the core lifecycle: create, delete, connect, set params, save/load, and inspect. It also includes important extras like channel finding, error reporting, screenshots, and a Python escape hatch. Minor gaps exist (no explicit disconnect/rename/move operations), but td_exec can cover these, so agents have workarounds.

Maintenance

ActivityStale
ResponsivenessNo issues