Skip to content
MCP Servers
Skill

/touchdesigner-self-debug

A generic workflow for self-starting TouchDesigner via computer-use (or an already-running instance), loading mcp_webserver_base.tox, and verifying any TD-side Python change (td/modules/**) directly from the Textport — reading back real TD runtime values and reconciling them.

BOOST
From plugin
touchdesigner-mcp
58112 skills1 agent1 MCP
Install
$ npx -y skills add 8beeeaaat/touchdesigner-mcp --skill touchdesigner-self-debug --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/touchdesigner-self-debug

Context preview

The summary Claude sees to decide when to auto-load this skill.

A generic workflow for self-starting TouchDesigner via computer-use (or an already-running instance), loading mcp_webserver_base.tox, and verifying any TD-side Python change (td/modules/**) directly from the Textport — reading back real TD runtime values and reconciling them.

SKILL.md

touchdesigner-self-debug.SKILL.md
name: touchdesigner-self-debug
description: >
  A generic workflow for self-starting TouchDesigner via computer-use (or an
  already-running instance), loading mcp_webserver_base.tox, and verifying any
  TD-side Python change (td/modules/**) directly from the Textport — reading
  back real TD runtime values and reconciling them. Use after changing TD-side
  code in the touchdesigner-mcp repo when E2E verification on a real TD is
  needed, or when told to "start TD and check," "verify on the actual machine,"
  or "import and run the .tox." Includes the shortcut of calling api_service
  directly, bypassing the HTTP WebServer / OpenAPI schema.

TouchDesigner Startup + Functional Self-Debugging

A **general technique** for verifying any TD-side Python change (e.g. anything in `td/modules/**`) inside **real TouchDesigner**. Calling functions directly from the Textport, without standing up the HTTP WebServer, is the shortest path.

> **This skill is feature-agnostic.** The worked example in Steps 4–5 happens to > verify *node auto-alignment* (the PR that produced this skill), but that is > **illustration only**. The reusable shape is: **create/modify via the real code > path → read back the TD runtime value you actually care about → reconcile > against an invariant.** Swap the alignment-specific bits (grid, overlap area, > `node_layout.py`) for whatever your change touches. Do **not** assume alignment, > grids, or overlap have anything to do with your task.

When to Execute

  • You modified TD-side logic (e.g. `td/modules/mcp/services/*.py`) and want to check behavior on the real machine.
  • Unit/offline verification is insufficient and you need to reconcile against TD runtime data (any node attribute, cook result, error state, etc.).
  • You are in a fresh worktree that cannot rely on CI or the 9981-dependent integration suite.

Prerequisites and Pitfalls (read first — these are general)

1. **The `.tox` reads `td/modules/` from disk at runtime.** Re-authoring the `.tox` is **not** required for `.py` changes; reload modules or restart TD. 2. **`loadTox()` leaves `externaltox` empty** → `import_modules.setup()` fails with `No module named 'mcp'`. Replicate setup manually (Step 3). 3. **A fresh worktree lacks generated artifacts** → empty OpenAPI schema / missing `node_modules` breaks HTTP routing. Bypass it by **calling the Textport directly** (Step 4). Only run `npm install && npm run gen` if you specifically need the HTTP path (e.g. running the vitest integration suite). 4. **Computer-use screenshots go black** when TD loses frontmost focus → recover with `open_application("TouchDesigner")` + `switch_display`. 5. **Multi-line pastes into the REPL break on line boundaries** → always wrap in `exec("""...""")` to submit as one statement. 6. **To pick up a later `.py` edit** in an already-running TD, drop the module from `sys.modules` so the next import reloads from disk (Step 3c). If the WebServer is already up you can do this via `execute_python_script` — no computer-use needed.

Step 1: Start TD (skip if already running)

computer-use: request_access(["TouchDesigner"])
computer-use: open_application("TouchDesigner")   # wait a few seconds
computer-use: screenshot                           # confirm

If a WebServer is already listening on 9981 (`lsof -nP -iTCP:9981 -sTCP:LISTEN`) and `get_td_info` succeeds, you can drive everything via `execute_python_script` and skip the computer-use / Textport steps entirely.

Step 2: Open the Textport

Menu bar **Dialogs → "Textport and DATs"**. (`Alt+T` toggles the Palette and is unreliable; use the menu.)

Step 3: Load .tox + manually replicate module setup

# 3a. Load
p = op('/project1').loadTox('<ABS_REPO>/td/mcp_webserver_base.tox'); print('LOADED', p)

# 3b. externaltox is empty after loadTox — replicate import_modules.setup()
exec("""
import sys, os, yaml
b = op('/project1/mcp_webserver_base')
b.par.externaltox = '<ABS_REPO>/td/mcp_webserver_base.tox'
mp = '<ABS_REPO>/td/modules'; tsp = os.path.join(mp, 'td_server')
[sys.modules.pop(m) for m in list(sys.modules) if m.split('.',1)[0] in ('mcp','utils')]
[sys.path.remove(x) for x in (tsp, mp) if x in sys.path]
sys.path.insert(0, mp); sys.path.insert(0, tsp)
import mcp
sp = os.path.join(mp, 'td_server', 'openapi_server', 'openapi', 'openapi.yaml')
mcp.openapi_schema = yaml.safe_load(open(sp)) if os.path.exists(sp) else {}
print('SETUP_OK', mcp.__file__, 'schema', bool(mcp.openapi_schema))
""")

# 3c. Reload just your edited modules to pick up later .py edits (targeted, safe)
import sys
for m in ('mcp.services.api_service',):   # list the modules you changed
    sys.modules.pop(m, None)

`SETUP_OK .../td/modules/mcp/__init__.py` means `mcp` imported from the local tree. (`schema False` is fine for the Textport-direct path.)

Step 4: Verify your change from the Textport (no HTTP required)

**Generic template — this is the part to reuse.** Drive the code you changed through its real entry point, then read back the runtime value and reconcile:

exec("""
from mcp.services.<your_module> import <entry_point>   # the code you changed
# 1. exercise it via the real call path
<result> = <entry_point>(<args>)
# 2. read back the ACTUAL TD runtime value(s) you care about
<observed> = <read from op(...), node attrs, cook state, errors, ...>
# 3. reconcile against an invariant (prefer a numeric/boolean check over "looks right")
print('JUDGE', 'PASS' if <invariant holds> else 'FAIL', <observed>)
""")

Notes that generalize:

  • Pass `node_type` as a **string** (e.g. `'circleTOP'`) to `api_service.create_node`; TD resolves it.
  • Prefer **reconciliation** (compute a value and compare) over assertions that can be gamed.
  • To test cumulative behavior, apply the change repeatedly and check an invariant like `after == before + N`.

<details> <summary><b>Worked example (align-nodes PR — illustration, not the procedure)</b></summary>

Verifying that `create_node` places

Read more
Ships withtouchdesigner-mcp

This is an implementation of an MCP (Model Context Protocol) server for TouchDesigner. Its goal is to enable AI agents to control and operate TouchDesigner projects. English / 日本語

Get the whole plugin
Stats
582
Stars
62
Forks
Active
Maintenance
TypeScript
Language
MIT
License
3d ago
Last commit
1y ago
Created
4h ago
Added

Repo: 8beeeaaat/touchdesigner-mcp

Other skills on touchdesigner-mcp.