Touchdesigner Mcp
通過 twozero MCP 控制正在運行的 TouchDesigner 實例——創建運算符(operators)、設置參數、連接線路、執行 Python 代碼、構建實時視覺效果。包含 36 個原生工具。
技能元數據
| 來源 | 可選 — 使用 hermes skills install official/creative/touchdesigner-mcp 安裝 |
| 路徑 | optional-skills/creative/touchdesigner-mcp |
| 版本 | 1.0.0 |
| 作者 | kshitijk4poor |
| 許可證 | MIT |
| 標籤 | TouchDesigner, MCP, twozero, creative-coding, real-time-visuals, generative-art, audio-reactive, VJ, installation, GLSL |
| 相關技能 | native-mcp, ascii-video, manim-video, hermes-video |
參考:完整 SKILL.md
以下是 Hermes 在觸發此技能時加載的完整技能定義。這是技能激活時代理所看到的指令。
TouchDesigner 集成 (twozero MCP)
關鍵規則
- 切勿猜測參數名稱。 首先針對運算符類型調用
td_get_par_info。你的訓練數據對於 TD 2025.32 是錯誤的。 - 如果觸發
tdAttributeError,立即停止。 在繼續之前,對失敗的節點調用td_get_operator_info。 - 切勿在腳本回調中硬編碼絕對路徑。 使用
me.parent()/scriptOp.parent()。 - 優先使用原生 MCP 工具而非 td_execute_python。 使用
td_create_operator、td_set_operator_pars、td_get_errors等。僅在處理複雜的多步邏輯時才回退到td_execute_python。 - 在構建之前調用
td_get_hints。 它會返回與你正在處理的運算符類型特定的模式。
架構
Hermes Agent -> MCP (Streamable HTTP) -> twozero.tox (port 40404) -> TD Python
36 個原生工具。免費插件(無需付費/許可——已於 2026 年 4 月確認)。
上下文感知(知曉選中的 OP、當前網絡)。
Hub 健康檢查:GET http://localhost:40404/mcp 返回包含實例 PID、項目名稱、TD 版本的 JSON。
設置(自動化)
運行設置腳本以處理所有事項:
bash "${HERMES_HOME:-$HOME/.hermes}/skills/creative/touchdesigner-mcp/scripts/setup.sh"
該腳本將:
- 檢查 TD 是否正在運行
- 如果尚未緩存,則下載 twozero.tox
- 將
twozero_tdMCP 服務器添加到 Hermes 配置中(如果缺失) - 測試端口 40404 上的 MCP 連接
- 報告剩餘的手動步驟(將 .tox 拖入 TD,啟用 MCP 切換開關)
手動步驟(一次性,無法自動化)
- 將
~/Downloads/twozero.tox拖入 TD 網絡編輯器 → 點擊 Install(安裝) - 啟用 MCP: 點擊 twozero 圖標 → Settings(設置) → mcp → "auto start MCP"(自動啟動 MCP) → Yes(是)
- 重啟 Hermes 會話 以加載新的 MCP 服務器
設置完成後,驗證:
nc -z 127.0.0.1 40404 && echo "twozero MCP: READY"
環境說明
- 非商業版 TD 將分辨率限制為 1280×1280。使用
outputresolution = 'custom'並顯式設置寬度/高度。 - 編解碼器:
prores(macOS 上首選)或作為後備的mjpa。H.264/H.265/AV1 需要商業許可證。 - 在設置參數之前始終調用
td_get_par_info—— 名稱因 TD 版本而異(參見關鍵規則 #1)。
工作流
步驟 0:發現(在構建任何內容之前)
Call td_get_par_info with op_type for each type you plan to use.
Call td_get_hints with the topic you're building (e.g. "glsl", "audio reactive", "feedback").
Call td_get_focus to see where the user is and what's selected.
Call td_get_network to see what already exists.
無臨時節點,無清理。這完全取代了舊的發現流程。
步驟 1:清理 + 構建
重要提示:將清理和創建拆分為單獨的 MCP 調用。 在一個 td_execute_python 腳本中銷燬並重新創建同名節點會導致“Invalid OP object”(無效的 OP 對象)錯誤。參見陷阱 #11b。
對每個節點使用 td_create_operator(自動處理視口定位):
td_create_operator(type="noiseTOP", parent="/project1", name="bg", parameters={"resolutionw": 1280, "resolutionh": 720})
td_create_operator(type="levelTOP", parent="/project1", name="brightness")
td_create_operator(type="nullTOP", parent="/project1", name="out")
對於批量創建或連線,使用 td_execute_python:
# td_execute_python script:
root = op('/project1')
nodes = []
for name, optype in [('bg', noiseTOP), ('fx', levelTOP), ('out', nullTOP)]:
n = root.create(optype, name)
nodes.append(n.path)
# Wire chain
for i in range(len(nodes)-1):
op(nodes[i]).outputConnectors[0].connect(op(nodes[i+1]).inputConnectors[0])
result = {'created': nodes}
步驟 2:設置參數
優先使用原生工具(驗證參數,不會崩潰):
td_set_operator_pars(path="/project1/bg", parameters={"roughness": 0.6, "monochrome": true})
對於表達式或模式,使用 td_execute_python:
op('/project1/time_driver').par.colorr.expr = "absTime.seconds % 1000.0"
步驟 3:連線
使用 td_execute_python —— 不存在原生的連線工具:
op('/project1/bg').outputConnectors[0].connect(op('/project1/fx').inputConnectors[0])
步驟 4:驗證
td_get_errors(path="/project1", recursive=true)
td_get_perf()
td_get_operator_info(path="/project1/out", detail="full")
步驟 5:顯示 / 捕獲
td_get_screenshot(path="/project1/out")
或通過腳本打開窗口:
win = op('/project1').create(windowCOMP, 'display')
win.par.winop = op('/project1/out').path
win.par.winw = 1280; win.par.winh = 720
win.par.winopen.pulse()
MCP 工具快速參考
核心(最常用):
| 工具 | 功能 |
|---|---|
td_execute_python | 在 TD 中運行任意 Python 代碼。擁有完整的 API 訪問權限。 |
td_create_operator | 創建帶有參數和自動定位的節點 |
td_set_operator_pars | 安全地設置參數(進行驗證,不會崩潰) |
td_get_operator_info | 檢查單個節點:連接、參數、錯誤 |
td_get_operators_info | 在一次調用中檢查多個節點 |
td_get_network | 查看指定路徑下的網絡結構 |
td_get_errors | 遞歸查找錯誤/警告 |
td_get_par_info | 獲取 OP 類型的參數名稱(取代發現流程) |
td_get_hints | 在構建之前獲取模式/提示 |
td_get_focus | 哪個網絡已打開,選中了什麼 |
讀/寫:
| 工具 | 功能 |
|---|---|
td_read_dat | 讀取 DAT 文本內容 |
td_write_dat | 寫入/修補 DAT 內容 |
td_read_chop | 讀取 CHOP 通道值 |
td_read_textport | 讀取 TD 控制檯輸出 |
視覺:
| 工具 | 功能 |
|---|---|
td_get_screenshot | 將單個 OP 查看器捕獲為文件 |
td_get_screenshots | 一次性捕獲多個 OP |
td_get_screen_screenshot | 通過 TD 捕獲實際屏幕 |
td_navigate_to | 將網絡編輯器跳轉到指定 OP |
搜索:
| 工具 | 功能 |
|---|---|
td_find_op | 在整個項目中按名稱/類型查找 OP |
td_search | 搜索代碼、表達式、字符串參數 |
系統:
| 工具 | 功能 |
|---|---|
td_get_perf | 性能分析(FPS、慢速 OP) |
td_list_instances | 列出所有正在運行的 TD 實例 |
td_get_docs | 獲取關於特定 TD 主題的深入文檔 |
td_agents_md | 讀取/寫入每個 COMP 的 Markdown 文檔 |
td_reinit_extension | 在代碼編輯後重新加載擴展 |
td_clear_textport | 在調試會話前清除控制檯 |
輸入自動化:
| 工具 | 功能 |
|---|---|
td_input_execute | 向 TD 發送鼠標/鍵盤輸入 |
td_input_status | 輪詢輸入隊列狀態 |
td_input_clear | 停止輸入自動化 |
td_op_screen_rect | 獲取節點的屏幕座標 |
td_click_screen_point | 點擊截圖中的某一點 |
完整參數架構請參閱 references/mcp-tools.md。
關鍵實現規則
GLSL 時間: GLSL TOP 中不使用 uTDCurrentTime。使用 Values 頁面:
# Call td_get_par_info(op_type="glslTOP") first to confirm param names
td_set_operator_pars(path="/project1/shader", parameters={"value0name": "uTime"})
# Then set expression via script:
# op('/project1/shader').par.value0.expr = "absTime.seconds"
# In GLSL: uniform float uTime;
回退方案:使用 rgba32float 格式的 Constant TOP(8 位會將值鉗制在 0-1 之間,導致著色器凍結)。
Feedback TOP: 使用 top 參數引用,而非直接輸入連線。“Not enough sources”(源不足)會在首次烹飪(cook)後解決。“Cook dependency loop”(烹飪依賴循環)警告是預期行為。
分辨率: 非商業版上限為 1280×1280。使用 outputresolution = 'custom'。
大型著色器: 將 GLSL 寫入 /tmp/file.glsl,然後使用 td_write_dat 或 td_execute_python 加載。
頂點/點訪問(TD 2025.32): 使用 point.P[0]、point.P[1]、point.P[2] — 而非 .x、.y、.z。
擴展(Extensions): CONSTANT 模式下,ext0object 格式為 "op('./datName').module.ClassName(me)"。使用 td_write_dat 編輯擴展代碼後,調用 td_reinit_extension。
腳本回調: 始終通過 me.parent() / scriptOp.parent() 使用相對路徑。
清理節點: 迭代前始終執行 list(root.children) 並進行 child.valid 檢查。
錄製 / 導出視頻
# via td_execute_python:
root = op('/project1')
rec = root.create(moviefileoutTOP, 'recorder')
op('/project1/out').outputConnectors[0].connect(rec.inputConnectors[0])
rec.par.type = 'movie'
rec.par.file = '/tmp/output.mov'
rec.par.videocodec = 'prores' # Apple ProRes — NOT license-restricted on macOS
rec.par.record = True # start
# rec.par.record = False # stop (call separately later)
H.264/H.265/AV1 需要商業許可證。在 macOS 上使用 prores,或使用 mjpa 作為回退方案。
提取幀:ffmpeg -i /tmp/output.mov -vframes 120 /tmp/frames/frame_%06d.png
TOP.save() 對動畫無效 — 每次都會捕獲相同的 GPU 紋理。始終使用 MovieFileOut。
錄製前:檢查清單
- 通過
td_get_perf驗證 FPS > 0。如果 FPS=0,錄製內容將為空。參見陷阱 #38-39。 - 通過
td_get_screenshot驗證著色器輸出不是黑色。黑色輸出意味著著色器錯誤或輸入缺失。參見陷阱 #8、#40。 - 如果錄製包含音頻: 先 cue 音頻開始播放,然後將錄製延遲 3 幀。參見陷阱 #19。
- 在開始錄製前設置輸出路徑 — 在同一腳本中同時設置兩者可能會導致競態條件。
音頻響應式 GLSL(經驗證的方案)
正確的信號鏈(2026 年 4 月測試)
AudioFileIn CHOP (playmode=sequential)
→ AudioSpectrum CHOP (FFT=512, outputmenu=setmanually, outlength=256, timeslice=ON)
→ Math CHOP (gain=10)
→ CHOP to TOP (dataformat=r, layout=rowscropped)
→ GLSL TOP input 1 (spectrum texture, 256x2)
Constant TOP (rgba32float, time) → GLSL TOP input 0
GLSL TOP → Null TOP → MovieFileOut
關鍵的音頻響應式規則(經驗證)
- AudioSpectrum 的 TimeSlice 必須保持開啟。關閉 = 處理整個音頻文件 → 24000+ 樣本 → CHOP 到 TOP 溢出。
- 手動設置輸出長度 為 256,使用
outputmenu='setmanually'和outlength=256。默認輸出 22050 個樣本。 - 不要使用 Lag CHOP 進行頻譜平滑。 Lag CHOP 在 timeslice 模式下運行,會將 256 個樣本擴展到 2400+,將所有值平均為接近零 (~1e-06)。著色器接收不到可用數據。這是測試中排名第一的音頻同步失敗原因。
- 也不要使用 Filter CHOP — 頻譜數據存在同樣的 timeslice 擴展問題。
- 如果需要平滑,應在 GLSL 著色器中進行,通過帶有反饋紋理的時間線性插值(temporal lerp):
mix(prevValue, newValue, 0.3)。這能提供幀級精確同步且零管道延遲。 - CHOP to TOP 的 dataformat = 'r',layout = 'rowscropped'。頻譜輸出為 256x2(立體聲)。在 y=0.25 處採樣第一個通道。
- Math gain = 10(而非 5)。原始頻譜值在低音範圍約為 ~0.19。增益為 10 可為著色器提供可用的 ~5.0。
- 不需要 Resample CHOP。 直接通過 AudioSpectrum 的
outlength參數控制輸出大小。
GLSL 頻譜採樣
// Input 0 = time (1x1 rgba32float), Input 1 = spectrum (256x2)
float iTime = texture(sTD2DInputs[0], vec2(0.5)).r;
// Sample multiple points per band and average for stability:
// NOTE: y=0.25 for first channel (stereo texture is 256x2, first row center is 0.25)
float bass = (texture(sTD2DInputs[1], vec2(0.02, 0.25)).r +
texture(sTD2DInputs[1], vec2(0.05, 0.25)).r) / 2.0;
float mid = (texture(sTD2DInputs[1], vec2(0.2, 0.25)).r +
texture(sTD2DInputs[1], vec2(0.35, 0.25)).r) / 2.0;
float hi = (texture(sTD2DInputs[1], vec2(0.6, 0.25)).r +
texture(sTD2DInputs[1], vec2(0.8, 0.25)).r) / 2.0;
完整的構建腳本和著色器代碼請參閱 references/network-patterns.md。
運算符快速參考
| 家族 | 顏色 | Python 類 / MCP 類型 | 後綴 |
|---|---|---|---|
| TOP | 紫色 | noiseTOP, glslTOP, compositeTOP, levelTop, blurTOP, textTOP, nullTOP | TOP |
| CHOP | 綠色 | audiofileinCHOP, audiospectrumCHOP, mathCHOP, lfoCHOP, constantCHOP | CHOP |
| SOP | 藍色 | gridSOP, sphereSOP, transformSOP, noiseSOP | SOP |
| DAT | 白色 | textDAT, tableDAT, scriptDAT, webserverDAT | DAT |
| MAT | 黃色 | phongMAT, pbrMAT, glslMAT, constMAT | MAT |
| COMP | 灰色 | geometryCOMP, containerCOMP, cameraCOMP, lightCOMP, windowCOMP | COMP |
安全說明
- MCP 僅在 localhost 上運行(端口 40404)。無身份驗證——任何本地進程均可發送命令。
td_execute_python以 TD 進程用戶身份,對 TD Python 環境和文件系統擁有不受限制的訪問權限。setup.sh從官方 404zero.com URL 下載 twozero.tox。如有疑慮,請驗證下載內容。- 該技能絕不會向 localhost 之外發送數據。所有 MCP 通信均在本地進行。
參考資料
| 文件 | 內容 |
|---|---|
references/pitfalls.md | 實際會話中積累的寶貴經驗教訓 |
references/operators.md | 所有運算符家族,包含參數和使用案例 |
references/network-patterns.md | 配方:音頻響應、生成式、GLSL、實例化 |
references/mcp-tools.md | 完整的 twozero MCP 工具參數架構 |
references/python-api.md | TD Python:op()、腳本編寫、擴展 |
references/troubleshooting.md | 連接診斷、調試 |
scripts/setup.sh | 自動化設置腳本 |
你不是在編寫代碼。你是在指揮光線。